@assistant-ui/react-generative-ui 0.0.20 → 0.0.22
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.
- package/LICENSE +1 -1
- package/dist/JSONGenerativeUI.client.d.ts.map +1 -1
- package/dist/JSONGenerativeUI.client.js +30 -13
- package/dist/JSONGenerativeUI.client.js.map +1 -1
- package/dist/RadioGroupScope.d.ts +6 -0
- package/dist/RadioGroupScope.d.ts.map +1 -0
- package/dist/RadioGroupScope.js +25 -0
- package/dist/RadioGroupScope.js.map +1 -0
- package/dist/a2ui/BindingContext.d.ts +11 -0
- package/dist/a2ui/BindingContext.d.ts.map +1 -0
- package/dist/a2ui/BindingContext.js +12 -0
- package/dist/a2ui/BindingContext.js.map +1 -0
- package/dist/a2ui/PresentRenderer.d.ts +11 -0
- package/dist/a2ui/PresentRenderer.d.ts.map +1 -0
- package/dist/a2ui/PresentRenderer.js +39 -0
- package/dist/a2ui/PresentRenderer.js.map +1 -0
- package/dist/a2ui/convert.d.ts +6 -0
- package/dist/a2ui/convert.d.ts.map +1 -1
- package/dist/a2ui/convert.js +369 -87
- package/dist/a2ui/convert.js.map +1 -1
- package/dist/a2ui/dataModel.d.ts +9 -0
- package/dist/a2ui/dataModel.d.ts.map +1 -0
- package/dist/a2ui/dataModel.js +44 -0
- package/dist/a2ui/dataModel.js.map +1 -0
- package/dist/a2ui/reducer.d.ts +5 -0
- package/dist/a2ui/reducer.d.ts.map +1 -1
- package/dist/a2ui/reducer.js +3 -3
- package/dist/a2ui/reducer.js.map +1 -1
- package/dist/a2ui/types.d.ts +8 -2
- package/dist/a2ui/types.d.ts.map +1 -1
- package/dist/a2ui/types.js.map +1 -1
- package/dist/a2ui/valueFunctions.d.ts +16 -0
- package/dist/a2ui/valueFunctions.d.ts.map +1 -0
- package/dist/a2ui/valueFunctions.js +332 -0
- package/dist/a2ui/valueFunctions.js.map +1 -0
- package/dist/actionRegistry.d.ts +1 -1
- package/dist/actionRegistry.js.map +1 -1
- package/dist/answeredValues.d.ts +16 -0
- package/dist/answeredValues.d.ts.map +1 -0
- package/dist/answeredValues.js +37 -0
- package/dist/answeredValues.js.map +1 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/fieldReferences.d.ts +9 -0
- package/dist/fieldReferences.d.ts.map +1 -0
- package/dist/fieldReferences.js +53 -0
- package/dist/fieldReferences.js.map +1 -0
- package/dist/generativeUIToJSX.js +3 -3
- package/dist/generativeUIToJSX.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.server.js +2 -2
- package/dist/index.shared.js +2 -2
- package/dist/ir.d.ts +1 -1
- package/dist/ir.js.map +1 -1
- package/dist/renderGenerativeUI.d.ts.map +1 -1
- package/dist/renderGenerativeUI.js +12 -1
- package/dist/renderGenerativeUI.js.map +1 -1
- package/dist/slack/constants.d.ts +2 -0
- package/dist/slack/constants.d.ts.map +1 -1
- package/dist/slack/constants.js +3 -1
- package/dist/slack/constants.js.map +1 -1
- package/dist/slack/decodeBlockAction.d.ts +3 -1
- package/dist/slack/decodeBlockAction.d.ts.map +1 -1
- package/dist/slack/decodeBlockAction.js +58 -7
- package/dist/slack/decodeBlockAction.js.map +1 -1
- package/dist/slack/fromSlackBlocks.d.ts.map +1 -1
- package/dist/slack/fromSlackBlocks.js +20 -3
- package/dist/slack/fromSlackBlocks.js.map +1 -1
- package/dist/slack/toSlackBlocks.d.ts.map +1 -1
- package/dist/slack/toSlackBlocks.js +187 -19
- package/dist/slack/toSlackBlocks.js.map +1 -1
- package/dist/slack/types.d.ts +4 -0
- package/dist/slack/types.d.ts.map +1 -1
- package/dist/teams/constants.d.ts +1 -1
- package/dist/teams/constants.d.ts.map +1 -1
- package/dist/teams/constants.js +1 -1
- package/dist/teams/constants.js.map +1 -1
- package/dist/teams/decodeSubmitData.d.ts +4 -0
- package/dist/teams/decodeSubmitData.d.ts.map +1 -1
- package/dist/teams/decodeSubmitData.js +6 -1
- package/dist/teams/decodeSubmitData.js.map +1 -1
- package/dist/teams/toAdaptiveCard.d.ts +5 -4
- package/dist/teams/toAdaptiveCard.d.ts.map +1 -1
- package/dist/teams/toAdaptiveCard.js +56 -17
- package/dist/teams/toAdaptiveCard.js.map +1 -1
- package/dist/teams/types.d.ts +4 -1
- package/dist/teams/types.d.ts.map +1 -1
- package/dist/vocabulary/alert.d.ts +9 -2
- package/dist/vocabulary/alert.d.ts.map +1 -1
- package/dist/vocabulary/alert.js +116 -19
- package/dist/vocabulary/alert.js.map +1 -1
- package/dist/vocabulary/collectFormValues.d.ts +2 -1
- package/dist/vocabulary/collectFormValues.d.ts.map +1 -1
- package/dist/vocabulary/collectFormValues.js +10 -3
- package/dist/vocabulary/collectFormValues.js.map +1 -1
- package/dist/vocabulary/data.d.ts +22 -5
- package/dist/vocabulary/data.d.ts.map +1 -1
- package/dist/vocabulary/data.js +278 -83
- package/dist/vocabulary/data.js.map +1 -1
- package/dist/vocabulary/dispatch.d.ts +3 -2
- package/dist/vocabulary/dispatch.d.ts.map +1 -1
- package/dist/vocabulary/dispatch.js +33 -4
- package/dist/vocabulary/dispatch.js.map +1 -1
- package/dist/vocabulary/fact.d.ts +8 -1
- package/dist/vocabulary/fact.d.ts.map +1 -1
- package/dist/vocabulary/fact.js +37 -11
- package/dist/vocabulary/fact.js.map +1 -1
- package/dist/vocabulary/form.d.ts.map +1 -1
- package/dist/vocabulary/form.js +3 -3
- package/dist/vocabulary/form.js.map +1 -1
- package/dist/vocabulary/formatValue.d.ts +7 -0
- package/dist/vocabulary/formatValue.d.ts.map +1 -0
- package/dist/vocabulary/formatValue.js +76 -0
- package/dist/vocabulary/formatValue.js.map +1 -0
- package/dist/vocabulary/icon.d.ts +1 -1
- package/dist/vocabulary/interactive.d.ts +137 -8
- package/dist/vocabulary/interactive.d.ts.map +1 -1
- package/dist/vocabulary/interactive.js +404 -103
- package/dist/vocabulary/interactive.js.map +1 -1
- package/dist/vocabulary/layout.d.ts.map +1 -1
- package/dist/vocabulary/layout.js +4 -4
- package/dist/vocabulary/layout.js.map +1 -1
- package/dist/vocabulary/list.js +2 -2
- package/dist/vocabulary/list.js.map +1 -1
- package/dist/vocabulary/text.d.ts +1 -1
- package/package.json +6 -3
- package/src/JSONGenerativeUI.client.tsx +84 -40
- package/src/JSONGenerativeUI.test.tsx +964 -68
- package/src/RadioGroupScope.server.test.tsx +24 -0
- package/src/RadioGroupScope.tsx +34 -0
- package/src/a2ui/BindingContext.ts +26 -0
- package/src/a2ui/PresentRenderer.tsx +83 -0
- package/src/a2ui/convert.test.ts +1982 -145
- package/src/a2ui/convert.ts +677 -137
- package/src/a2ui/dataModel.ts +69 -0
- package/src/a2ui/reducer.test.ts +35 -0
- package/src/a2ui/reducer.ts +5 -4
- package/src/a2ui/types.ts +9 -2
- package/src/a2ui/valueFunctions.test.ts +271 -0
- package/src/a2ui/valueFunctions.ts +523 -0
- package/src/actionRegistry.ts +1 -1
- package/src/answeredValues.test.ts +33 -0
- package/src/answeredValues.tsx +70 -0
- package/src/constants.ts +4 -0
- package/src/fieldReferences.test.ts +66 -0
- package/src/fieldReferences.ts +83 -0
- package/src/generativeUIToJSX.test.ts +18 -0
- package/src/generativeUIToJSX.ts +4 -6
- package/src/index.server.test.ts +106 -0
- package/src/ir.ts +1 -1
- package/src/renderGenerativeUI.test.tsx +14 -5
- package/src/renderGenerativeUI.tsx +30 -1
- package/src/slack/a2uiSlack.test.ts +198 -0
- package/src/slack/constants.ts +3 -0
- package/src/slack/decodeBlockAction.test.ts +98 -0
- package/src/slack/decodeBlockAction.ts +110 -17
- package/src/slack/fromSlackBlocks.test.ts +222 -3
- package/src/slack/fromSlackBlocks.ts +53 -2
- package/src/slack/toSlackBlocks.test.ts +682 -3
- package/src/slack/toSlackBlocks.ts +374 -23
- package/src/slack/types.ts +4 -0
- package/src/teams/constants.ts +1 -1
- package/src/teams/decodeSubmitData.test.ts +33 -0
- package/src/teams/decodeSubmitData.ts +9 -1
- package/src/teams/toAdaptiveCard.test.ts +219 -0
- package/src/teams/toAdaptiveCard.ts +93 -19
- package/src/teams/types.ts +4 -1
- package/src/vocabulary/alert.test.tsx +288 -7
- package/src/vocabulary/alert.tsx +168 -26
- package/src/vocabulary/collectFormValues.test.ts +28 -1
- package/src/vocabulary/collectFormValues.ts +25 -5
- package/src/vocabulary/data.test.tsx +248 -6
- package/src/vocabulary/data.tsx +398 -100
- package/src/vocabulary/dispatch.ts +63 -2
- package/src/vocabulary/fact.test.tsx +67 -0
- package/src/vocabulary/fact.tsx +40 -9
- package/src/vocabulary/form.tsx +7 -2
- package/src/vocabulary/formatValue.test.ts +72 -0
- package/src/vocabulary/formatValue.ts +127 -0
- package/src/vocabulary/index.test.ts +2 -0
- package/src/vocabulary/interactive.dispatch.test.tsx +167 -79
- package/src/vocabulary/interactive.dom.test.tsx +1699 -0
- package/src/vocabulary/interactive.test.tsx +60 -4
- package/src/vocabulary/interactive.tsx +770 -151
- package/src/vocabulary/layout.test.tsx +6 -4
- package/src/vocabulary/layout.tsx +13 -2
- package/src/vocabulary/list.tsx +2 -2
|
@@ -45,53 +45,65 @@ describe("interactiveVocabulary $action dispatch", () => {
|
|
|
45
45
|
it("Button render attaches an onClick that fires $dispatch with the $action payload", () => {
|
|
46
46
|
const handler = vi.fn();
|
|
47
47
|
const registry = createActionRegistry({ purchase: handler });
|
|
48
|
-
const out =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
const out = renderWithHooks(() =>
|
|
49
|
+
interactiveVocabulary.Button.render({
|
|
50
|
+
label: "Buy",
|
|
51
|
+
$status: "done",
|
|
52
|
+
$action: { type: "purchase", itemId: "sku-1" },
|
|
53
|
+
$dispatch: registry.dispatch,
|
|
54
|
+
} as ButtonRenderProps),
|
|
55
|
+
);
|
|
54
56
|
expect(isValidElement(out)).toBe(true);
|
|
55
|
-
const onClick = (out as { props: { onClick: () => void } }).props
|
|
57
|
+
const onClick = (out as { props: { onClick: (e: object) => void } }).props
|
|
58
|
+
.onClick;
|
|
56
59
|
expect(typeof onClick).toBe("function");
|
|
57
|
-
onClick();
|
|
60
|
+
onClick({ currentTarget: {} });
|
|
58
61
|
expect(handler).toHaveBeenCalledWith({
|
|
59
62
|
payload: { type: "purchase", itemId: "sku-1" },
|
|
60
63
|
});
|
|
61
64
|
});
|
|
62
65
|
|
|
63
66
|
it("Button onClick is a no-op when no $dispatch is wired (read-only render)", () => {
|
|
64
|
-
const out =
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
const out = renderWithHooks(() =>
|
|
68
|
+
interactiveVocabulary.Button.render({
|
|
69
|
+
label: "Buy",
|
|
70
|
+
$status: "done",
|
|
71
|
+
$action: { type: "purchase", itemId: "sku-1" },
|
|
72
|
+
} as ButtonRenderProps),
|
|
73
|
+
);
|
|
74
|
+
const onClick = (out as { props: { onClick: (e: object) => void } }).props
|
|
75
|
+
.onClick;
|
|
70
76
|
expect(typeof onClick).toBe("function");
|
|
71
|
-
expect(() => onClick()).not.toThrow();
|
|
77
|
+
expect(() => onClick({ currentTarget: {} })).not.toThrow();
|
|
72
78
|
});
|
|
73
79
|
|
|
74
80
|
it("Button onClick is a no-op when $action is absent", () => {
|
|
75
81
|
const handler = vi.fn();
|
|
76
82
|
const registry = createActionRegistry({ purchase: handler });
|
|
77
|
-
const out =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
const out = renderWithHooks(() =>
|
|
84
|
+
interactiveVocabulary.Button.render({
|
|
85
|
+
label: "Go",
|
|
86
|
+
$status: "done",
|
|
87
|
+
$dispatch: registry.dispatch,
|
|
88
|
+
} as ButtonRenderProps),
|
|
89
|
+
);
|
|
90
|
+
(out as { props: { onClick: (e: object) => void } }).props.onClick({
|
|
91
|
+
currentTarget: {},
|
|
92
|
+
});
|
|
83
93
|
expect(handler).not.toHaveBeenCalled();
|
|
84
94
|
});
|
|
85
95
|
|
|
86
96
|
it("Select onChange merges the selected value into $input and preserves a model-supplied $action.value", () => {
|
|
87
97
|
const handler = vi.fn();
|
|
88
98
|
const registry = createActionRegistry({ pick: handler });
|
|
89
|
-
const out =
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
99
|
+
const out = renderWithHooks(() =>
|
|
100
|
+
interactiveVocabulary.Select.render({
|
|
101
|
+
options: [{ label: "A", value: "a" }],
|
|
102
|
+
$status: "done",
|
|
103
|
+
$action: { type: "pick", value: "model-supplied" },
|
|
104
|
+
$dispatch: registry.dispatch,
|
|
105
|
+
}),
|
|
106
|
+
) as ReactNode;
|
|
95
107
|
const onChange = (
|
|
96
108
|
out as {
|
|
97
109
|
props: { onChange: (e: { currentTarget: { value: string } }) => void };
|
|
@@ -110,11 +122,13 @@ describe("interactiveVocabulary $action dispatch", () => {
|
|
|
110
122
|
it("Input onKeyDown (Enter) merges the entered value into $input", () => {
|
|
111
123
|
const handler = vi.fn();
|
|
112
124
|
const registry = createActionRegistry({ submit: handler });
|
|
113
|
-
const out =
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
125
|
+
const out = renderWithHooks(() =>
|
|
126
|
+
interactiveVocabulary.Input.render({
|
|
127
|
+
$status: "done",
|
|
128
|
+
$action: { type: "submit" },
|
|
129
|
+
$dispatch: registry.dispatch,
|
|
130
|
+
}),
|
|
131
|
+
) as ReactNode;
|
|
118
132
|
const onKeyDown = (
|
|
119
133
|
out as {
|
|
120
134
|
props: {
|
|
@@ -136,15 +150,75 @@ describe("interactiveVocabulary $action dispatch", () => {
|
|
|
136
150
|
});
|
|
137
151
|
});
|
|
138
152
|
|
|
153
|
+
it.each(["text", "password", "number"] as const)(
|
|
154
|
+
"Input renders its %s inputType",
|
|
155
|
+
(inputType) => {
|
|
156
|
+
expect(
|
|
157
|
+
interactiveVocabulary.Input.properties.parse({ inputType }),
|
|
158
|
+
).toEqual({ inputType });
|
|
159
|
+
const out = renderWithHooks(() =>
|
|
160
|
+
interactiveVocabulary.Input.render({
|
|
161
|
+
inputType,
|
|
162
|
+
defaultValue: "12.5",
|
|
163
|
+
$status: "done",
|
|
164
|
+
}),
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
expect(out.type).toBe("input");
|
|
168
|
+
expect(out.props).toMatchObject({
|
|
169
|
+
type: inputType,
|
|
170
|
+
defaultValue: "12.5",
|
|
171
|
+
step: inputType === "number" ? "any" : undefined,
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
it.each(["12.5", ""])(
|
|
177
|
+
"Input with inputType number submits %j as a string",
|
|
178
|
+
(value) => {
|
|
179
|
+
const handler = vi.fn();
|
|
180
|
+
const registry = createActionRegistry({ submit: handler });
|
|
181
|
+
const out = renderWithHooks(() =>
|
|
182
|
+
interactiveVocabulary.Input.render({
|
|
183
|
+
inputType: "number",
|
|
184
|
+
$status: "done",
|
|
185
|
+
$action: { type: "submit" },
|
|
186
|
+
$dispatch: registry.dispatch,
|
|
187
|
+
}),
|
|
188
|
+
) as ReactElement<{
|
|
189
|
+
type: string;
|
|
190
|
+
step: string;
|
|
191
|
+
onKeyDown: (event: {
|
|
192
|
+
key: string;
|
|
193
|
+
nativeEvent: { isComposing: boolean };
|
|
194
|
+
currentTarget: { value: string };
|
|
195
|
+
}) => void;
|
|
196
|
+
}>;
|
|
197
|
+
|
|
198
|
+
expect(out.props.type).toBe("number");
|
|
199
|
+
expect(out.props.step).toBe("any");
|
|
200
|
+
out.props.onKeyDown({
|
|
201
|
+
key: "Enter",
|
|
202
|
+
nativeEvent: { isComposing: false },
|
|
203
|
+
currentTarget: { value },
|
|
204
|
+
});
|
|
205
|
+
expect(handler).toHaveBeenCalledWith({
|
|
206
|
+
payload: { type: "submit", $input: value },
|
|
207
|
+
});
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
|
|
139
211
|
it("Input onKeyDown (Enter) defers to an ancestor form instead of firing its own $action", () => {
|
|
140
212
|
const handler = vi.fn();
|
|
141
213
|
const registry = createActionRegistry({ submit: handler });
|
|
142
|
-
const out =
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
214
|
+
const out = renderWithHooks(() =>
|
|
215
|
+
interactiveVocabulary.Input.render({
|
|
216
|
+
name: "email",
|
|
217
|
+
$status: "done",
|
|
218
|
+
$action: { type: "submit" },
|
|
219
|
+
$dispatch: registry.dispatch,
|
|
220
|
+
}),
|
|
221
|
+
) as ReactNode;
|
|
148
222
|
const onKeyDown = (
|
|
149
223
|
out as {
|
|
150
224
|
props: {
|
|
@@ -179,13 +253,15 @@ describe("interactiveVocabulary $action dispatch", () => {
|
|
|
179
253
|
it("Input multiline (textarea) Ctrl+Enter inside a form calls HTMLFormElement.prototype.requestSubmit instead of firing its own $action", () => {
|
|
180
254
|
const handler = vi.fn();
|
|
181
255
|
const registry = createActionRegistry({ submit: handler });
|
|
182
|
-
const out =
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
256
|
+
const out = renderWithHooks(() =>
|
|
257
|
+
interactiveVocabulary.Input.render({
|
|
258
|
+
multiline: true,
|
|
259
|
+
name: "notes",
|
|
260
|
+
$status: "done",
|
|
261
|
+
$action: { type: "submit" },
|
|
262
|
+
$dispatch: registry.dispatch,
|
|
263
|
+
}),
|
|
264
|
+
) as ReactNode;
|
|
189
265
|
const onKeyDown = (
|
|
190
266
|
out as { props: { onKeyDown: (e: TextareaKeyDownEvent) => void } }
|
|
191
267
|
).props.onKeyDown;
|
|
@@ -225,12 +301,14 @@ describe("interactiveVocabulary $action dispatch", () => {
|
|
|
225
301
|
it("Input multiline (textarea) Ctrl+Enter without a form still fires its own $action", () => {
|
|
226
302
|
const handler = vi.fn();
|
|
227
303
|
const registry = createActionRegistry({ submit: handler });
|
|
228
|
-
const out =
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
304
|
+
const out = renderWithHooks(() =>
|
|
305
|
+
interactiveVocabulary.Input.render({
|
|
306
|
+
multiline: true,
|
|
307
|
+
$status: "done",
|
|
308
|
+
$action: { type: "submit" },
|
|
309
|
+
$dispatch: registry.dispatch,
|
|
310
|
+
}),
|
|
311
|
+
) as ReactNode;
|
|
234
312
|
const onKeyDown = (
|
|
235
313
|
out as { props: { onKeyDown: (e: TextareaKeyDownEvent) => void } }
|
|
236
314
|
).props.onKeyDown;
|
|
@@ -252,13 +330,15 @@ describe("interactiveVocabulary $action dispatch", () => {
|
|
|
252
330
|
it("Button with submit set renders no onClick handler, so it never fires $action on click", () => {
|
|
253
331
|
const handler = vi.fn();
|
|
254
332
|
const registry = createActionRegistry({ purchase: handler });
|
|
255
|
-
const out =
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
333
|
+
const out = renderWithHooks(() =>
|
|
334
|
+
interactiveVocabulary.Button.render({
|
|
335
|
+
label: "Buy",
|
|
336
|
+
submit: true,
|
|
337
|
+
$status: "done",
|
|
338
|
+
$action: { type: "purchase" },
|
|
339
|
+
$dispatch: registry.dispatch,
|
|
340
|
+
} as ButtonRenderProps & { submit: boolean }),
|
|
341
|
+
);
|
|
262
342
|
expect(
|
|
263
343
|
(out as { props: { onClick?: unknown } }).props.onClick,
|
|
264
344
|
).toBeUndefined();
|
|
@@ -268,26 +348,31 @@ describe("interactiveVocabulary $action dispatch", () => {
|
|
|
268
348
|
it("Button without submit keeps firing $action on click", () => {
|
|
269
349
|
const handler = vi.fn();
|
|
270
350
|
const registry = createActionRegistry({ purchase: handler });
|
|
271
|
-
const out =
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
351
|
+
const out = renderWithHooks(() =>
|
|
352
|
+
interactiveVocabulary.Button.render({
|
|
353
|
+
label: "Buy",
|
|
354
|
+
$status: "done",
|
|
355
|
+
$action: { type: "purchase" },
|
|
356
|
+
$dispatch: registry.dispatch,
|
|
357
|
+
} as ButtonRenderProps),
|
|
358
|
+
);
|
|
359
|
+
const onClick = (out as { props: { onClick: (e: object) => void } }).props
|
|
360
|
+
.onClick;
|
|
361
|
+
onClick({ currentTarget: {} });
|
|
279
362
|
expect(handler).toHaveBeenCalledWith({ payload: { type: "purchase" } });
|
|
280
363
|
});
|
|
281
364
|
|
|
282
365
|
it("Checkbox onChange fires $dispatch with the checked boolean as $input", () => {
|
|
283
366
|
const handler = vi.fn();
|
|
284
367
|
const registry = createActionRegistry({ toggle: handler });
|
|
285
|
-
const out =
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
368
|
+
const out = renderWithHooks(() =>
|
|
369
|
+
interactiveVocabulary.Checkbox.render({
|
|
370
|
+
label: "Accept",
|
|
371
|
+
$status: "done",
|
|
372
|
+
$action: { type: "toggle" },
|
|
373
|
+
$dispatch: registry.dispatch,
|
|
374
|
+
}),
|
|
375
|
+
);
|
|
291
376
|
const input = (out.props as { children: ReactElement[] }).children[0];
|
|
292
377
|
const onChange = (
|
|
293
378
|
input as {
|
|
@@ -303,11 +388,13 @@ describe("interactiveVocabulary $action dispatch", () => {
|
|
|
303
388
|
});
|
|
304
389
|
|
|
305
390
|
it("Checkbox onChange is a no-op when no $dispatch is wired", () => {
|
|
306
|
-
const out =
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
391
|
+
const out = renderWithHooks(() =>
|
|
392
|
+
interactiveVocabulary.Checkbox.render({
|
|
393
|
+
label: "Accept",
|
|
394
|
+
$status: "done",
|
|
395
|
+
$action: { type: "toggle" },
|
|
396
|
+
}),
|
|
397
|
+
);
|
|
311
398
|
const input = (out.props as { children: ReactElement[] }).children[0];
|
|
312
399
|
const onChange = (
|
|
313
400
|
input as {
|
|
@@ -336,8 +423,9 @@ describe("interactiveVocabulary $action dispatch", () => {
|
|
|
336
423
|
const options = getRadioOptions(out);
|
|
337
424
|
const secondRadio = (options[1]!.props as { children: ReactElement[] })
|
|
338
425
|
.children[0] as ReactElement;
|
|
339
|
-
const onChange = (secondRadio.props as { onChange: () => void })
|
|
340
|
-
|
|
426
|
+
const onChange = (secondRadio.props as { onChange: (e: object) => void })
|
|
427
|
+
.onChange;
|
|
428
|
+
onChange({ currentTarget: {} });
|
|
341
429
|
expect(handler).toHaveBeenCalledWith({
|
|
342
430
|
payload: { type: "pick", $input: "lg" },
|
|
343
431
|
});
|