@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
@@ -5,7 +5,8 @@ import { usePluginSession } from "../context/PluginSessionContext.js";
5
5
  import { usePluginState } from "../context/PluginStateContext.js";
6
6
  import { useRuntimeContext } from "../context/RuntimeContext.js";
7
7
  import { validationErrorFromUnknown } from "../errors/ValidationError.js";
8
- import { eligibleTargetsByBoardKind, eligibleTargetsForInput, hasBoardTargetInput, hasCardTargetInput, hasInteractionFieldErrors, inputByTarget, inputKeyForTarget, isInputValueReady, interactionArmScope, interactionInputKeys, toggleManyValue, validateInteractionInputDomains, } from "../utils/interaction-inputs.js";
8
+ import { applyInteractionInputDefaults, eligibleTargetsByBoardKind, eligibleTargetsForInput, hasBoardTargetInput, hasCardTargetInput, inputByTarget, inputKeyForTarget, } from "../utils/interaction-inputs.js";
9
+ import { claimInteractionSubmit, clearInteractionRoute, getInteractionDraftReadiness, markInteractionPending, routeInteractionTarget, shouldRouteInteractionPending, } from "../utils/interaction-router.js";
9
10
  export class BoardInteractionConflictError extends Error {
10
11
  constructor({ targetKind, targetId, interactionKeys, }) {
11
12
  super(`Ambiguous ${targetKind} target '${targetId}' matched interactions: ${interactionKeys.join(", ")}. Arm one interaction explicitly or route with a narrower board primitive.`);
@@ -20,9 +21,9 @@ export class BoardInteractionConflictError extends Error {
20
21
  * wiring many `useInteractionById(...)` calls, merging their
21
22
  * eligibility sets, and dispatching clicks to the right handle.
22
23
  *
23
- * Use this alongside (or instead of) `<BoardSurface>` when a game
24
- * keeps multiple board interactions live simultaneously and dispatch
25
- * is target-driven rather than armed-then-clicked. The typical
24
+ * Internal board primitive controller for games that keep multiple board
25
+ * interactions live simultaneously and dispatch by target geometry. The
26
+ * typical
26
27
  * Catan-class shape:
27
28
  *
28
29
  * ```tsx
@@ -32,15 +33,16 @@ export class BoardInteractionConflictError extends Error {
32
33
  * <HexGrid
33
34
  * interactiveVertices={board.targetLayers.vertex()}
34
35
  * interactiveEdges={board.targetLayers.edge()}
35
- * onTileClick={(id) =>
36
- * board.select.space(id, { stealFromPlayerId: null })
37
- * }
36
+ * onTileClick={(id) => board.select.space(id)}
38
37
  * />
39
38
  * );
40
39
  * ```
41
40
  *
41
+ * Mount generated interaction routes with `<Interaction.Switch routes={...}>`
42
+ * for interactions that need more input after a board target is selected.
43
+ *
42
44
  * Eligibility and availability remain authoritative on reducer-projected
43
- * descriptors. Armed follow-up descriptors beat ambient board descriptors.
45
+ * descriptors. Armed routed descriptors beat ambient board descriptors.
44
46
  * Multiple unarmed matches are ambiguous and throw
45
47
  * {@link BoardInteractionConflictError}.
46
48
  */
@@ -50,22 +52,30 @@ export function useBoardInteractions(options = {}) {
50
52
  const { controllingPlayerId } = usePluginSession();
51
53
  const store = useInteractionUiStore();
52
54
  const subscribedArmedBySurface = useStore(store, (state) => state.arms);
55
+ const subscribedDrafts = useStore(store, (state) => state.drafts);
56
+ const pendingInteractionKey = useStore(store, (state) => state.pendingInteractionKey);
53
57
  const armedBySurface = store.getState().arms ?? subscribedArmedBySurface;
58
+ const drafts = store.getState().drafts ?? subscribedDrafts;
54
59
  const descriptors = usePluginState((state) => state.gameplay.availableInteractions ?? []);
55
60
  const targetKindSet = useMemo(() => new Set(targetKinds), [targetKinds]);
56
61
  const armedIds = useMemo(() => new Set(Object.values(armedBySurface)), [armedBySurface]);
57
62
  const interactions = useMemo(() => {
58
- return descriptors.filter((descriptor) => {
59
- if (armedIds.has(descriptor.interactionKey))
60
- return true;
63
+ return descriptors.flatMap((descriptor) => {
64
+ if (armedIds.has(descriptor.interactionKey)) {
65
+ return [
66
+ { ...descriptor, interactionKey: descriptor.interactionKey },
67
+ ];
68
+ }
61
69
  if (hasCardTargetInput(descriptor))
62
- return false;
70
+ return [];
63
71
  if (!hasBoardTargetInput(descriptor))
64
- return false;
65
- if (!targetKinds || targetKinds.length === 0)
66
- return true;
67
- const byKind = eligibleTargetsByBoardKind(descriptor);
68
- return Object.keys(byKind).some((kind) => targetKindSet.has(kind));
72
+ return [];
73
+ const include = !targetKinds || targetKinds.length === 0
74
+ ? true
75
+ : Object.keys(eligibleTargetsByBoardKind(descriptor)).some((kind) => targetKindSet.has(kind));
76
+ return include
77
+ ? [{ ...descriptor, interactionKey: descriptor.interactionKey }]
78
+ : [];
69
79
  });
70
80
  }, [armedIds, descriptors, targetKindSet, targetKinds]);
71
81
  const eligible = useMemo(() => {
@@ -78,7 +88,7 @@ export function useBoardInteractions(options = {}) {
78
88
  for (const descriptor of interactions) {
79
89
  if (!descriptor.available)
80
90
  continue;
81
- const targetsByKind = eligibleTargetsByBoardKind(descriptor);
91
+ const targetsByKind = eligibleTargetsByBoardKind(descriptor, drafts[descriptor.interactionKey] ?? {});
82
92
  for (const [targetKind, ids] of Object.entries(targetsByKind)) {
83
93
  if (!ids)
84
94
  continue;
@@ -88,7 +98,7 @@ export function useBoardInteractions(options = {}) {
88
98
  }
89
99
  }
90
100
  return acc;
91
- }, [interactions]);
101
+ }, [drafts, interactions]);
92
102
  const isEligible = useCallback((targetId, targetKind) => {
93
103
  if (targetKind !== undefined) {
94
104
  return eligible[targetKind].has(targetId);
@@ -99,21 +109,71 @@ export function useBoardInteractions(options = {}) {
99
109
  }
100
110
  return false;
101
111
  }, [eligible]);
102
- const selectByKind = useCallback(async (targetKind, targetId, extraInputs) => {
112
+ const clearPendingInteraction = useCallback((descriptor) => {
113
+ clearInteractionRoute(store, descriptor);
114
+ }, [store]);
115
+ const resolveSelection = useCallback(async (descriptor, inputKey, targetId, extraInputs) => {
103
116
  if (!controllingPlayerId)
104
- return null;
117
+ return { status: "none" };
118
+ const { params, readiness } = routeInteractionTarget(store, descriptor, {
119
+ inputKey,
120
+ value: targetId,
121
+ extraInputs,
122
+ });
123
+ if (shouldRouteInteractionPending(descriptor, readiness)) {
124
+ markInteractionPending(store, descriptor);
125
+ return {
126
+ status: "pending",
127
+ interactionKey: descriptor.interactionKey,
128
+ descriptor,
129
+ missingInputs: readiness.missingInputs,
130
+ };
131
+ }
132
+ const submitParams = applyInteractionInputDefaults(descriptor, params);
133
+ if (!claimInteractionSubmit(store, descriptor)) {
134
+ return {
135
+ status: "submitted",
136
+ interactionKey: descriptor.interactionKey,
137
+ descriptor,
138
+ };
139
+ }
140
+ try {
141
+ await runtime.submitInteraction(controllingPlayerId, descriptor.interactionId, submitParams);
142
+ clearPendingInteraction(descriptor);
143
+ return {
144
+ status: "submitted",
145
+ interactionKey: descriptor.interactionKey,
146
+ descriptor,
147
+ };
148
+ }
149
+ catch (error) {
150
+ throw validationErrorFromUnknown(error);
151
+ }
152
+ finally {
153
+ store.setSubmitting(descriptor.interactionKey, false);
154
+ }
155
+ }, [clearPendingInteraction, controllingPlayerId, runtime, store]);
156
+ const resolveTargetMatches = useCallback((targetKind, targetId, interactionKeys) => {
157
+ const allowedInteractionKeys = interactionKeys
158
+ ? new Set(interactionKeys)
159
+ : null;
105
160
  const matches = interactions.flatMap((descriptor) => {
161
+ if (allowedInteractionKeys &&
162
+ !allowedInteractionKeys.has(descriptor.interactionKey)) {
163
+ return [];
164
+ }
106
165
  if (!descriptor.available)
107
166
  return [];
108
- const inputKey = inputKeyForTarget(descriptor, targetKind, targetId);
167
+ const draft = store.getDraft(descriptor.interactionKey);
168
+ const inputKey = inputKeyForTarget(descriptor, targetKind, targetId, draft);
109
169
  if (!inputKey)
110
170
  return [];
111
- const input = inputByTarget(descriptor, targetKind, targetId);
171
+ const input = inputByTarget(descriptor, targetKind, targetId, draft);
112
172
  if (input?.domain.type === "target" &&
113
173
  !isTargetSelectable(input, store.getDraft(descriptor.interactionKey), targetId)) {
114
174
  return [];
115
175
  }
116
- const targets = eligibleTargetsForInput(descriptor, inputKey);
176
+ const targets = eligibleTargetsForInput(descriptor, inputKey, draft);
117
177
  if (!targets || !targets.includes(targetId))
118
178
  return [];
119
179
  return [
@@ -124,79 +184,90 @@ export function useBoardInteractions(options = {}) {
124
184
  },
125
185
  ];
126
186
  });
187
+ return matches;
188
+ }, [armedIds, interactions, store]);
189
+ const selectByKind = useCallback(async (targetKind, targetId, extraInputs, interactionKeys) => {
190
+ if (!controllingPlayerId)
191
+ return { status: "none" };
192
+ const matches = resolveTargetMatches(targetKind, targetId, interactionKeys);
127
193
  const selected = selectDispatchCandidate(matches, targetKind, targetId);
128
194
  if (selected) {
129
195
  const { descriptor, inputKey } = selected;
130
- const input = inputByTarget(descriptor, targetKind, targetId);
131
- const currentDraft = store.getDraft(descriptor.interactionKey);
132
- const selection = input?.domain.type === "target" ? input.domain.selection : undefined;
133
- const nextTargetValue = selection?.mode === "many"
134
- ? toggleManyValue(currentDraft[inputKey], targetId, selection)
135
- : targetId;
136
- const params = {
137
- ...currentDraft,
138
- ...(extraInputs ?? {}),
139
- [inputKey]: nextTargetValue,
140
- };
141
- for (const [key, value] of Object.entries(extraInputs ?? {})) {
142
- store.setInput(descriptor.interactionKey, key, value);
143
- }
144
- store.setInput(descriptor.interactionKey, inputKey, nextTargetValue);
145
- if (descriptor.commit.mode !== "autoWhenReady" ||
146
- (selection?.mode === "many" && !isDraftReady(descriptor, params))) {
147
- store.arm(interactionArmScope(descriptor), descriptor.interactionKey);
148
- return descriptor.interactionKey;
149
- }
150
- // Fill any remaining required inputs with `null` so the reducer
151
- // bundle can decide whether to reject (missing) or accept
152
- // (optional). This matches the Catan "spaceId + null stealee"
153
- // pattern without forcing callers to memorise each interaction's
154
- // full input shape.
155
- for (const required of interactionInputKeys(descriptor)) {
156
- if (!(required in params))
157
- params[required] = null;
158
- }
159
- try {
160
- await runtime.submitInteraction(controllingPlayerId, descriptor.interactionId, params);
161
- store.clearInput(descriptor.interactionKey);
162
- if (store.getArmed(interactionArmScope(descriptor)) ===
163
- descriptor.interactionKey) {
164
- store.arm(interactionArmScope(descriptor), null);
165
- }
166
- return descriptor.interactionKey;
167
- }
168
- catch (error) {
169
- throw validationErrorFromUnknown(error);
170
- }
196
+ return resolveSelection(descriptor, inputKey, targetId, extraInputs);
171
197
  }
172
- return null;
173
- }, [armedIds, controllingPlayerId, interactions, runtime, store]);
198
+ return { status: "none" };
199
+ }, [controllingPlayerId, resolveSelection, resolveTargetMatches]);
174
200
  const select = useMemo(() => ({
175
201
  edge: (targetId, extraInputs) => selectByKind("edge", targetId, extraInputs),
176
202
  vertex: (targetId, extraInputs) => selectByKind("vertex", targetId, extraInputs),
177
203
  space: (targetId, extraInputs) => selectByKind("space", targetId, extraInputs),
178
204
  tile: (targetId, extraInputs) => selectByKind("tile", targetId, extraInputs),
179
205
  }), [selectByKind]);
206
+ const targetState = useCallback((targetKind, targetId, options = {}) => {
207
+ const enabled = options.enabled !== false;
208
+ const matches = enabled
209
+ ? resolveTargetMatches(targetKind, targetId, options.interactionKeys)
210
+ : [];
211
+ const armed = matches.filter((match) => match.armed);
212
+ const candidates = armed.length > 0 ? armed : matches;
213
+ const selected = candidates[0] ?? null;
214
+ const conflict = candidates.length > 1;
215
+ const pending = selected
216
+ ? pendingInteractionKey === selected.descriptor.interactionKey
217
+ : false;
218
+ const eligible = enabled && !!selected && !conflict;
219
+ return {
220
+ kind: targetKind,
221
+ id: targetId,
222
+ eligible,
223
+ selectable: eligible && !!controllingPlayerId,
224
+ hovered: false,
225
+ interactionKey: selected?.descriptor.interactionKey,
226
+ interactionId: selected?.descriptor.interactionId,
227
+ inputKey: selected?.inputKey,
228
+ pending,
229
+ conflict,
230
+ unavailableReason: candidateUnavailableReason(selected, conflict),
231
+ };
232
+ }, [controllingPlayerId, pendingInteractionKey, resolveTargetMatches]);
180
233
  const targetLayers = useMemo(() => {
181
234
  const createLayer = (targetKind) => (layerOptions = {}) => {
182
- const { enabled, extraInputs, onBeforeSelect, onError } = layerOptions;
235
+ const { enabled, interactionKeys, extraInputs, onBeforeSelect, onError, } = layerOptions;
183
236
  const resolveExtraInputs = (targetId) => typeof extraInputs === "function"
184
237
  ? extraInputs(targetId)
185
238
  : extraInputs;
186
239
  return {
187
240
  enabled,
188
241
  eligible: eligible[targetKind],
242
+ targetState: (targetId) => ({
243
+ ...targetState(targetKind, targetId, { enabled, interactionKeys }),
244
+ select: async () => {
245
+ if (enabled === false)
246
+ return { status: "none" };
247
+ onBeforeSelect?.();
248
+ try {
249
+ return await selectByKind(targetKind, targetId, resolveExtraInputs(targetId), interactionKeys);
250
+ }
251
+ catch (error) {
252
+ onError?.(error);
253
+ if (!onError)
254
+ throw error;
255
+ return { status: "none" };
256
+ }
257
+ },
258
+ }),
189
259
  selectTargetId: async (targetId) => {
190
260
  if (enabled === false)
191
- return;
261
+ return { status: "none" };
192
262
  onBeforeSelect?.();
193
263
  try {
194
- await select[targetKind](targetId, resolveExtraInputs(targetId));
264
+ return await selectByKind(targetKind, targetId, resolveExtraInputs(targetId), interactionKeys);
195
265
  }
196
266
  catch (error) {
197
267
  onError?.(error);
198
268
  if (!onError)
199
269
  throw error;
270
+ return { status: "none" };
200
271
  }
201
272
  },
202
273
  };
@@ -207,8 +278,40 @@ export function useBoardInteractions(options = {}) {
207
278
  space: createLayer("space"),
208
279
  tile: createLayer("tile"),
209
280
  };
210
- }, [eligible, select]);
211
- return useMemo(() => ({ interactions, eligible, isEligible, select, targetLayers }), [interactions, eligible, isEligible, select, targetLayers]);
281
+ }, [eligible, selectByKind, targetState]);
282
+ const pendingInteraction = useMemo(() => {
283
+ if (!pendingInteractionKey)
284
+ return null;
285
+ const descriptor = interactions.find((candidate) => candidate.interactionKey === pendingInteractionKey);
286
+ if (!descriptor)
287
+ return null;
288
+ return {
289
+ interactionKey: descriptor.interactionKey,
290
+ descriptor,
291
+ missingInputs: missingInputsForDraft(descriptor, drafts[descriptor.interactionKey] ?? {}),
292
+ clear: () => clearPendingInteraction(descriptor),
293
+ };
294
+ }, [clearPendingInteraction, drafts, interactions, pendingInteractionKey]);
295
+ const selectTarget = useCallback((descriptor, _targetKind, targetId, inputKey, extraInputs) => resolveSelection(descriptor, inputKey, targetId, extraInputs), [resolveSelection]);
296
+ return useMemo(() => ({
297
+ interactions,
298
+ eligible,
299
+ isEligible,
300
+ pendingInteraction,
301
+ select,
302
+ targetLayers,
303
+ targetState,
304
+ selectTarget,
305
+ }), [
306
+ interactions,
307
+ eligible,
308
+ isEligible,
309
+ pendingInteraction,
310
+ select,
311
+ targetLayers,
312
+ targetState,
313
+ selectTarget,
314
+ ]);
212
315
  }
213
316
  function isTargetSelectable(input, draft, targetId) {
214
317
  const selection = input.domain.type === "target" ? input.domain.selection : undefined;
@@ -221,16 +324,8 @@ function isTargetSelectable(input, draft, targetId) {
221
324
  return true;
222
325
  return selection.max === undefined || current.length < selection.max;
223
326
  }
224
- function isDraftReady(descriptor, draft) {
225
- const fieldErrors = validateInteractionInputDomains(descriptor, draft);
226
- if (hasInteractionFieldErrors(fieldErrors))
227
- return false;
228
- return interactionInputKeys(descriptor).every((key) => {
229
- const input = descriptor.inputs.find((candidate) => candidate.key === key);
230
- const value = draft[key] ??
231
- (input && "defaultValue" in input ? input.defaultValue : undefined);
232
- return input ? isInputValueReady(input, value) : value !== undefined;
233
- });
327
+ function missingInputsForDraft(descriptor, draft) {
328
+ return [...getInteractionDraftReadiness(descriptor, draft).missingInputs];
234
329
  }
235
330
  function selectDispatchCandidate(matches, targetKind, targetId) {
236
331
  if (matches.length === 0)
@@ -246,3 +341,12 @@ function selectDispatchCandidate(matches, targetKind, targetId) {
246
341
  }
247
342
  return candidates[0] ?? null;
248
343
  }
344
+ function candidateUnavailableReason(match, conflict) {
345
+ if (conflict)
346
+ return "conflict";
347
+ if (!match)
348
+ return "unavailable";
349
+ if (!match.descriptor.available)
350
+ return "unavailable";
351
+ return undefined;
352
+ }
@@ -76,7 +76,7 @@ export interface InteractionHandle<Params extends InteractionParamsShape = Inter
76
76
  isReady: boolean;
77
77
  /**
78
78
  * True when this interaction is the currently armed one on its surface.
79
- * Armed interactions are the ones that surfaces like `BoardSurface` use
79
+ * Armed interactions are the ones that board primitives use
80
80
  * to highlight eligible targets and route clicks.
81
81
  */
82
82
  isArmed: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"useInteractionHandle.d.ts","sourceRoot":"","sources":["../../src/hooks/useInteractionHandle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useInteractionHandle.d.ts","sourceRoot":"","sources":["../../src/hooks/useInteractionHandle.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,8 @@ import { usePluginState } from "../context/PluginStateContext.js";
5
5
  import { usePluginSession } from "../context/PluginSessionContext.js";
6
6
  import { useRuntimeContext } from "../context/RuntimeContext.js";
7
7
  import { ValidationError, validationErrorFromUnknown, } from "../errors/ValidationError.js";
8
- import { applyInteractionInputDefaults, hasInteractionFieldErrors, inputByKey, isInputValueReady, interactionArmScope, interactionInputKeys, mergeInteractionFieldErrors, validateInteractionInputDomains, } from "../utils/interaction-inputs.js";
8
+ import { applyInteractionInputDefaults, hasInteractionFieldErrors, interactionArmScope, interactionInputKeys, mergeInteractionFieldErrors, validateInteractionInputDomains, } from "../utils/interaction-inputs.js";
9
+ import { applyInteractionDraftMutation, claimInteractionSubmit, clearInteractionRoute, getInteractionDraftReadiness, } from "../utils/interaction-router.js";
9
10
  /**
10
11
  * Bind an {@link InteractionDescriptor} to submit/validate helpers plus
11
12
  * draft + arming state. Use this from any surface; draft state is shared
@@ -46,17 +47,8 @@ export function useInteractionHandle(descriptor) {
46
47
  ? "submitting"
47
48
  : "open";
48
49
  const isReady = useMemo(() => {
49
- const required = inputKeys;
50
- if (required.length === 0)
51
- return true;
52
- return required.every((key) => {
53
- const input = inputByKey(descriptor, key);
54
- const value = values[key];
55
- return input
56
- ? isInputValueReady(input, value)
57
- : value !== null && value !== undefined;
58
- });
59
- }, [descriptor, values, inputKeys]);
50
+ return getInteractionDraftReadiness(descriptor, values).ready;
51
+ }, [descriptor, values]);
60
52
  const requirePlayer = useCallback(() => {
61
53
  if (!controllingPlayerId) {
62
54
  throw new Error("useInteractionHandle: no controlling player available");
@@ -69,15 +61,14 @@ export function useInteractionHandle(descriptor) {
69
61
  ? "Interaction has already been submitted."
70
62
  : "Interaction submission is already in progress.");
71
63
  }
64
+ if (!claimInteractionSubmit(store, descriptor)) {
65
+ throw new ValidationError("SUBMITTING", "Interaction submission is already in progress.");
66
+ }
72
67
  submittingRef.current = true;
73
- store.setSubmitting(interactionKey, true);
74
68
  const finalParams = applyInteractionInputDefaults(descriptor, params ?? values);
75
69
  try {
76
70
  await runtime.submitInteraction(requirePlayer(), interactionId, finalParams);
77
- store.clearInput(interactionKey);
78
- if (store.getArmed(armScope) === interactionKey) {
79
- store.arm(armScope, null);
80
- }
71
+ clearInteractionRoute(store, descriptor);
81
72
  }
82
73
  catch (error) {
83
74
  throw validationErrorFromUnknown(error);
@@ -93,7 +84,6 @@ export function useInteractionHandle(descriptor) {
93
84
  requirePlayer,
94
85
  interactionId,
95
86
  interactionKey,
96
- armScope,
97
87
  store,
98
88
  status,
99
89
  ]);
@@ -107,13 +97,8 @@ export function useInteractionHandle(descriptor) {
107
97
  const validateDraft = useCallback(() => {
108
98
  const rawDraft = { ...values };
109
99
  const required = inputKeys;
110
- const missing = required.filter((key) => {
111
- const input = inputByKey(descriptor, key);
112
- const value = rawDraft[key];
113
- return input
114
- ? !isInputValueReady(input, value)
115
- : value === null || value === undefined;
116
- });
100
+ const missing = getInteractionDraftReadiness(descriptor, rawDraft)
101
+ .missingInputs;
117
102
  const domainFieldErrors = validateInteractionInputDomains(descriptor, rawDraft);
118
103
  if (!paramsSchema) {
119
104
  if (missing.length > 0 || hasInteractionFieldErrors(domainFieldErrors)) {
@@ -218,8 +203,8 @@ export function useInteractionHandle(descriptor) {
218
203
  validateDraft,
219
204
  ]);
220
205
  const setInput = useCallback((key, value) => {
221
- store.setInput(interactionKey, key, value);
222
- }, [store, interactionKey]);
206
+ applyInteractionDraftMutation(store, descriptor, [{ key, value }]);
207
+ }, [store, descriptor]);
223
208
  const clearInput = useCallback((key) => {
224
209
  store.clearInput(interactionKey, key);
225
210
  }, [store, interactionKey]);
package/dist/index.d.ts CHANGED
@@ -1,30 +1,24 @@
1
- export * from "./reducer.js";
2
- export { createDreamboardUI, type BoardTargetKey, type CardKey, type DreamboardUI, type DreamboardUIRegister, type InteractionInputKey, type InteractionKey, type PhaseKey, type PromptOptionKey, type PromptKey, type RegisteredUI, type TypedBoard, type TypedInteraction, type TypedPhase, type TypedPlayerRoster, type TypedPrompt, type TypedPromptInbox, type TypedZone, type UIContract, type UIContractBucket, type ZoneKey, } from "./ui-contract.js";
1
+ export { createDreamboardUI, type BoardTargetKey, type CardKey, type DreamboardUI, type DreamboardUIRegister, type InteractionInputKey, type InteractionKey, type PhaseKey, type PromptOptionKey, type PromptKey, type RegisteredUI, type TypedBoard, type TypedGame, type TypedInteraction, type TypedPhase, type TypedPlayerRoster, type TypedPrompt, type TypedPromptInbox, type TypedZone, type UIContract, type UIContractBucket, type ZoneKey, } from "./ui-contract.js";
3
2
  export * from "./primitives/index.js";
4
- export { BoardInteractionConflictError, useBoardInteractions, type BoardInteractionsContext, type BoardInteractionsOptions, type BoardTargetLayerFactory, type BoardTargetLayerOptions, } from "./hooks/useBoardInteractions.js";
5
- export { useBoardTopology } from "./hooks/useBoardTopology.js";
6
- export { useCards } from "./hooks/useCards.js";
7
- export { useHexBoard } from "./hooks/useHexBoard.js";
8
- export { useSquareBoard } from "./hooks/useSquareBoard.js";
9
- export { useHandLayout } from "./hooks/useHandLayout.js";
10
- export { useInteractionByKey } from "./hooks/useInteractionByKey.js";
11
- export { useIsMobile } from "./hooks/useIsMobile.js";
12
- export { usePanZoom, calculateViewBox } from "./hooks/usePanZoom.js";
13
- export { usePluginRuntime } from "./hooks/usePluginRuntime.js";
3
+ export type { BoardSelectionResult } from "./hooks/useBoardInteractions.js";
4
+ export { calculateViewBox } from "./hooks/usePanZoom.js";
14
5
  export { toTrackBoardData } from "./helpers/track-board.js";
15
- export { PluginStateProvider, usePluginActions, usePluginState, } from "./context/PluginStateContext.js";
16
- export { RuntimeContext, RuntimeProvider, useRuntimeContext, } from "./context/RuntimeContext.js";
6
+ export { PluginStateProvider } from "./context/PluginStateContext.js";
7
+ export { RuntimeContext, RuntimeProvider } from "./context/RuntimeContext.js";
17
8
  export { type ClientParamSchema, type ClientParamSchemaMap, } from "./context/ClientParamSchemaContext.js";
18
9
  export { ThemeProvider, arcadeTheme, buttonStyle, chipStyle, cssVar, cssVarOr, deriveBoardTheme, getThemePreset, intentForVariant, mergeTheme, motionDuration, playerColor, resolveTheme, studioTheme, surfaceStyle, tabletopTheme, themeToCssVars, useBoardTheme, useTheme, useThemeCssVars, type BoardTheme, type ButtonSize, type ButtonVariant, type ColorRamp, type ComponentTokens, type Elevation, type FoundationColor, type IntentColor, type Motion, type PlayerColor, type Radius, type SemanticColor, type Space, type Theme, type ThemeContextValue, type ThemeMeta, type ThemeOverride, type ThemePresetId, type ThemeProviderProps, type Typography, } from "./theme/index.js";
19
10
  export { normalizeHexBoardInput, normalizeSquareBoardInput, } from "./types/tiled-board.js";
20
- export { InteractionField, InteractionForm, defaultFormInputs, hasDefaultInteractionFormFields, } from "./components/InteractionForm.js";
21
- export type { InteractionFieldProps, InteractionFieldRenderMap, InteractionFieldRenderProps, InteractionFormProps, } from "./components/InteractionForm.js";
11
+ export { InteractionForm, defaultFormInputs, hasDefaultInteractionFormFields, } from "./components/InteractionForm.js";
12
+ export type { InteractionFormProps } from "./components/InteractionForm.js";
22
13
  export * from "./components/index.js";
23
14
  export type * from "./hooks/useHandLayout.js";
24
15
  export type * from "./hooks/usePanZoom.js";
25
16
  export type * from "./hooks/usePluginRuntime.js";
26
- export type { PluginStateSnapshot } from "./types/plugin-state.js";
17
+ export type { InteractionContext, InteractionContextOption, InteractionDescriptor, InputDomainDependencyCase, PluginStateSnapshot, } from "./types/plugin-state.js";
18
+ export { hexColor, isHexColor, parseHexColor, type HexColor, } from "./types/hex-color.js";
27
19
  export type * from "./types/player-state.js";
28
20
  export type * from "./types/runtime-api.js";
21
+ export type { DraftValidation, InteractionHandle, InteractionHandleStatus, InteractionParamsShape, } from "./hooks/useInteractionHandle.js";
22
+ export type { CardCollection, ViewCard, ViewSlotOccupant, } from "@dreamboard/sdk-types";
29
23
  export type { AnyHexBoardInput, AnySquareBoardInput, BoardEdgeIdOf, BoardSpaceIdOf, BoardVertexIdOf, AuthoredHexBoardInput, AuthoredSquareBoardInput, GeneratedHexBoardInput, GeneratedHexSpaceStateLike, GeneratedSquareBoardInput, GeneratedSquareSpaceStateLike, GeneratedTiledEdgeStateLike, GeneratedTiledVertexStateLike, HexBoardInput, NormalizedHexBoard, NormalizedHexEdgeOf, NormalizedHexTileOf, NormalizedHexVertexOf, NormalizedSquareBoard, NormalizedSquareCellOf, NormalizedSquareEdgeOf, NormalizedSquarePieceOf, NormalizedSquareVertexOf, SquareBoardInput, } from "./types/tiled-board.js";
30
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,OAAO,GACb,MAAM,kBAAkB,CAAC;AAC1B,cAAc,uBAAuB,CAAC;AACtC,YAAY,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,aAAa,EACb,WAAW,EACX,WAAW,EACX,SAAS,EACT,MAAM,EACN,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,QAAQ,EACR,eAAe,EACf,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,KAAK,EACV,KAAK,KAAK,EACV,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,UAAU,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,+BAA+B,GAChC,MAAM,iCAAiC,CAAC;AACzC,YAAY,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,cAAc,uBAAuB,CAAC;AACtC,mBAAmB,0BAA0B,CAAC;AAC9C,mBAAmB,uBAAuB,CAAC;AAC3C,mBAAmB,6BAA6B,CAAC;AACjD,YAAY,EACV,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,QAAQ,EACR,UAAU,EACV,aAAa,EACb,KAAK,QAAQ,GACd,MAAM,sBAAsB,CAAC;AAC9B,mBAAmB,yBAAyB,CAAC;AAC7C,mBAAmB,wBAAwB,CAAC;AAC5C,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AACzC,YAAY,EACV,cAAc,EACd,QAAQ,EACR,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,6BAA6B,EAC7B,2BAA2B,EAC3B,6BAA6B,EAC7B,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -1,20 +1,11 @@
1
- export * from "./reducer.js";
2
1
  export { createDreamboardUI, } from "./ui-contract.js";
3
2
  export * from "./primitives/index.js";
4
- export { BoardInteractionConflictError, useBoardInteractions, } from "./hooks/useBoardInteractions.js";
5
- export { useBoardTopology } from "./hooks/useBoardTopology.js";
6
- export { useCards } from "./hooks/useCards.js";
7
- export { useHexBoard } from "./hooks/useHexBoard.js";
8
- export { useSquareBoard } from "./hooks/useSquareBoard.js";
9
- export { useHandLayout } from "./hooks/useHandLayout.js";
10
- export { useInteractionByKey } from "./hooks/useInteractionByKey.js";
11
- export { useIsMobile } from "./hooks/useIsMobile.js";
12
- export { usePanZoom, calculateViewBox } from "./hooks/usePanZoom.js";
13
- export { usePluginRuntime } from "./hooks/usePluginRuntime.js";
3
+ export { calculateViewBox } from "./hooks/usePanZoom.js";
14
4
  export { toTrackBoardData } from "./helpers/track-board.js";
15
- export { PluginStateProvider, usePluginActions, usePluginState, } from "./context/PluginStateContext.js";
16
- export { RuntimeContext, RuntimeProvider, useRuntimeContext, } from "./context/RuntimeContext.js";
5
+ export { PluginStateProvider } from "./context/PluginStateContext.js";
6
+ export { RuntimeContext, RuntimeProvider } from "./context/RuntimeContext.js";
17
7
  export { ThemeProvider, arcadeTheme, buttonStyle, chipStyle, cssVar, cssVarOr, deriveBoardTheme, getThemePreset, intentForVariant, mergeTheme, motionDuration, playerColor, resolveTheme, studioTheme, surfaceStyle, tabletopTheme, themeToCssVars, useBoardTheme, useTheme, useThemeCssVars, } from "./theme/index.js";
18
8
  export { normalizeHexBoardInput, normalizeSquareBoardInput, } from "./types/tiled-board.js";
19
- export { InteractionField, InteractionForm, defaultFormInputs, hasDefaultInteractionFormFields, } from "./components/InteractionForm.js";
9
+ export { InteractionForm, defaultFormInputs, hasDefaultInteractionFormFields, } from "./components/InteractionForm.js";
20
10
  export * from "./components/index.js";
11
+ export { hexColor, isHexColor, parseHexColor, } from "./types/hex-color.js";