@dreamboard-games/ui-sdk 0.0.43 → 0.0.46

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 (172) hide show
  1. package/dist/components/ActionButton.d.ts.map +1 -1
  2. package/dist/components/ActionButton.js +2 -1
  3. package/dist/components/Card.d.ts +1 -1
  4. package/dist/components/Card.d.ts.map +1 -1
  5. package/dist/components/DiceRoller.d.ts +3 -2
  6. package/dist/components/DiceRoller.d.ts.map +1 -1
  7. package/dist/components/DiceRoller.js +4 -13
  8. package/dist/components/ErrorBoundary.d.ts.map +1 -1
  9. package/dist/components/ErrorBoundary.js +94 -2
  10. package/dist/components/InteractionForm.d.ts +1 -1
  11. package/dist/components/InteractionForm.d.ts.map +1 -1
  12. package/dist/components/InteractionForm.js +29 -15
  13. package/dist/components/PrimaryActionButton.d.ts.map +1 -1
  14. package/dist/components/PrimaryActionButton.js +7 -6
  15. package/dist/components/ResourceCounter.d.ts +59 -25
  16. package/dist/components/ResourceCounter.d.ts.map +1 -1
  17. package/dist/components/ResourceCounter.js +106 -115
  18. package/dist/components/Toast.d.ts +13 -6
  19. package/dist/components/Toast.d.ts.map +1 -1
  20. package/dist/components/Toast.js +10 -5
  21. package/dist/components/board/HexGrid.js +6 -6
  22. package/dist/components/board/target-layer.d.ts +18 -2
  23. package/dist/components/board/target-layer.d.ts.map +1 -1
  24. package/dist/components/board/target-layer.js +20 -3
  25. package/dist/components/index.d.ts +3 -4
  26. package/dist/components/index.d.ts.map +1 -1
  27. package/dist/components/index.js +3 -4
  28. package/dist/components/surfaces/InboxSurface.d.ts.map +1 -1
  29. package/dist/components/surfaces/InboxSurface.js +2 -6
  30. package/dist/components/surfaces/PlayerCardsSurface.js +2 -2
  31. package/dist/components/surfaces/internal/CardZoneRoutedForm.d.ts +7 -0
  32. package/dist/components/surfaces/internal/CardZoneRoutedForm.d.ts.map +1 -0
  33. package/dist/components/surfaces/internal/CardZoneRoutedForm.js +9 -0
  34. package/dist/components/surfaces/internal/DefaultInteractionButton.d.ts.map +1 -1
  35. package/dist/components/surfaces/internal/DefaultInteractionButton.js +5 -8
  36. package/dist/components/surfaces/internal/useCardZoneInteractions.d.ts +2 -2
  37. package/dist/components/surfaces/internal/useCardZoneInteractions.d.ts.map +1 -1
  38. package/dist/components/surfaces/internal/useCardZoneInteractions.js +19 -43
  39. package/dist/context/InteractionDraftContext.d.ts +11 -2
  40. package/dist/context/InteractionDraftContext.d.ts.map +1 -1
  41. package/dist/context/InteractionDraftContext.js +41 -4
  42. package/dist/defaults/components.d.ts +0 -5
  43. package/dist/defaults/components.d.ts.map +1 -1
  44. package/dist/defaults/components.js +7 -11
  45. package/dist/hooks/useBoardInteractions.d.ts +35 -12
  46. package/dist/hooks/useBoardInteractions.d.ts.map +1 -1
  47. package/dist/hooks/useBoardInteractions.js +186 -82
  48. package/dist/hooks/useInteractionHandle.d.ts +1 -1
  49. package/dist/hooks/useInteractionHandle.d.ts.map +1 -1
  50. package/dist/hooks/useInteractionHandle.js +12 -27
  51. package/dist/index.d.ts +11 -17
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +5 -14
  54. package/dist/primitives/board.d.ts +53 -3
  55. package/dist/primitives/board.d.ts.map +1 -1
  56. package/dist/primitives/board.js +65 -41
  57. package/dist/primitives/dialog-lifecycle.d.ts +17 -0
  58. package/dist/primitives/dialog-lifecycle.d.ts.map +1 -0
  59. package/dist/primitives/dialog-lifecycle.js +24 -0
  60. package/dist/primitives/dice.d.ts +31 -0
  61. package/dist/primitives/dice.d.ts.map +1 -0
  62. package/dist/primitives/dice.js +33 -0
  63. package/dist/primitives/game.d.ts +55 -0
  64. package/dist/primitives/game.d.ts.map +1 -0
  65. package/dist/primitives/game.js +101 -0
  66. package/dist/primitives/index.d.ts +7 -4
  67. package/dist/primitives/index.d.ts.map +1 -1
  68. package/dist/primitives/index.js +7 -4
  69. package/dist/primitives/interaction-form-binding.d.ts +12 -0
  70. package/dist/primitives/interaction-form-binding.d.ts.map +1 -0
  71. package/dist/primitives/interaction-form-binding.js +14 -0
  72. package/dist/primitives/interaction-submit.d.ts +23 -0
  73. package/dist/primitives/interaction-submit.d.ts.map +1 -0
  74. package/dist/primitives/interaction-submit.js +41 -0
  75. package/dist/primitives/interaction.d.ts +76 -6
  76. package/dist/primitives/interaction.d.ts.map +1 -1
  77. package/dist/primitives/interaction.js +210 -26
  78. package/dist/primitives/player-roster.d.ts +2 -1
  79. package/dist/primitives/player-roster.d.ts.map +1 -1
  80. package/dist/primitives/prompt.d.ts +36 -11
  81. package/dist/primitives/prompt.d.ts.map +1 -1
  82. package/dist/primitives/prompt.js +29 -17
  83. package/dist/primitives/ui.d.ts +9 -0
  84. package/dist/primitives/ui.d.ts.map +1 -0
  85. package/dist/primitives/ui.js +7 -0
  86. package/dist/primitives/zone.d.ts +111 -5
  87. package/dist/primitives/zone.d.ts.map +1 -1
  88. package/dist/primitives/zone.js +349 -9
  89. package/dist/reducer.d.ts +2 -14
  90. package/dist/reducer.d.ts.map +1 -1
  91. package/dist/reducer.js +1 -14
  92. package/dist/runtime/createPluginRuntimeAPI.js +1 -1
  93. package/dist/types/hex-color.d.ts +7 -0
  94. package/dist/types/hex-color.d.ts.map +1 -0
  95. package/dist/types/hex-color.js +13 -0
  96. package/dist/types/player-state.d.ts +28 -14
  97. package/dist/types/player-state.d.ts.map +1 -1
  98. package/dist/types/plugin-state.d.ts +9 -3
  99. package/dist/types/plugin-state.d.ts.map +1 -1
  100. package/dist/ui-contract.d.ts +119 -14
  101. package/dist/ui-contract.d.ts.map +1 -1
  102. package/dist/ui-contract.js +4 -3
  103. package/dist/ui-sdk.d.ts +1637 -1245
  104. package/dist/utils/interaction-inputs.d.ts +8 -5
  105. package/dist/utils/interaction-inputs.d.ts.map +1 -1
  106. package/dist/utils/interaction-inputs.js +82 -14
  107. package/dist/utils/interaction-router.d.ts +31 -0
  108. package/dist/utils/interaction-router.d.ts.map +1 -0
  109. package/dist/utils/interaction-router.js +114 -0
  110. package/package.json +2 -1
  111. package/src/components/ActionButton.tsx +2 -1
  112. package/src/components/Card.tsx +1 -1
  113. package/src/components/DiceRoller.tsx +13 -22
  114. package/src/components/ErrorBoundary.test.tsx +19 -0
  115. package/src/components/ErrorBoundary.tsx +113 -24
  116. package/src/components/InteractionForm.test.tsx +24 -0
  117. package/src/components/InteractionForm.tsx +48 -23
  118. package/src/components/PrimaryActionButton.tsx +19 -5
  119. package/src/components/ResourceCounter.test.tsx +13 -13
  120. package/src/components/ResourceCounter.tsx +238 -244
  121. package/src/components/Toast.tsx +23 -10
  122. package/src/components/__fixtures__/ResourceCounter.fixture.tsx +70 -169
  123. package/src/components/board/HexGrid.tsx +6 -6
  124. package/src/components/board/target-layer.ts +44 -5
  125. package/src/components/index.ts +17 -10
  126. package/src/components/surfaces/InboxSurface.tsx +7 -5
  127. package/src/components/surfaces/PlayerCardsSurface.tsx +6 -6
  128. package/src/components/surfaces/internal/CardZoneRoutedForm.tsx +35 -0
  129. package/src/components/surfaces/internal/DefaultInteractionButton.tsx +17 -7
  130. package/src/components/surfaces/internal/useCardZoneInteractions.ts +25 -67
  131. package/src/context/InteractionDraftContext.tsx +51 -5
  132. package/src/defaults/components.tsx +12 -50
  133. package/src/defaults/defaults.test.tsx +1 -50
  134. package/src/hooks/useBoardInteractions.test.tsx +240 -17
  135. package/src/hooks/useBoardInteractions.ts +330 -105
  136. package/src/hooks/useInteractionHandle.ts +23 -28
  137. package/src/index.test.ts +60 -40
  138. package/src/index.ts +30 -36
  139. package/src/primitives/board.test.tsx +73 -0
  140. package/src/primitives/board.tsx +191 -40
  141. package/src/primitives/dialog-lifecycle.ts +58 -0
  142. package/src/primitives/dice.test.tsx +47 -0
  143. package/src/primitives/dice.tsx +79 -0
  144. package/src/primitives/game.test.tsx +98 -0
  145. package/src/primitives/game.tsx +213 -0
  146. package/src/primitives/index.ts +84 -0
  147. package/src/primitives/interaction-form-binding.tsx +56 -0
  148. package/src/primitives/interaction-submit.ts +90 -0
  149. package/src/primitives/interaction.test.tsx +396 -0
  150. package/src/primitives/interaction.tsx +451 -31
  151. package/src/primitives/player-roster.tsx +2 -1
  152. package/src/primitives/prompt.test.tsx +94 -3
  153. package/src/primitives/prompt.tsx +87 -48
  154. package/src/primitives/ui.test.tsx +131 -0
  155. package/src/primitives/ui.tsx +13 -0
  156. package/src/primitives/zone.test.tsx +305 -0
  157. package/src/primitives/zone.tsx +660 -12
  158. package/src/reducer.ts +7 -20
  159. package/src/runtime/createPluginRuntimeAPI.ts +1 -1
  160. package/src/types/hex-color.ts +20 -0
  161. package/src/types/player-state.ts +36 -18
  162. package/src/types/plugin-state.ts +10 -3
  163. package/src/ui-contract.ts +253 -21
  164. package/src/utils/interaction-inputs.test.ts +400 -0
  165. package/src/utils/interaction-inputs.ts +113 -11
  166. package/src/utils/interaction-router.ts +200 -0
  167. package/type-stubs/manifest-contract.d.ts +42 -0
  168. package/type-stubs/manifest-contract.d.ts.map +1 -0
  169. package/type-stubs/manifest-contract.js +72 -0
  170. package/type-stubs/ui-contract.d.ts +5 -0
  171. package/type-stubs/ui-contract.d.ts.map +1 -0
  172. package/type-stubs/ui-contract.js +1 -0
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { useTheme } from "../../../theme/ThemeProvider.js";
4
4
  import { InteractionForm, hasDefaultInteractionFormFields, } from "../../InteractionForm.js";
5
+ import { submitInteractionDraft, submitInteractionParams, } from "../../../primitives/interaction-submit.js";
5
6
  import { interactionLabel } from "../../../utils/interaction-labels.js";
6
7
  import { ThemedButton } from "../../ThemedButton.js";
7
8
  /**
@@ -49,18 +50,14 @@ export function DefaultInteractionButton({ descriptor, handle, variant: variantO
49
50
  setPending(true);
50
51
  try {
51
52
  if (params !== undefined) {
52
- await handle.submit(params);
53
+ await submitInteractionParams(handle, params, {}, {
54
+ unhandledError: "ignore",
55
+ });
53
56
  }
54
57
  else {
55
- await handle.submitDraft();
58
+ await submitInteractionDraft(handle, {}, { unhandledError: "ignore" });
56
59
  }
57
60
  }
58
- catch {
59
- // Descriptor-level availability is authoritative; submission
60
- // errors flow through the runtime's error channel. We swallow
61
- // here so consumers without an error boundary don't see an
62
- // unhandled rejection warning.
63
- }
64
61
  finally {
65
62
  setPending(false);
66
63
  }
@@ -15,7 +15,7 @@ export declare function useCardZoneInteractions<I extends string = string>(zoneI
15
15
  }): {
16
16
  cards: readonly ViewCard<string, string, Record<string, unknown>>[];
17
17
  contexts: readonly CardZoneInteractionContext<I>[];
18
- followUp: InteractionDescriptor<I> | null;
19
- setFollowUp: import("react").Dispatch<import("react").SetStateAction<InteractionDescriptor<I> | null>>;
18
+ routedInteraction: InteractionDescriptor<I> | null;
19
+ setRoutedInteraction: import("react").Dispatch<import("react").SetStateAction<InteractionDescriptor<I> | null>>;
20
20
  };
21
21
  //# sourceMappingURL=useCardZoneInteractions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCardZoneInteractions.d.ts","sourceRoot":"","sources":["../../../../src/components/surfaces/internal/useCardZoneInteractions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,qBAAqB,EAEtB,MAAM,gCAAgC,CAAC;AAUxC,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,WAAW,0BAA0B,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACnE,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IACnE,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,yBAAyB,CAAC;IAC3C,WAAW,EAAE,sBAAsB,CAAC;IACpC,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC/D,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE;IAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE;;;;;EA0NzC"}
1
+ {"version":3,"file":"useCardZoneInteractions.d.ts","sourceRoot":"","sources":["../../../../src/components/surfaces/internal/useCardZoneInteractions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,qBAAqB,EAEtB,MAAM,gCAAgC,CAAC;AAaxC,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,WAAW,0BAA0B,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACnE,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IACnE,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,yBAAyB,CAAC;IAC3C,WAAW,EAAE,sBAAsB,CAAC;IACpC,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC/D,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE;IAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE;;;;;EA4LzC"}
@@ -4,14 +4,15 @@ import { useInteractionUiStore } from "../../../context/InteractionDraftContext.
4
4
  import { usePluginSession } from "../../../context/PluginSessionContext.js";
5
5
  import { usePluginState } from "../../../context/PluginStateContext.js";
6
6
  import { useRuntimeContext } from "../../../context/RuntimeContext.js";
7
- import { hasInteractionFieldErrors, inputByTarget, interactionArmScope, interactionInputKeys, isInputValueReady, toggleManyValue, validateInteractionInputDomains, } from "../../../utils/interaction-inputs.js";
7
+ import { inputByTarget, interactionInputKeys, toggleManyValue, } from "../../../utils/interaction-inputs.js";
8
+ import { applyInteractionDraftMutation, clearInteractionRoute, getInteractionDraftReadiness, markInteractionPending, shouldRouteInteractionPending, } from "../../../utils/interaction-router.js";
8
9
  export function useCardZoneInteractions(zoneId, _options) {
9
10
  const runtime = useRuntimeContext();
10
11
  const { controllingPlayerId } = usePluginSession();
11
12
  const draftStore = useInteractionUiStore();
12
13
  const draftSnapshot = useStore(draftStore, (state) => state.drafts);
13
14
  const submittingSnapshot = useStore(draftStore, (state) => state.submitting);
14
- const [followUp, setFollowUp] = useState(null);
15
+ const [routedInteraction, setRoutedInteraction] = useState(null);
15
16
  const zone = usePluginState((s) => s.gameplay.zones?.[zoneId]);
16
17
  const simultaneousPhase = usePluginState((s) => s.gameplay.simultaneousPhase);
17
18
  const cards = useMemo(() => {
@@ -39,11 +40,7 @@ export function useCardZoneInteractions(zoneId, _options) {
39
40
  draftStore.setSubmitting(descriptor.interactionKey, true);
40
41
  try {
41
42
  await runtime.submitInteraction(controllingPlayerId, descriptor.interactionId, params);
42
- draftStore.clearInput(descriptor.interactionKey);
43
- const armScope = interactionArmScope(descriptor);
44
- if (draftStore.getArmed(armScope) === descriptor.interactionKey) {
45
- draftStore.arm(armScope, null);
46
- }
43
+ clearInteractionRoute(draftStore, descriptor);
47
44
  }
48
45
  finally {
49
46
  draftStore.setSubmitting(descriptor.interactionKey, false);
@@ -61,28 +58,18 @@ export function useCardZoneInteractions(zoneId, _options) {
61
58
  cardInput.domain.selection?.mode === "many"
62
59
  ? toggleManyValue(currentDraft[cardInputKey], card.id, cardInput.domain.selection)
63
60
  : card.id;
64
- const nextDraft = {
65
- ...currentDraft,
66
- ...(params ?? {}),
67
- [cardInputKey]: nextCardValue,
68
- };
69
- for (const [key, value] of Object.entries(params ?? {})) {
70
- draftStore.setInput(descriptor.interactionKey, key, value);
71
- }
72
- draftStore.setInput(descriptor.interactionKey, cardInputKey, nextCardValue);
61
+ const nextDraft = applyInteractionDraftMutation(draftStore, descriptor, [
62
+ ...Object.entries(params ?? {}).map(([key, value]) => ({ key, value })),
63
+ { key: cardInputKey, value: nextCardValue },
64
+ ]);
65
+ const readiness = getInteractionDraftReadiness(descriptor, nextDraft);
73
66
  if (cardInput.domain.type === "target" &&
74
67
  cardInput.domain.selection?.mode === "many") {
75
- if (descriptor.commit.mode === "autoWhenReady" &&
76
- isDraftReady(descriptor, nextDraft)) {
68
+ if (descriptor.commit.mode === "autoWhenReady" && readiness.ready) {
77
69
  await submitInteractionDraft(descriptor, nextDraft);
78
70
  }
79
71
  return;
80
72
  }
81
- const remaining = descriptor.inputs.filter((input) => {
82
- const value = nextDraft[input.key] ??
83
- ("defaultValue" in input ? input.defaultValue : undefined);
84
- return input.key !== cardInputKey && value === undefined;
85
- });
86
73
  const needsBoardTarget = descriptor.inputs.some((input) => {
87
74
  const value = nextDraft[input.key] ??
88
75
  ("defaultValue" in input ? input.defaultValue : undefined);
@@ -91,18 +78,18 @@ export function useCardZoneInteractions(zoneId, _options) {
91
78
  value === undefined);
92
79
  });
93
80
  if (needsBoardTarget) {
94
- setFollowUp(null);
95
- draftStore.arm(interactionArmScope(descriptor), descriptor.interactionKey);
81
+ setRoutedInteraction(null);
82
+ markInteractionPending(draftStore, descriptor);
83
+ draftStore.setPendingInteraction(null);
96
84
  return;
97
85
  }
98
- if (remaining.length > 0) {
99
- setFollowUp(descriptor);
86
+ if (readiness.missingInputs.length > 0) {
87
+ setRoutedInteraction(descriptor);
100
88
  return;
101
89
  }
102
- if (!isDraftReady(descriptor, nextDraft) ||
103
- descriptor.commit.mode !== "autoWhenReady") {
104
- setFollowUp(null);
105
- draftStore.arm(interactionArmScope(descriptor), descriptor.interactionKey);
90
+ if (shouldRouteInteractionPending(descriptor, readiness)) {
91
+ setRoutedInteraction(null);
92
+ markInteractionPending(draftStore, descriptor);
106
93
  return;
107
94
  }
108
95
  await submitInteractionDraft(descriptor, nextDraft);
@@ -155,7 +142,7 @@ export function useCardZoneInteractions(zoneId, _options) {
155
142
  submittingSnapshot,
156
143
  zone,
157
144
  ]);
158
- return { cards, contexts, followUp, setFollowUp };
145
+ return { cards, contexts, routedInteraction, setRoutedInteraction };
159
146
  }
160
147
  function isCardSelected(descriptor, cardId, draft) {
161
148
  const input = resolveCardInput(descriptor, cardId);
@@ -180,17 +167,6 @@ function isCardInteractionSelectable(descriptor, cardId, draft) {
180
167
  return true;
181
168
  return selection.max === undefined || current.length < selection.max;
182
169
  }
183
- function isDraftReady(descriptor, draft) {
184
- const fieldErrors = validateInteractionInputDomains(descriptor, draft);
185
- if (hasInteractionFieldErrors(fieldErrors))
186
- return false;
187
- return interactionInputKeys(descriptor).every((key) => {
188
- const input = descriptor.inputs.find((candidate) => candidate.key === key);
189
- const value = draft[key] ??
190
- (input && "defaultValue" in input ? input.defaultValue : undefined);
191
- return input ? isInputValueReady(input, value) : value !== undefined;
192
- });
193
- }
194
170
  function resolveCardInput(descriptor, cardId) {
195
171
  const targetInput = inputByTarget(descriptor, "card", cardId);
196
172
  if (targetInput)
@@ -5,9 +5,10 @@ interface DraftState {
5
5
  drafts: Readonly<Record<string, Draft>>;
6
6
  arms: Readonly<Record<string, string>>;
7
7
  submitting: Readonly<Record<string, true>>;
8
+ pendingInteractionKey: string | null;
8
9
  }
9
10
  /**
10
- * Imperative API exposed to `useInteractionHandle` and `<BoardSurface>`.
11
+ * Imperative API exposed to interaction primitives.
11
12
  * Intentionally small; the vanilla zustand store underneath powers
12
13
  * fine-grained subscriptions via {@link useDraft} and {@link useArmed}.
13
14
  */
@@ -24,8 +25,14 @@ export interface InteractionUiStore {
24
25
  getArmed(surface: string): string | null;
25
26
  /** Arm a specific interaction on a surface. Pass `null` to disarm. */
26
27
  arm(surface: string, interactionId: string | null): void;
28
+ /** Which interaction draft currently needs route-owned remaining input UI. */
29
+ getPendingInteraction(): string | null;
30
+ /** Mark the interaction draft currently waiting for remaining input. */
31
+ setPendingInteraction(interactionId: string | null): void;
27
32
  /** True while a local submission is in flight before the host echo arrives. */
28
33
  isSubmitting(interactionId: string): boolean;
34
+ /** Atomically mark a submission in flight. Returns false if already busy. */
35
+ claimSubmitting(interactionId: string): boolean;
29
36
  /** Mark or clear a local submission in flight. */
30
37
  setSubmitting(interactionId: string, submitting: boolean): void;
31
38
  }
@@ -41,7 +48,7 @@ export declare function createInteractionUiStore(): InteractionUiStoreApi;
41
48
  * ```tsx
42
49
  * <InteractionUiProvider>
43
50
  * <PanelSurface />
44
- * <BoardSurface>{(ctx) => <Board ctx={ctx} />}</BoardSurface>
51
+ * <Board.Root>{...}</Board.Root>
45
52
  * </InteractionUiProvider>
46
53
  * ```
47
54
  */
@@ -63,6 +70,8 @@ export declare function useInteractionUiStore(): InteractionUiStoreApi;
63
70
  export declare function useInteractionDraft(interactionId: string): Draft;
64
71
  /** Subscribe to the armed interaction id on a given surface. */
65
72
  export declare function useArmedInteraction(surface: string): string | null;
73
+ /** Subscribe to the interaction draft currently waiting for pending input. */
74
+ export declare function usePendingInteractionKey(): string | null;
66
75
  /** Subscribe to local submitting status for a single interaction key. */
67
76
  export declare function useInteractionSubmitting(interactionId: string): boolean;
68
77
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"InteractionDraftContext.d.ts","sourceRoot":"","sources":["../../src/context/InteractionDraftContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE3E,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG7D,KAAK,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAI/C,UAAU,UAAU;IAClB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACxC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;CAC5C;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,KAAK,CAAC;IACvC,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACnE,oEAAoE;IACpE,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,0CAA0C;IAC1C,QAAQ,IAAI,IAAI,CAAC;IACjB,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACzC,sEAAsE;IACtE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IACzD,+EAA+E;IAC/E,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7C,kDAAkD;IAClD,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;CACjE;AAED,qEAAqE;AACrE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,kBAAkB,CAAC;AAE9E,wBAAgB,wBAAwB,IAAI,qBAAqB,CA0FhE;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B,2CAOA;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,qBAAqB,CAI7D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,KAAK,CAQhE;AAED,gEAAgE;AAChE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGlE;AAED,yEAAyE;AACzE,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAMvE"}
1
+ {"version":3,"file":"InteractionDraftContext.d.ts","sourceRoot":"","sources":["../../src/context/InteractionDraftContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE3E,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG7D,KAAK,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAI/C,UAAU,UAAU;IAClB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACxC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3C,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,KAAK,CAAC;IACvC,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACnE,oEAAoE;IACpE,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,0CAA0C;IAC1C,QAAQ,IAAI,IAAI,CAAC;IACjB,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACzC,sEAAsE;IACtE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IACzD,8EAA8E;IAC9E,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAAC;IACvC,wEAAwE;IACxE,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1D,+EAA+E;IAC/E,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7C,6EAA6E;IAC7E,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;IAChD,kDAAkD;IAClD,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;CACjE;AAED,qEAAqE;AACrE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,kBAAkB,CAAC;AAE9E,wBAAgB,wBAAwB,IAAI,qBAAqB,CAsHhE;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B,2CAOA;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,qBAAqB,CAI7D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,KAAK,CAShE;AAED,gEAAgE;AAChE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGlE;AAED,8EAA8E;AAC9E,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,IAAI,CAOxD;AAED,yEAAyE;AACzE,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAMvE"}
@@ -9,6 +9,7 @@ export function createInteractionUiStore() {
9
9
  drafts: {},
10
10
  arms: {},
11
11
  submitting: {},
12
+ pendingInteractionKey: null,
12
13
  }));
13
14
  const api = {
14
15
  getDraft(interactionId) {
@@ -54,10 +55,16 @@ export function createInteractionUiStore() {
54
55
  store.setState((prev) => {
55
56
  if (Object.keys(prev.drafts).length === 0 &&
56
57
  Object.keys(prev.arms).length === 0 &&
57
- Object.keys(prev.submitting).length === 0) {
58
+ Object.keys(prev.submitting).length === 0 &&
59
+ prev.pendingInteractionKey === null) {
58
60
  return prev;
59
61
  }
60
- return { drafts: {}, arms: {}, submitting: {} };
62
+ return {
63
+ drafts: {},
64
+ arms: {},
65
+ submitting: {},
66
+ pendingInteractionKey: null,
67
+ };
61
68
  });
62
69
  },
63
70
  getArmed(surface) {
@@ -75,9 +82,32 @@ export function createInteractionUiStore() {
75
82
  return { ...prev, arms: { ...prev.arms, [surface]: interactionId } };
76
83
  });
77
84
  },
85
+ getPendingInteraction() {
86
+ return store.getState().pendingInteractionKey;
87
+ },
88
+ setPendingInteraction(interactionId) {
89
+ store.setState((prev) => {
90
+ if (prev.pendingInteractionKey === interactionId)
91
+ return prev;
92
+ return { ...prev, pendingInteractionKey: interactionId };
93
+ });
94
+ },
78
95
  isSubmitting(interactionId) {
79
96
  return store.getState().submitting[interactionId] === true;
80
97
  },
98
+ claimSubmitting(interactionId) {
99
+ let claimed = false;
100
+ store.setState((prev) => {
101
+ if (prev.submitting[interactionId] === true)
102
+ return prev;
103
+ claimed = true;
104
+ return {
105
+ ...prev,
106
+ submitting: { ...prev.submitting, [interactionId]: true },
107
+ };
108
+ });
109
+ return claimed;
110
+ },
81
111
  setSubmitting(interactionId, submitting) {
82
112
  store.setState((prev) => {
83
113
  const current = prev.submitting[interactionId] === true;
@@ -106,7 +136,7 @@ const InteractionUiCtx = createContext(null);
106
136
  * ```tsx
107
137
  * <InteractionUiProvider>
108
138
  * <PanelSurface />
109
- * <BoardSurface>{(ctx) => <Board ctx={ctx} />}</BoardSurface>
139
+ * <Board.Root>{...}</Board.Root>
110
140
  * </InteractionUiProvider>
111
141
  * ```
112
142
  */
@@ -131,13 +161,20 @@ export function useInteractionUiStore() {
131
161
  */
132
162
  export function useInteractionDraft(interactionId) {
133
163
  const store = useInteractionUiStore();
134
- return useStore(store, useShallow((state) => state.drafts[interactionId] ?? EMPTY_DRAFT));
164
+ useStore(store, useShallow((state) => state.drafts[interactionId] ?? EMPTY_DRAFT));
165
+ return store.getDraft(interactionId);
135
166
  }
136
167
  /** Subscribe to the armed interaction id on a given surface. */
137
168
  export function useArmedInteraction(surface) {
138
169
  const store = useInteractionUiStore();
139
170
  return useStore(store, (state) => state.arms[surface] ?? null);
140
171
  }
172
+ /** Subscribe to the interaction draft currently waiting for pending input. */
173
+ export function usePendingInteractionKey() {
174
+ const store = useInteractionUiStore();
175
+ const subscribed = useStore(store, (state) => state.pendingInteractionKey ?? null);
176
+ return store.getPendingInteraction() ?? subscribed;
177
+ }
141
178
  /** Subscribe to local submitting status for a single interaction key. */
142
179
  export function useInteractionSubmitting(interactionId) {
143
180
  const store = useInteractionUiStore();
@@ -15,11 +15,6 @@ export declare const GameLayout: {
15
15
  Sidebar: typeof GameLayoutSidebar;
16
16
  Bottom: typeof GameLayoutBottom;
17
17
  };
18
- export interface DefaultPromptInboxProps extends PrimitiveCommonProps {
19
- empty?: ReactNode;
20
- renderPrompt?: (prompt: InteractionDescriptor) => ReactNode;
21
- }
22
- export declare function DefaultPromptInbox({ empty, renderPrompt, ...props }: DefaultPromptInboxProps): import("react/jsx-runtime").JSX.Element;
23
18
  export interface DefaultInteractionListProps extends PrimitiveCommonProps {
24
19
  empty?: ReactNode;
25
20
  includeUnavailable?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/defaults/components.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/defaults/components.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Interaction, Prompt, PromptInbox, Zone, renderPrimitive, useInteractionPrimitiveContext, useZonePrimitiveContext, } from "../primitives/index.js";
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Interaction, Zone, renderPrimitive, useInteractionPrimitiveContext, useZonePrimitiveContext, } from "../primitives/index.js";
3
3
  import { useSeatInbox } from "../hooks/useSeatInbox.js";
4
4
  function layoutStyle(base, style) {
5
5
  return style ? { ...base, ...style } : base;
@@ -64,13 +64,6 @@ export const GameLayout = {
64
64
  Sidebar: GameLayoutSidebar,
65
65
  Bottom: GameLayoutBottom,
66
66
  };
67
- export function DefaultPromptInbox({ empty = "No available prompts.", renderPrompt, ...props }) {
68
- return (_jsx(PromptInbox.Root, { children: renderPrimitive("section", {
69
- ...props,
70
- "data-dreamboard-default-prompt-inbox": "",
71
- children: (_jsxs(_Fragment, { children: [_jsx(PromptInbox.Empty, { children: empty }), _jsx(PromptInbox.Items, { children: (prompt) => renderPrompt ? (renderPrompt(prompt)) : (_jsxs(Prompt.Root, { interaction: prompt.interactionKey, children: [_jsx(Prompt.Title, {}), _jsx(Prompt.Message, {}), _jsx("div", { "data-dreamboard-default-prompt-options": "", children: _jsx(Prompt.Options, {}) })] }, prompt.interactionKey)) })] })),
72
- }) }));
73
- }
74
67
  export function DefaultInteractionList({ empty = null, includeUnavailable = false, renderInteraction, ...props }) {
75
68
  const inbox = useSeatInbox();
76
69
  const interactions = (inbox.bySurface.panel ?? []).filter((descriptor) => includeUnavailable || descriptor.available);
@@ -110,7 +103,10 @@ function DefaultInteractionField({ input, }) {
110
103
  function DefaultChoiceField({ input }) {
111
104
  const { handle } = useInteractionPrimitiveContext();
112
105
  const value = handle?.draft[input.key] ?? handle?.values[input.key];
113
- return (_jsxs("label", { "data-dreamboard-default-interaction-field": "", children: [input.key, _jsxs("select", { name: input.key, value: value === undefined ? "" : String(value), "data-dreamboard-default-choice-input": "", disabled: !handle?.available, onChange: (event) => handle?.setInput(input.key, event.currentTarget.value), children: [_jsx("option", { value: "" }), (input.domain.choices ?? []).map((choice) => (_jsx("option", { value: choice.value, disabled: choice.disabled, children: choice.label }, choice.value)))] })] }));
106
+ const encodeValue = (candidate) => candidate === null ? "__dreamboard_null_choice__" : String(candidate);
107
+ return (_jsxs("label", { "data-dreamboard-default-interaction-field": "", children: [input.key, _jsxs("select", { name: input.key, value: value === undefined ? "" : encodeValue(value), "data-dreamboard-default-choice-input": "", disabled: !handle?.available, onChange: (event) => handle?.setInput(input.key, event.currentTarget.value === "__dreamboard_null_choice__"
108
+ ? null
109
+ : event.currentTarget.value), children: [_jsx("option", { value: "" }), (input.domain.choices ?? []).map((choice) => (_jsx("option", { value: encodeValue(choice.value), disabled: choice.disabled, children: choice.label }, encodeValue(choice.value))))] })] }));
114
110
  }
115
111
  export function DefaultZone({ zone, empty = null, layout = "row", interaction, input, renderCard, ...props }) {
116
112
  const content = (_jsx(Zone.Root, { zone: zone, children: _jsx(DefaultZoneList, { empty: empty, input: input, layout: layout, renderCard: renderCard, ...props }) }));
@@ -129,7 +125,7 @@ function DefaultZoneList({ empty, input, layout = "row", renderCard, style, ...p
129
125
  data: parseCardData(serialized),
130
126
  };
131
127
  const body = renderCard ? renderCard(card) : card.id;
132
- return (_jsx(Zone.Item, { card: cardId, children: input ? (_jsx(Interaction.CardInput, { input: input, card: cardId, children: body })) : (body) }, cardId));
128
+ return (_jsx(Zone.Item, { card: cardId, children: input ? (_jsx(Interaction.CardInput, { input: input, children: body })) : (body) }, cardId));
133
129
  }) }));
134
130
  }
135
131
  function defaultZoneLayoutStyle(layout) {
@@ -1,14 +1,33 @@
1
- import type { InteractiveTargetLayer } from "../components/board/target-layer.js";
1
+ import type { InteractiveTargetLayer, InteractiveTargetState } from "../components/board/target-layer.js";
2
2
  import type { InteractionDescriptor } from "../types/plugin-state.js";
3
3
  import { type BoardTargetKind } from "../utils/interaction-inputs.js";
4
4
  export type BoardEligibleTargets = Readonly<Record<BoardTargetKind, ReadonlySet<string>>>;
5
5
  export interface BoardTargetLayerOptions {
6
6
  enabled?: boolean;
7
+ interactionKeys?: readonly string[];
7
8
  extraInputs?: Record<string, unknown> | ((targetId: string) => Record<string, unknown>);
8
9
  onBeforeSelect?: () => void;
9
10
  onError?: (error: unknown) => void;
10
11
  }
11
12
  export type BoardTargetLayerFactory = (options?: BoardTargetLayerOptions) => InteractiveTargetLayer;
13
+ export type BoardSelectionResult<I extends string = string> = {
14
+ status: "none";
15
+ } | {
16
+ status: "pending";
17
+ interactionKey: I;
18
+ descriptor: InteractionDescriptor<I>;
19
+ missingInputs: readonly string[];
20
+ } | {
21
+ status: "submitted";
22
+ interactionKey: I;
23
+ descriptor: InteractionDescriptor<I>;
24
+ };
25
+ export interface BoardPendingInteraction<I extends string = string> {
26
+ interactionKey: I;
27
+ descriptor: InteractionDescriptor<I>;
28
+ missingInputs: readonly string[];
29
+ clear(): void;
30
+ }
12
31
  export interface BoardInteractionsOptions {
13
32
  /**
14
33
  * Target kinds the hook pulls interactions from. Defaults to every board
@@ -59,11 +78,12 @@ export interface BoardInteractionsContext<I extends string = string> {
59
78
  * Target-kind dispatch. Routes by board geometry (`edge`, `vertex`,
60
79
  * `space`, `tile`) rather than authored input-key strings.
61
80
  */
81
+ pendingInteraction: BoardPendingInteraction<I> | null;
62
82
  select: {
63
- edge(targetId: string, extraInputs?: Record<string, unknown>): Promise<string | null>;
64
- vertex(targetId: string, extraInputs?: Record<string, unknown>): Promise<string | null>;
65
- space(targetId: string, extraInputs?: Record<string, unknown>): Promise<string | null>;
66
- tile(targetId: string, extraInputs?: Record<string, unknown>): Promise<string | null>;
83
+ edge(targetId: string, extraInputs?: Record<string, unknown>): Promise<BoardSelectionResult<I>>;
84
+ vertex(targetId: string, extraInputs?: Record<string, unknown>): Promise<BoardSelectionResult<I>>;
85
+ space(targetId: string, extraInputs?: Record<string, unknown>): Promise<BoardSelectionResult<I>>;
86
+ tile(targetId: string, extraInputs?: Record<string, unknown>): Promise<BoardSelectionResult<I>>;
67
87
  };
68
88
  /**
69
89
  * Reducer-aware target layers for board primitives. Pass these directly
@@ -76,15 +96,17 @@ export interface BoardInteractionsContext<I extends string = string> {
76
96
  space: BoardTargetLayerFactory;
77
97
  tile: BoardTargetLayerFactory;
78
98
  };
99
+ targetState(targetKind: BoardTargetKind, targetId: string, options?: Pick<BoardTargetLayerOptions, "enabled" | "interactionKeys">): InteractiveTargetState;
100
+ selectTarget(descriptor: InteractionDescriptor<I>, targetKind: BoardTargetKind, targetId: string, inputKey: string, extraInputs?: Record<string, unknown>): Promise<BoardSelectionResult<I>>;
79
101
  }
80
102
  /**
81
103
  * Board-surface orchestration helper that removes the boilerplate of
82
104
  * wiring many `useInteractionById(...)` calls, merging their
83
105
  * eligibility sets, and dispatching clicks to the right handle.
84
106
  *
85
- * Use this alongside (or instead of) `<BoardSurface>` when a game
86
- * keeps multiple board interactions live simultaneously and dispatch
87
- * is target-driven rather than armed-then-clicked. The typical
107
+ * Internal board primitive controller for games that keep multiple board
108
+ * interactions live simultaneously and dispatch by target geometry. The
109
+ * typical
88
110
  * Catan-class shape:
89
111
  *
90
112
  * ```tsx
@@ -94,15 +116,16 @@ export interface BoardInteractionsContext<I extends string = string> {
94
116
  * <HexGrid
95
117
  * interactiveVertices={board.targetLayers.vertex()}
96
118
  * interactiveEdges={board.targetLayers.edge()}
97
- * onTileClick={(id) =>
98
- * board.select.space(id, { stealFromPlayerId: null })
99
- * }
119
+ * onTileClick={(id) => board.select.space(id)}
100
120
  * />
101
121
  * );
102
122
  * ```
103
123
  *
124
+ * Mount generated interaction routes with `<Interaction.Switch routes={...}>`
125
+ * for interactions that need more input after a board target is selected.
126
+ *
104
127
  * Eligibility and availability remain authoritative on reducer-projected
105
- * descriptors. Armed follow-up descriptors beat ambient board descriptors.
128
+ * descriptors. Armed routed descriptors beat ambient board descriptors.
106
129
  * Multiple unarmed matches are ambiguous and throw
107
130
  * {@link BoardInteractionConflictError}.
108
131
  */
@@ -1 +1 @@
1
- {"version":3,"file":"useBoardInteractions.d.ts","sourceRoot":"","sources":["../../src/hooks/useBoardInteractions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useBoardInteractions.d.ts","sourceRoot":"","sources":["../../src/hooks/useBoardInteractions.ts"],"names":[],"mappings":"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"}