@assistant-ui/react-generative-ui 0.0.14 → 0.0.16
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/README.md +48 -0
- package/dist/convert/boundSpec.d.ts +47 -0
- package/dist/convert/boundSpec.d.ts.map +1 -0
- package/dist/convert/boundSpec.js +99 -0
- package/dist/convert/boundSpec.js.map +1 -0
- package/dist/convert/copyBounded.d.ts +28 -0
- package/dist/convert/copyBounded.d.ts.map +1 -0
- package/dist/convert/copyBounded.js +38 -0
- package/dist/convert/copyBounded.js.map +1 -0
- package/dist/convert/isElement.d.ts +6 -0
- package/dist/convert/isElement.d.ts.map +1 -0
- package/dist/convert/isElement.js +6 -0
- package/dist/convert/isElement.js.map +1 -0
- package/dist/convert/takeRun.d.ts +9 -0
- package/dist/convert/takeRun.d.ts.map +1 -0
- package/dist/convert/takeRun.js +20 -0
- package/dist/convert/takeRun.js.map +1 -0
- package/dist/slack/constants.d.ts +1 -26
- package/dist/slack/constants.d.ts.map +1 -1
- package/dist/slack/constants.js +1 -26
- package/dist/slack/constants.js.map +1 -1
- package/dist/slack/fromSlackBlocks.js +6 -10
- package/dist/slack/fromSlackBlocks.js.map +1 -1
- package/dist/slack/toSlackBlocks.d.ts.map +1 -1
- package/dist/slack/toSlackBlocks.js +28 -95
- package/dist/slack/toSlackBlocks.js.map +1 -1
- package/dist/teams/constants.d.ts +1 -28
- package/dist/teams/constants.d.ts.map +1 -1
- package/dist/teams/constants.js +1 -32
- package/dist/teams/constants.js.map +1 -1
- package/dist/teams/toAdaptiveCard.d.ts.map +1 -1
- package/dist/teams/toAdaptiveCard.js +13 -24
- package/dist/teams/toAdaptiveCard.js.map +1 -1
- package/dist/teams/toTeamsAttachments.d.ts.map +1 -1
- package/dist/teams/toTeamsAttachments.js +3 -4
- package/dist/teams/toTeamsAttachments.js.map +1 -1
- package/dist/vocabulary/list.js +4 -2
- package/dist/vocabulary/list.js.map +1 -1
- package/package.json +6 -6
- package/src/convert/boundSpec.test.ts +147 -0
- package/src/{teams → convert}/boundSpec.ts +48 -14
- package/src/convert/copyBounded.test.ts +131 -0
- package/src/convert/copyBounded.ts +38 -0
- package/src/convert/isElement.ts +6 -0
- package/src/convert/takeRun.test.ts +64 -0
- package/src/convert/takeRun.ts +19 -0
- package/src/slack/constants.ts +0 -29
- package/src/slack/fromSlackBlocks.test.ts +105 -7
- package/src/slack/fromSlackBlocks.ts +9 -9
- package/src/slack/toSlackBlocks.test.ts +82 -2
- package/src/slack/toSlackBlocks.ts +68 -164
- package/src/teams/constants.ts +0 -42
- package/src/teams/toAdaptiveCard.test.ts +75 -3
- package/src/teams/toAdaptiveCard.ts +30 -37
- package/src/teams/toTeamsAttachments.ts +2 -8
- package/src/vocabulary/list.test.tsx +35 -9
- package/src/vocabulary/list.tsx +4 -2
- package/dist/teams/boundSpec.d.ts +0 -20
- package/dist/teams/boundSpec.d.ts.map +0 -1
- package/dist/teams/boundSpec.js +0 -67
- package/dist/teams/boundSpec.js.map +0 -1
|
@@ -69,13 +69,17 @@ describe("listVocabulary $action dispatch", () => {
|
|
|
69
69
|
const trigger = rowOut(registry.dispatch).props.children as ReactElement;
|
|
70
70
|
const onClick = (trigger.props as { onClick: (e: unknown) => void })
|
|
71
71
|
.onClick;
|
|
72
|
-
onClick({
|
|
72
|
+
onClick({
|
|
73
|
+
target: { closest: () => trigger },
|
|
74
|
+
currentTarget: trigger,
|
|
75
|
+
});
|
|
73
76
|
expect(handler).toHaveBeenCalledWith({ payload: { type: "open" } });
|
|
74
77
|
});
|
|
75
78
|
|
|
76
79
|
type KeyDownEvent = {
|
|
77
80
|
key: string;
|
|
78
81
|
target: { closest: (selector: string) => unknown };
|
|
82
|
+
currentTarget: unknown;
|
|
79
83
|
preventDefault: () => void;
|
|
80
84
|
};
|
|
81
85
|
|
|
@@ -89,14 +93,17 @@ describe("listVocabulary $action dispatch", () => {
|
|
|
89
93
|
const handler = vi.fn();
|
|
90
94
|
const registry = createActionRegistry({ open: handler });
|
|
91
95
|
const onKeyDown = getOnKeyDown(registry.dispatch);
|
|
96
|
+
const currentTarget = {};
|
|
92
97
|
onKeyDown({
|
|
93
98
|
key: "Enter",
|
|
94
|
-
target: { closest: () =>
|
|
99
|
+
target: { closest: () => currentTarget },
|
|
100
|
+
currentTarget,
|
|
95
101
|
preventDefault: vi.fn(),
|
|
96
102
|
});
|
|
97
103
|
onKeyDown({
|
|
98
104
|
key: " ",
|
|
99
|
-
target: { closest: () =>
|
|
105
|
+
target: { closest: () => currentTarget },
|
|
106
|
+
currentTarget,
|
|
100
107
|
preventDefault: vi.fn(),
|
|
101
108
|
});
|
|
102
109
|
expect(handler).toHaveBeenCalledTimes(2);
|
|
@@ -109,6 +116,7 @@ describe("listVocabulary $action dispatch", () => {
|
|
|
109
116
|
onKeyDown({
|
|
110
117
|
key: "Tab",
|
|
111
118
|
target: { closest: () => null },
|
|
119
|
+
currentTarget: {},
|
|
112
120
|
preventDefault: vi.fn(),
|
|
113
121
|
});
|
|
114
122
|
expect(handler).not.toHaveBeenCalled();
|
|
@@ -124,7 +132,7 @@ describe("listVocabulary $action dispatch", () => {
|
|
|
124
132
|
closest: (selector: string) =>
|
|
125
133
|
selector.includes("button") ? nestedButton : null,
|
|
126
134
|
};
|
|
127
|
-
onClick({ target: nestedButton });
|
|
135
|
+
onClick({ target: nestedButton, currentTarget: {} });
|
|
128
136
|
expect(handler).not.toHaveBeenCalled();
|
|
129
137
|
});
|
|
130
138
|
|
|
@@ -137,7 +145,12 @@ describe("listVocabulary $action dispatch", () => {
|
|
|
137
145
|
selector.includes("input") ? nestedInput : null,
|
|
138
146
|
};
|
|
139
147
|
const preventDefault = vi.fn();
|
|
140
|
-
onKeyDown({
|
|
148
|
+
onKeyDown({
|
|
149
|
+
key: "Enter",
|
|
150
|
+
target: nestedInput,
|
|
151
|
+
currentTarget: {},
|
|
152
|
+
preventDefault,
|
|
153
|
+
});
|
|
141
154
|
expect(handler).not.toHaveBeenCalled();
|
|
142
155
|
expect(preventDefault).not.toHaveBeenCalled();
|
|
143
156
|
});
|
|
@@ -152,7 +165,7 @@ describe("listVocabulary $action dispatch", () => {
|
|
|
152
165
|
closest: (selector: string) =>
|
|
153
166
|
selector.includes('[role="button"]') ? nestedRoleButton : null,
|
|
154
167
|
};
|
|
155
|
-
onClick({ target: nestedRoleButton });
|
|
168
|
+
onClick({ target: nestedRoleButton, currentTarget: {} });
|
|
156
169
|
expect(handler).not.toHaveBeenCalled();
|
|
157
170
|
});
|
|
158
171
|
|
|
@@ -165,7 +178,12 @@ describe("listVocabulary $action dispatch", () => {
|
|
|
165
178
|
selector.includes('[role="button"]') ? nestedRoleButton : null,
|
|
166
179
|
};
|
|
167
180
|
const preventDefault = vi.fn();
|
|
168
|
-
onKeyDown({
|
|
181
|
+
onKeyDown({
|
|
182
|
+
key: "Enter",
|
|
183
|
+
target: nestedRoleButton,
|
|
184
|
+
currentTarget: {},
|
|
185
|
+
preventDefault,
|
|
186
|
+
});
|
|
169
187
|
expect(handler).not.toHaveBeenCalled();
|
|
170
188
|
});
|
|
171
189
|
|
|
@@ -173,8 +191,14 @@ describe("listVocabulary $action dispatch", () => {
|
|
|
173
191
|
const handler = vi.fn();
|
|
174
192
|
const registry = createActionRegistry({ open: handler });
|
|
175
193
|
const onKeyDown = getOnKeyDown(registry.dispatch);
|
|
194
|
+
const currentTarget = {};
|
|
176
195
|
const preventDefault = vi.fn();
|
|
177
|
-
onKeyDown({
|
|
196
|
+
onKeyDown({
|
|
197
|
+
key: " ",
|
|
198
|
+
target: { closest: () => currentTarget },
|
|
199
|
+
currentTarget,
|
|
200
|
+
preventDefault,
|
|
201
|
+
});
|
|
178
202
|
expect(handler).toHaveBeenCalledWith({ payload: { type: "open" } });
|
|
179
203
|
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
180
204
|
});
|
|
@@ -183,10 +207,12 @@ describe("listVocabulary $action dispatch", () => {
|
|
|
183
207
|
const handler = vi.fn();
|
|
184
208
|
const registry = createActionRegistry({ open: handler });
|
|
185
209
|
const onKeyDown = getOnKeyDown(registry.dispatch);
|
|
210
|
+
const currentTarget = {};
|
|
186
211
|
const preventDefault = vi.fn();
|
|
187
212
|
onKeyDown({
|
|
188
213
|
key: "Enter",
|
|
189
|
-
target: { closest: () =>
|
|
214
|
+
target: { closest: () => currentTarget },
|
|
215
|
+
currentTarget,
|
|
190
216
|
preventDefault,
|
|
191
217
|
});
|
|
192
218
|
expect(handler).toHaveBeenCalledWith({ payload: { type: "open" } });
|
package/src/vocabulary/list.tsx
CHANGED
|
@@ -28,13 +28,15 @@ export const listVocabulary = {
|
|
|
28
28
|
data-aui="listview-item-trigger"
|
|
29
29
|
onClick={(event) => {
|
|
30
30
|
const target = event.target as Element;
|
|
31
|
-
|
|
31
|
+
const hit = target.closest(INTERACTIVE_DESCENDANT_SELECTOR);
|
|
32
|
+
if (hit !== null && hit !== event.currentTarget) return;
|
|
32
33
|
fire($action, $dispatch);
|
|
33
34
|
}}
|
|
34
35
|
onKeyDown={(event) => {
|
|
35
36
|
if (event.key !== "Enter" && event.key !== " ") return;
|
|
36
37
|
const target = event.target as Element;
|
|
37
|
-
|
|
38
|
+
const hit = target.closest(INTERACTIVE_DESCENDANT_SELECTOR);
|
|
39
|
+
if (hit !== null && hit !== event.currentTarget) return;
|
|
38
40
|
if (event.key === " ") event.preventDefault();
|
|
39
41
|
fire($action, $dispatch);
|
|
40
42
|
}}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { ClampReason } from "./constants.js";
|
|
2
|
-
//#region src/teams/boundSpec.d.ts
|
|
3
|
-
/**
|
|
4
|
-
* Produces a bounded plain copy of a raw generative-ui spec before it
|
|
5
|
-
* reaches `normalizeSpec`, whose own traversal of the root array or any
|
|
6
|
-
* `children` array walks the full reported length of a hostile proxied
|
|
7
|
-
* array before any per-field cap downstream ever applies. Every array
|
|
8
|
-
* (root, or `children` at any depth) is capped to {@link CHILDREN_CAP}
|
|
9
|
-
* entries via `Array.prototype.slice`, which bounds even a proxy with a
|
|
10
|
-
* fabricated `length`; recursion itself is capped at
|
|
11
|
-
* {@link MAX_TRAVERSAL_DEPTH}. `onClamp` fires once per level that was
|
|
12
|
-
* truncated, receiving the reason for that truncation: `"children"`,
|
|
13
|
-
* `"depth"`, `"budget"`, or `"cycle"`. The walk also spends a total budget of
|
|
14
|
-
* {@link NODE_BUDGET} nodes, so shared references cannot multiply work
|
|
15
|
-
* exponentially, and a node that is its own ancestor is cut to `null`.
|
|
16
|
-
*/
|
|
17
|
-
declare function boundSpec(spec: unknown, onClamp: (reason: ClampReason) => void): unknown;
|
|
18
|
-
//#endregion
|
|
19
|
-
export { boundSpec };
|
|
20
|
-
//# sourceMappingURL=boundSpec.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"boundSpec.d.ts","names":[],"sources":["../../src/teams/boundSpec.ts"],"mappings":";;;;;;;;;;;;;;;;iBA0FgB,UACd,eACA,UAAU,QAAQ"}
|
package/dist/teams/boundSpec.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { NODE_BUDGET } from "./constants.js";
|
|
2
|
-
//#region src/teams/boundSpec.ts
|
|
3
|
-
function boundNode(value, depth, onClamp, state, ancestors) {
|
|
4
|
-
if (state.remaining <= 0) {
|
|
5
|
-
if (!state.exhausted) {
|
|
6
|
-
state.exhausted = true;
|
|
7
|
-
onClamp("budget");
|
|
8
|
-
}
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
state.remaining -= 1;
|
|
12
|
-
if (depth > 64) {
|
|
13
|
-
onClamp("depth");
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
if (Array.isArray(value)) {
|
|
17
|
-
if (ancestors.has(value)) {
|
|
18
|
-
onClamp("cycle");
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
ancestors.add(value);
|
|
22
|
-
const bounded = Array.prototype.slice.call(value, 0, 200);
|
|
23
|
-
if (value.length > 200) onClamp("children");
|
|
24
|
-
const result = bounded.map((item) => boundNode(item, depth + 1, onClamp, state, ancestors));
|
|
25
|
-
ancestors.delete(value);
|
|
26
|
-
return result;
|
|
27
|
-
}
|
|
28
|
-
if (value !== null && typeof value === "object" && "children" in value) {
|
|
29
|
-
if (ancestors.has(value)) {
|
|
30
|
-
onClamp("cycle");
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
ancestors.add(value);
|
|
34
|
-
const record = value;
|
|
35
|
-
const result = {
|
|
36
|
-
...record,
|
|
37
|
-
children: boundNode(record["children"], depth + 1, onClamp, state, ancestors)
|
|
38
|
-
};
|
|
39
|
-
ancestors.delete(value);
|
|
40
|
-
return result;
|
|
41
|
-
}
|
|
42
|
-
return value;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Produces a bounded plain copy of a raw generative-ui spec before it
|
|
46
|
-
* reaches `normalizeSpec`, whose own traversal of the root array or any
|
|
47
|
-
* `children` array walks the full reported length of a hostile proxied
|
|
48
|
-
* array before any per-field cap downstream ever applies. Every array
|
|
49
|
-
* (root, or `children` at any depth) is capped to {@link CHILDREN_CAP}
|
|
50
|
-
* entries via `Array.prototype.slice`, which bounds even a proxy with a
|
|
51
|
-
* fabricated `length`; recursion itself is capped at
|
|
52
|
-
* {@link MAX_TRAVERSAL_DEPTH}. `onClamp` fires once per level that was
|
|
53
|
-
* truncated, receiving the reason for that truncation: `"children"`,
|
|
54
|
-
* `"depth"`, `"budget"`, or `"cycle"`. The walk also spends a total budget of
|
|
55
|
-
* {@link NODE_BUDGET} nodes, so shared references cannot multiply work
|
|
56
|
-
* exponentially, and a node that is its own ancestor is cut to `null`.
|
|
57
|
-
*/
|
|
58
|
-
function boundSpec(spec, onClamp) {
|
|
59
|
-
return boundNode(spec, 0, onClamp, {
|
|
60
|
-
remaining: NODE_BUDGET,
|
|
61
|
-
exhausted: false
|
|
62
|
-
}, /* @__PURE__ */ new WeakSet());
|
|
63
|
-
}
|
|
64
|
-
//#endregion
|
|
65
|
-
export { boundSpec };
|
|
66
|
-
|
|
67
|
-
//# sourceMappingURL=boundSpec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"boundSpec.js","names":[],"sources":["../../src/teams/boundSpec.ts"],"sourcesContent":["import {\n CHILDREN_CAP,\n MAX_TRAVERSAL_DEPTH,\n NODE_BUDGET,\n type ClampReason,\n} from \"./constants\";\n\ninterface BoundState {\n remaining: number;\n exhausted: boolean;\n}\n\nfunction boundNode(\n value: unknown,\n depth: number,\n onClamp: (reason: ClampReason) => void,\n state: BoundState,\n ancestors: WeakSet<object>,\n): unknown {\n if (state.remaining <= 0) {\n if (!state.exhausted) {\n state.exhausted = true;\n onClamp(\"budget\");\n }\n return null;\n }\n state.remaining -= 1;\n if (depth > MAX_TRAVERSAL_DEPTH) {\n onClamp(\"depth\");\n return null;\n }\n if (Array.isArray(value)) {\n if (ancestors.has(value)) {\n onClamp(\"cycle\");\n return null;\n }\n ancestors.add(value);\n const bounded = Array.prototype.slice.call(\n value,\n 0,\n CHILDREN_CAP,\n ) as unknown[];\n if (value.length > CHILDREN_CAP) onClamp(\"children\");\n const result = bounded.map((item) =>\n boundNode(item, depth + 1, onClamp, state, ancestors),\n );\n ancestors.delete(value);\n return result;\n }\n if (\n value !== null &&\n typeof value === \"object\" &&\n \"children\" in (value as Record<string, unknown>)\n ) {\n if (ancestors.has(value)) {\n onClamp(\"cycle\");\n return null;\n }\n ancestors.add(value);\n const record = value as Record<string, unknown>;\n const result = {\n ...record,\n children: boundNode(\n record[\"children\"],\n depth + 1,\n onClamp,\n state,\n ancestors,\n ),\n };\n ancestors.delete(value);\n return result;\n }\n return value;\n}\n\n/**\n * Produces a bounded plain copy of a raw generative-ui spec before it\n * reaches `normalizeSpec`, whose own traversal of the root array or any\n * `children` array walks the full reported length of a hostile proxied\n * array before any per-field cap downstream ever applies. Every array\n * (root, or `children` at any depth) is capped to {@link CHILDREN_CAP}\n * entries via `Array.prototype.slice`, which bounds even a proxy with a\n * fabricated `length`; recursion itself is capped at\n * {@link MAX_TRAVERSAL_DEPTH}. `onClamp` fires once per level that was\n * truncated, receiving the reason for that truncation: `\"children\"`,\n * `\"depth\"`, `\"budget\"`, or `\"cycle\"`. The walk also spends a total budget of\n * {@link NODE_BUDGET} nodes, so shared references cannot multiply work\n * exponentially, and a node that is its own ancestor is cut to `null`.\n */\nexport function boundSpec(\n spec: unknown,\n onClamp: (reason: ClampReason) => void,\n): unknown {\n return boundNode(\n spec,\n 0,\n onClamp,\n { remaining: NODE_BUDGET, exhausted: false },\n new WeakSet(),\n );\n}\n"],"mappings":";;AAYA,SAAS,UACP,OACA,OACA,SACA,OACA,WACS;CACT,IAAI,MAAM,aAAa,GAAG;EACxB,IAAI,CAAC,MAAM,WAAW;GACpB,MAAM,YAAY;GAClB,QAAQ,QAAQ;EAClB;EACA,OAAO;CACT;CACA,MAAM,aAAa;CACnB,IAAI,QAAA,IAA6B;EAC/B,QAAQ,OAAO;EACf,OAAO;CACT;CACA,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,IAAI,UAAU,IAAI,KAAK,GAAG;GACxB,QAAQ,OAAO;GACf,OAAO;EACT;EACA,UAAU,IAAI,KAAK;EACnB,MAAM,UAAU,MAAM,UAAU,MAAM,KACpC,OACA,GAAA,GAEF;EACA,IAAI,MAAM,SAAA,KAAuB,QAAQ,UAAU;EACnD,MAAM,SAAS,QAAQ,KAAK,SAC1B,UAAU,MAAM,QAAQ,GAAG,SAAS,OAAO,SAAS,CACtD;EACA,UAAU,OAAO,KAAK;EACtB,OAAO;CACT;CACA,IACE,UAAU,QACV,OAAO,UAAU,YACjB,cAAe,OACf;EACA,IAAI,UAAU,IAAI,KAAK,GAAG;GACxB,QAAQ,OAAO;GACf,OAAO;EACT;EACA,UAAU,IAAI,KAAK;EACnB,MAAM,SAAS;EACf,MAAM,SAAS;GACb,GAAG;GACH,UAAU,UACR,OAAO,aACP,QAAQ,GACR,SACA,OACA,SACF;EACF;EACA,UAAU,OAAO,KAAK;EACtB,OAAO;CACT;CACA,OAAO;AACT;;;;;;;;;;;;;;;AAgBA,SAAgB,UACd,MACA,SACS;CACT,OAAO,UACL,MACA,GACA,SACA;EAAE,WAAW;EAAa,WAAW;CAAM,mBAC3C,IAAI,QAAQ,CACd;AACF"}
|