@dreamboard-games/ui-sdk 0.0.43 → 0.0.45

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 (166) 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 +1 -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
@@ -0,0 +1,200 @@
1
+ import type { InteractionUiStore } from "../context/InteractionDraftContext.js";
2
+ import type { InteractionDescriptor } from "../types/plugin-state.js";
3
+ import {
4
+ applyInteractionInputDefaults,
5
+ dependentInputKeys,
6
+ hasInteractionFieldErrors,
7
+ inputByKey,
8
+ interactionArmScope,
9
+ interactionInputKeys,
10
+ isInputValueReady,
11
+ resolveInputDomain,
12
+ toggleManyValue,
13
+ validateInteractionInputDomains,
14
+ } from "./interaction-inputs.js";
15
+
16
+ export interface InteractionDraftMutation {
17
+ key: string;
18
+ value: unknown;
19
+ }
20
+
21
+ export interface InteractionDraftReadiness {
22
+ values: Record<string, unknown>;
23
+ missingInputs: readonly string[];
24
+ readyFrontier: readonly string[];
25
+ blockedInputs: readonly string[];
26
+ fieldErrors: Partial<Record<string, readonly string[]>>;
27
+ ready: boolean;
28
+ }
29
+
30
+ export interface RoutedInteractionTarget {
31
+ inputKey: string;
32
+ value: string;
33
+ extraInputs?: Record<string, unknown>;
34
+ }
35
+
36
+ export interface RoutedInteractionTargetResult {
37
+ params: Record<string, unknown>;
38
+ readiness: InteractionDraftReadiness;
39
+ }
40
+
41
+ export function applyInteractionDraftMutation(
42
+ store: Pick<InteractionUiStore, "getDraft" | "setInput" | "clearInput">,
43
+ descriptor: InteractionDescriptor,
44
+ mutations: readonly InteractionDraftMutation[],
45
+ ): Record<string, unknown> {
46
+ const nextDraft: Record<string, unknown> = {
47
+ ...store.getDraft(descriptor.interactionKey),
48
+ };
49
+ const mutatedKeys = new Set(mutations.map((mutation) => mutation.key));
50
+
51
+ for (const { key, value } of mutations) {
52
+ nextDraft[key] = value;
53
+ }
54
+
55
+ for (const { key } of mutations) {
56
+ for (const dependentKey of dependentInputKeys(descriptor, key)) {
57
+ if (mutatedKeys.has(dependentKey)) continue;
58
+ if (shouldClearDependentInput(descriptor, nextDraft, dependentKey)) {
59
+ delete nextDraft[dependentKey];
60
+ }
61
+ }
62
+ }
63
+
64
+ for (const { key, value } of mutations) {
65
+ store.setInput(descriptor.interactionKey, key, value);
66
+ }
67
+ for (const { key } of mutations) {
68
+ for (const dependentKey of dependentInputKeys(descriptor, key)) {
69
+ if (mutatedKeys.has(dependentKey)) continue;
70
+ if (shouldClearDependentInput(descriptor, nextDraft, dependentKey)) {
71
+ store.clearInput(descriptor.interactionKey, dependentKey);
72
+ }
73
+ }
74
+ }
75
+
76
+ return nextDraft;
77
+ }
78
+
79
+ function shouldClearDependentInput(
80
+ descriptor: InteractionDescriptor,
81
+ draft: Readonly<Record<string, unknown>>,
82
+ dependentKey: string,
83
+ ): boolean {
84
+ const input = inputByKey(descriptor, dependentKey);
85
+ if (!input) return true;
86
+ const value = draft[dependentKey];
87
+ if (!isInputValueReady(resolveInputDomain(input, draft), value)) return true;
88
+ const errors = validateInteractionInputDomains(descriptor, draft);
89
+ return (errors[dependentKey]?.length ?? 0) > 0;
90
+ }
91
+
92
+ export function getInteractionDraftReadiness(
93
+ descriptor: InteractionDescriptor,
94
+ draft: Readonly<Record<string, unknown>>,
95
+ ): InteractionDraftReadiness {
96
+ const values = applyInteractionInputDefaults<Record<string, unknown>>(
97
+ descriptor,
98
+ draft,
99
+ ) as Record<string, unknown>;
100
+ const missingInputs = interactionInputKeys(descriptor).filter((key) => {
101
+ const input = inputByKey(descriptor, key);
102
+ const value = values[key];
103
+ return input
104
+ ? !isInputValueReady(resolveInputDomain(input, values), value)
105
+ : value === null || value === undefined;
106
+ });
107
+ const missingInputSet = new Set(missingInputs);
108
+ const readyFrontier = missingInputs.filter((key) => {
109
+ const input = inputByKey(descriptor, key);
110
+ if (!input) return true;
111
+ return (input.domain.dependsOn ?? []).every((dependencyKey) => {
112
+ if (missingInputSet.has(dependencyKey)) return false;
113
+ const dependency = inputByKey(descriptor, dependencyKey);
114
+ if (!dependency) return values[dependencyKey] !== undefined;
115
+ return isInputValueReady(
116
+ resolveInputDomain(dependency, values),
117
+ values[dependencyKey],
118
+ );
119
+ });
120
+ });
121
+ const fieldErrors = validateInteractionInputDomains(descriptor, values);
122
+ return {
123
+ values,
124
+ missingInputs,
125
+ readyFrontier,
126
+ blockedInputs: missingInputs.filter((key) => !readyFrontier.includes(key)),
127
+ fieldErrors,
128
+ ready:
129
+ missingInputs.length === 0 && !hasInteractionFieldErrors(fieldErrors),
130
+ };
131
+ }
132
+
133
+ export function routeInteractionTarget(
134
+ store: Pick<InteractionUiStore, "getDraft" | "setInput" | "clearInput">,
135
+ descriptor: InteractionDescriptor,
136
+ target: RoutedInteractionTarget,
137
+ ): RoutedInteractionTargetResult {
138
+ const input = inputByKey(descriptor, target.inputKey);
139
+ const currentDraft = store.getDraft(descriptor.interactionKey);
140
+ const selection =
141
+ input?.domain.type === "target" ? input.domain.selection : undefined;
142
+ const targetValue =
143
+ selection?.mode === "many"
144
+ ? toggleManyValue(currentDraft[target.inputKey], target.value, selection)
145
+ : target.value;
146
+ const params = applyInteractionDraftMutation(store, descriptor, [
147
+ ...Object.entries(target.extraInputs ?? {}).map(([key, value]) => ({
148
+ key,
149
+ value,
150
+ })),
151
+ { key: target.inputKey, value: targetValue },
152
+ ]);
153
+ return {
154
+ params,
155
+ readiness: getInteractionDraftReadiness(descriptor, params),
156
+ };
157
+ }
158
+
159
+ export function shouldRouteInteractionPending(
160
+ descriptor: InteractionDescriptor,
161
+ readiness: Pick<InteractionDraftReadiness, "ready">,
162
+ ): boolean {
163
+ return descriptor.commit.mode !== "autoWhenReady" || !readiness.ready;
164
+ }
165
+
166
+ export function markInteractionPending(
167
+ store: Pick<InteractionUiStore, "arm" | "setPendingInteraction">,
168
+ descriptor: InteractionDescriptor,
169
+ ): void {
170
+ store.arm(interactionArmScope(descriptor), descriptor.interactionKey);
171
+ store.setPendingInteraction(descriptor.interactionKey);
172
+ }
173
+
174
+ export function clearInteractionRoute(
175
+ store: Pick<
176
+ InteractionUiStore,
177
+ | "clearInput"
178
+ | "getArmed"
179
+ | "arm"
180
+ | "getPendingInteraction"
181
+ | "setPendingInteraction"
182
+ >,
183
+ descriptor: InteractionDescriptor,
184
+ ): void {
185
+ const armScope = interactionArmScope(descriptor);
186
+ store.clearInput(descriptor.interactionKey);
187
+ if (store.getArmed(armScope) === descriptor.interactionKey) {
188
+ store.arm(armScope, null);
189
+ }
190
+ if (store.getPendingInteraction() === descriptor.interactionKey) {
191
+ store.setPendingInteraction(null);
192
+ }
193
+ }
194
+
195
+ export function claimInteractionSubmit(
196
+ store: Pick<InteractionUiStore, "claimSubmitting">,
197
+ descriptor: InteractionDescriptor,
198
+ ): boolean {
199
+ return store.claimSubmitting(descriptor.interactionKey);
200
+ }