@a2ui-sdk/react 0.2.0 → 0.2.2
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 +153 -18
- package/dist/0.8/components/layout/ColumnComponent.js +33 -40
- package/dist/0.8/components/layout/ListComponent.js +31 -38
- package/dist/0.8/components/layout/RowComponent.js +33 -40
- package/dist/0.8/components/layout/TemplateRenderer.d.ts +22 -0
- package/dist/0.8/components/layout/TemplateRenderer.js +30 -0
- package/dist/0.8/contexts/ActionContext.d.ts +1 -1
- package/dist/0.8/contexts/ActionContext.js +21 -17
- package/dist/0.8/contexts/ScopeContext.d.ts +53 -0
- package/dist/0.8/contexts/ScopeContext.js +22 -0
- package/dist/0.8/hooks/useDataBinding.js +22 -18
- package/dist/0.8/hooks/useDispatchAction.d.ts +1 -0
- package/dist/0.8/hooks/useDispatchAction.js +12 -5
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -15,7 +15,129 @@ npm install @a2ui-sdk/react
|
|
|
15
15
|
|
|
16
16
|
## Usage
|
|
17
17
|
|
|
18
|
-
###
|
|
18
|
+
### v0.8
|
|
19
|
+
|
|
20
|
+
#### Basic Usage
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import {
|
|
24
|
+
A2UIProvider,
|
|
25
|
+
A2UIRenderer,
|
|
26
|
+
type A2UIMessage,
|
|
27
|
+
type A2UIAction,
|
|
28
|
+
} from '@a2ui-sdk/react/0.8'
|
|
29
|
+
|
|
30
|
+
function App() {
|
|
31
|
+
const messages: A2UIMessage[] = [
|
|
32
|
+
// A2UI messages from your backend
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
const handleAction = (action: A2UIAction) => {
|
|
36
|
+
console.log('Action received:', action)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<A2UIProvider messages={messages}>
|
|
41
|
+
<A2UIRenderer onAction={handleAction} />
|
|
42
|
+
</A2UIProvider>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### Custom Components
|
|
48
|
+
|
|
49
|
+
You can override default components or add new custom components via the `catalog` prop on `A2UIProvider`. Use `standardCatalog` as a base and extend it with your custom components.
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import {
|
|
53
|
+
A2UIProvider,
|
|
54
|
+
A2UIRenderer,
|
|
55
|
+
standardCatalog,
|
|
56
|
+
type A2UIMessage,
|
|
57
|
+
type A2UIAction,
|
|
58
|
+
} from '@a2ui-sdk/react/0.8'
|
|
59
|
+
|
|
60
|
+
// Extend standard catalog with custom components
|
|
61
|
+
const customCatalog = {
|
|
62
|
+
...standardCatalog,
|
|
63
|
+
components: {
|
|
64
|
+
...standardCatalog.components,
|
|
65
|
+
// Override default Button component with a custom one
|
|
66
|
+
Button: CustomButtonComponent,
|
|
67
|
+
// Add a new custom Switch component
|
|
68
|
+
Switch: CustomSwitchComponent,
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function App() {
|
|
73
|
+
return (
|
|
74
|
+
<A2UIProvider catalog={customCatalog} messages={messages}>
|
|
75
|
+
<A2UIRenderer onAction={handleAction} />
|
|
76
|
+
</A2UIProvider>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Implementing a custom button component with action dispatch:
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import {
|
|
85
|
+
useDispatchAction,
|
|
86
|
+
ComponentRenderer,
|
|
87
|
+
type ButtonComponentProps,
|
|
88
|
+
} from '@a2ui-sdk/react/0.8'
|
|
89
|
+
|
|
90
|
+
export function CustomButtonComponent({
|
|
91
|
+
surfaceId,
|
|
92
|
+
componentId,
|
|
93
|
+
child,
|
|
94
|
+
action,
|
|
95
|
+
}: ButtonComponentProps) {
|
|
96
|
+
const dispatchAction = useDispatchAction()
|
|
97
|
+
|
|
98
|
+
const handleClick = () => {
|
|
99
|
+
if (action) {
|
|
100
|
+
dispatchAction(surfaceId, componentId, action)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<button onClick={handleClick}>
|
|
106
|
+
<ComponentRenderer surfaceId={surfaceId} componentId={child} />
|
|
107
|
+
</button>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Implementing a custom switch component with data binding:
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import { useDataBinding, useFormBinding } from '@a2ui-sdk/react/0.8'
|
|
116
|
+
|
|
117
|
+
export function CustomSwitchComponent({
|
|
118
|
+
surfaceId,
|
|
119
|
+
componentId,
|
|
120
|
+
label,
|
|
121
|
+
value,
|
|
122
|
+
}: SwitchComponentProps) {
|
|
123
|
+
const labelText = useDataBinding<string>(surfaceId, label, '')
|
|
124
|
+
const [checked, setChecked] = useFormBinding<boolean>(surfaceId, value, false)
|
|
125
|
+
|
|
126
|
+
const handleChange = (newChecked: boolean) => {
|
|
127
|
+
setChecked(newChecked)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<Switch checked={checked} onChange={handleChange}>
|
|
132
|
+
{labelText}
|
|
133
|
+
</Switch>
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### v0.9
|
|
139
|
+
|
|
140
|
+
#### Basic Usage
|
|
19
141
|
|
|
20
142
|
```tsx
|
|
21
143
|
import {
|
|
@@ -35,36 +157,40 @@ function App() {
|
|
|
35
157
|
}
|
|
36
158
|
|
|
37
159
|
return (
|
|
38
|
-
<A2UIProvider messages={messages}
|
|
39
|
-
<A2UIRenderer />
|
|
160
|
+
<A2UIProvider messages={messages}>
|
|
161
|
+
<A2UIRenderer onAction={handleAction} />
|
|
40
162
|
</A2UIProvider>
|
|
41
163
|
)
|
|
42
164
|
}
|
|
43
165
|
```
|
|
44
166
|
|
|
45
|
-
|
|
167
|
+
#### Custom Components
|
|
46
168
|
|
|
47
|
-
|
|
169
|
+
Override or extend the standard catalog the same way as in v0.8:
|
|
48
170
|
|
|
49
171
|
```tsx
|
|
50
|
-
import {
|
|
172
|
+
import {
|
|
173
|
+
A2UIProvider,
|
|
174
|
+
A2UIRenderer,
|
|
175
|
+
standardCatalog,
|
|
176
|
+
type A2UIMessage,
|
|
177
|
+
type A2UIAction,
|
|
178
|
+
} from '@a2ui-sdk/react/0.9'
|
|
51
179
|
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
180
|
+
// Extend standard catalog with custom components
|
|
181
|
+
const customCatalog = {
|
|
182
|
+
...standardCatalog,
|
|
183
|
+
components: {
|
|
184
|
+
...standardCatalog.components,
|
|
185
|
+
// Override default components or add new ones
|
|
186
|
+
Button: CustomButtonComponent,
|
|
187
|
+
},
|
|
56
188
|
}
|
|
57
189
|
|
|
58
190
|
function App() {
|
|
59
|
-
const components = new Map([['Text', MyCustomText]])
|
|
60
|
-
|
|
61
191
|
return (
|
|
62
|
-
<A2UIProvider
|
|
63
|
-
|
|
64
|
-
onAction={handleAction}
|
|
65
|
-
components={components}
|
|
66
|
-
>
|
|
67
|
-
<A2UIRenderer />
|
|
192
|
+
<A2UIProvider catalog={customCatalog} messages={messages}>
|
|
193
|
+
<A2UIRenderer onAction={handleAction} />
|
|
68
194
|
</A2UIProvider>
|
|
69
195
|
)
|
|
70
196
|
}
|
|
@@ -81,6 +207,9 @@ import {
|
|
|
81
207
|
A2UIRenderer,
|
|
82
208
|
ComponentRenderer,
|
|
83
209
|
|
|
210
|
+
// Catalog
|
|
211
|
+
standardCatalog,
|
|
212
|
+
|
|
84
213
|
// Hooks
|
|
85
214
|
useDispatchAction,
|
|
86
215
|
useDataBinding,
|
|
@@ -124,12 +253,17 @@ import {
|
|
|
124
253
|
A2UIRenderer,
|
|
125
254
|
ComponentRenderer,
|
|
126
255
|
|
|
256
|
+
// Catalog
|
|
257
|
+
standardCatalog,
|
|
258
|
+
|
|
127
259
|
// Hooks
|
|
128
260
|
useDispatchAction,
|
|
129
261
|
useDataBinding,
|
|
130
262
|
useFormBinding,
|
|
131
263
|
useSurfaceContext,
|
|
132
264
|
useDataModelContext,
|
|
265
|
+
useScope,
|
|
266
|
+
useScopeBasePath,
|
|
133
267
|
|
|
134
268
|
// Types
|
|
135
269
|
type A2UIMessage,
|
|
@@ -139,6 +273,7 @@ import {
|
|
|
139
273
|
type ComponentsMap,
|
|
140
274
|
type Action,
|
|
141
275
|
type ValueSource,
|
|
276
|
+
type ScopeValue,
|
|
142
277
|
} from '@a2ui-sdk/react/0.8'
|
|
143
278
|
```
|
|
144
279
|
|
|
@@ -1,58 +1,51 @@
|
|
|
1
1
|
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
-
import { memo as
|
|
3
|
-
import { useDataModel as
|
|
4
|
-
import { cn as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
2
|
+
import { memo as a } from "react";
|
|
3
|
+
import { useDataModel as c } from "../../hooks/useDataBinding.js";
|
|
4
|
+
import { cn as l } from "../../../lib/utils.js";
|
|
5
|
+
import { ComponentRenderer as f } from "../ComponentRenderer.js";
|
|
6
|
+
import { TemplateRenderer as u } from "./TemplateRenderer.js";
|
|
7
|
+
import { useScope as d } from "../../contexts/ScopeContext.js";
|
|
8
|
+
const y = {
|
|
8
9
|
start: "justify-start",
|
|
9
10
|
center: "justify-center",
|
|
10
11
|
end: "justify-end",
|
|
11
12
|
spaceBetween: "justify-between",
|
|
12
13
|
spaceAround: "justify-around",
|
|
13
14
|
spaceEvenly: "justify-evenly"
|
|
14
|
-
},
|
|
15
|
+
}, j = {
|
|
15
16
|
start: "items-start",
|
|
16
17
|
center: "items-center",
|
|
17
18
|
end: "items-end",
|
|
18
19
|
stretch: "items-stretch"
|
|
19
|
-
},
|
|
20
|
-
surfaceId:
|
|
20
|
+
}, x = a(function({
|
|
21
|
+
surfaceId: n,
|
|
21
22
|
children: e,
|
|
22
|
-
distribution:
|
|
23
|
-
alignment:
|
|
23
|
+
distribution: s = "start",
|
|
24
|
+
alignment: m = "stretch"
|
|
24
25
|
}) {
|
|
25
|
-
const c = d(
|
|
26
|
+
const i = c(n), { basePath: p } = d(), o = l(
|
|
26
27
|
"flex flex-col gap-4",
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
y[s],
|
|
29
|
+
j[m]
|
|
29
30
|
);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
{
|
|
47
|
-
surfaceId: s,
|
|
48
|
-
componentId: o
|
|
49
|
-
},
|
|
50
|
-
f
|
|
51
|
-
)) });
|
|
52
|
-
}
|
|
53
|
-
return /* @__PURE__ */ t("div", { className: n });
|
|
31
|
+
return e?.explicitList ? /* @__PURE__ */ t("div", { className: o, children: e.explicitList.map((r) => /* @__PURE__ */ t(
|
|
32
|
+
f,
|
|
33
|
+
{
|
|
34
|
+
surfaceId: n,
|
|
35
|
+
componentId: r
|
|
36
|
+
},
|
|
37
|
+
r
|
|
38
|
+
)) }) : e?.template ? /* @__PURE__ */ t("div", { className: o, children: /* @__PURE__ */ t(
|
|
39
|
+
u,
|
|
40
|
+
{
|
|
41
|
+
surfaceId: n,
|
|
42
|
+
template: e.template,
|
|
43
|
+
dataModel: i,
|
|
44
|
+
basePath: p
|
|
45
|
+
}
|
|
46
|
+
) }) : /* @__PURE__ */ t("div", { className: o });
|
|
54
47
|
});
|
|
55
|
-
|
|
48
|
+
x.displayName = "A2UI.Column";
|
|
56
49
|
export {
|
|
57
|
-
|
|
50
|
+
x as ColumnComponent
|
|
58
51
|
};
|
|
@@ -1,51 +1,44 @@
|
|
|
1
1
|
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
-
import { memo as
|
|
3
|
-
import { useDataModel as
|
|
4
|
-
import { cn as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { memo as a } from "react";
|
|
3
|
+
import { useDataModel as l } from "../../hooks/useDataBinding.js";
|
|
4
|
+
import { cn as c } from "../../../lib/utils.js";
|
|
5
|
+
import { ComponentRenderer as f } from "../ComponentRenderer.js";
|
|
6
|
+
import { TemplateRenderer as d } from "./TemplateRenderer.js";
|
|
7
|
+
import { useScope as x } from "../../contexts/ScopeContext.js";
|
|
7
8
|
const L = {
|
|
8
9
|
start: "items-start",
|
|
9
10
|
center: "items-center",
|
|
10
11
|
end: "items-end",
|
|
11
12
|
stretch: "items-stretch"
|
|
12
|
-
},
|
|
13
|
-
surfaceId:
|
|
13
|
+
}, u = a(function({
|
|
14
|
+
surfaceId: o,
|
|
14
15
|
children: e,
|
|
15
|
-
direction:
|
|
16
|
-
alignment:
|
|
16
|
+
direction: i = "vertical",
|
|
17
|
+
alignment: n = "stretch"
|
|
17
18
|
}) {
|
|
18
|
-
const p = x(
|
|
19
|
+
const s = l(o), { basePath: p } = x(), m = c(
|
|
19
20
|
"flex gap-3",
|
|
20
|
-
|
|
21
|
-
L[
|
|
21
|
+
i === "horizontal" ? "flex-row" : "flex-col",
|
|
22
|
+
L[n]
|
|
22
23
|
);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
surfaceId: n,
|
|
41
|
-
componentId: i
|
|
42
|
-
},
|
|
43
|
-
f
|
|
44
|
-
)) });
|
|
45
|
-
}
|
|
46
|
-
return /* @__PURE__ */ t("div", { className: o });
|
|
24
|
+
return e?.explicitList ? /* @__PURE__ */ t("div", { className: m, children: e.explicitList.map((r) => /* @__PURE__ */ t(
|
|
25
|
+
f,
|
|
26
|
+
{
|
|
27
|
+
surfaceId: o,
|
|
28
|
+
componentId: r
|
|
29
|
+
},
|
|
30
|
+
r
|
|
31
|
+
)) }) : e?.template ? /* @__PURE__ */ t("div", { className: m, children: /* @__PURE__ */ t(
|
|
32
|
+
d,
|
|
33
|
+
{
|
|
34
|
+
surfaceId: o,
|
|
35
|
+
template: e.template,
|
|
36
|
+
dataModel: s,
|
|
37
|
+
basePath: p
|
|
38
|
+
}
|
|
39
|
+
) }) : /* @__PURE__ */ t("div", { className: m });
|
|
47
40
|
});
|
|
48
|
-
|
|
41
|
+
u.displayName = "A2UI.List";
|
|
49
42
|
export {
|
|
50
|
-
|
|
43
|
+
u as ListComponent
|
|
51
44
|
};
|
|
@@ -1,58 +1,51 @@
|
|
|
1
1
|
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
-
import { memo as
|
|
3
|
-
import { useDataModel as
|
|
4
|
-
import { cn as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
2
|
+
import { memo as a } from "react";
|
|
3
|
+
import { useDataModel as c } from "../../hooks/useDataBinding.js";
|
|
4
|
+
import { cn as f } from "../../../lib/utils.js";
|
|
5
|
+
import { ComponentRenderer as l } from "../ComponentRenderer.js";
|
|
6
|
+
import { TemplateRenderer as u } from "./TemplateRenderer.js";
|
|
7
|
+
import { useScope as d } from "../../contexts/ScopeContext.js";
|
|
8
|
+
const y = {
|
|
8
9
|
start: "justify-start",
|
|
9
10
|
center: "justify-center",
|
|
10
11
|
end: "justify-end",
|
|
11
12
|
spaceBetween: "justify-between",
|
|
12
13
|
spaceAround: "justify-around",
|
|
13
14
|
spaceEvenly: "justify-evenly"
|
|
14
|
-
},
|
|
15
|
+
}, j = {
|
|
15
16
|
start: "items-start",
|
|
16
17
|
center: "items-center",
|
|
17
18
|
end: "items-end",
|
|
18
19
|
stretch: "items-stretch"
|
|
19
|
-
},
|
|
20
|
-
surfaceId:
|
|
20
|
+
}, w = a(function({
|
|
21
|
+
surfaceId: o,
|
|
21
22
|
children: e,
|
|
22
|
-
distribution:
|
|
23
|
-
alignment:
|
|
23
|
+
distribution: s = "start",
|
|
24
|
+
alignment: i = "stretch"
|
|
24
25
|
}) {
|
|
25
|
-
const p =
|
|
26
|
+
const m = c(o), { basePath: p } = d(), n = f(
|
|
26
27
|
"flex flex-row gap-3",
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
y[s],
|
|
29
|
+
j[i]
|
|
29
30
|
);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
{
|
|
47
|
-
surfaceId: s,
|
|
48
|
-
componentId: o
|
|
49
|
-
},
|
|
50
|
-
d
|
|
51
|
-
)) });
|
|
52
|
-
}
|
|
53
|
-
return /* @__PURE__ */ t("div", { className: n });
|
|
31
|
+
return e?.explicitList ? /* @__PURE__ */ t("div", { className: n, children: e.explicitList.map((r) => /* @__PURE__ */ t(
|
|
32
|
+
l,
|
|
33
|
+
{
|
|
34
|
+
surfaceId: o,
|
|
35
|
+
componentId: r
|
|
36
|
+
},
|
|
37
|
+
r
|
|
38
|
+
)) }) : e?.template ? /* @__PURE__ */ t("div", { className: n, children: /* @__PURE__ */ t(
|
|
39
|
+
u,
|
|
40
|
+
{
|
|
41
|
+
surfaceId: o,
|
|
42
|
+
template: e.template,
|
|
43
|
+
dataModel: m,
|
|
44
|
+
basePath: p
|
|
45
|
+
}
|
|
46
|
+
) }) : /* @__PURE__ */ t("div", { className: n });
|
|
54
47
|
});
|
|
55
|
-
|
|
48
|
+
w.displayName = "A2UI.Row";
|
|
56
49
|
export {
|
|
57
|
-
|
|
50
|
+
w as RowComponent
|
|
58
51
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { TemplateBinding, DataModel } from '@a2ui-sdk/types/0.8';
|
|
2
|
+
export interface TemplateRendererProps {
|
|
3
|
+
surfaceId: string;
|
|
4
|
+
template: TemplateBinding;
|
|
5
|
+
dataModel: DataModel;
|
|
6
|
+
basePath: string | null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Renders template-bound children with scoped data context.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <TemplateRenderer
|
|
14
|
+
* surfaceId="main"
|
|
15
|
+
* template={{ componentId: "item-card", dataBinding: "/items" }}
|
|
16
|
+
* dataModel={{ items: { 0: { name: "Alice" }, 1: { name: "Bob" } } }}
|
|
17
|
+
* basePath={null}
|
|
18
|
+
* />
|
|
19
|
+
* // Renders two item-card components, each with scoped access to its data
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const TemplateRenderer: import('react').NamedExoticComponent<TemplateRendererProps>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as t, Fragment as l } from "react/jsx-runtime";
|
|
2
|
+
import { memo as f } from "react";
|
|
3
|
+
import { resolvePath as h, getValueByPath as u } from "@a2ui-sdk/utils/0.8";
|
|
4
|
+
import { ScopeProvider as P } from "../../contexts/ScopeContext.js";
|
|
5
|
+
import { ComponentRenderer as R } from "../ComponentRenderer.js";
|
|
6
|
+
const $ = f(function({
|
|
7
|
+
surfaceId: m,
|
|
8
|
+
template: a,
|
|
9
|
+
dataModel: i,
|
|
10
|
+
basePath: p
|
|
11
|
+
}) {
|
|
12
|
+
const { componentId: r, dataBinding: s } = a, o = h(s, p), e = u(i, o);
|
|
13
|
+
if (!e || typeof e != "object")
|
|
14
|
+
return null;
|
|
15
|
+
const c = Object.entries(e);
|
|
16
|
+
return /* @__PURE__ */ t(l, { children: c.map(([n]) => {
|
|
17
|
+
const d = `${o}/${n}`;
|
|
18
|
+
return /* @__PURE__ */ t(P, { basePath: d, children: /* @__PURE__ */ t(
|
|
19
|
+
R,
|
|
20
|
+
{
|
|
21
|
+
surfaceId: m,
|
|
22
|
+
componentId: r
|
|
23
|
+
}
|
|
24
|
+
) }, `${r}-${n}`);
|
|
25
|
+
}) });
|
|
26
|
+
});
|
|
27
|
+
$.displayName = "A2UI.TemplateRenderer";
|
|
28
|
+
export {
|
|
29
|
+
$ as TemplateRenderer
|
|
30
|
+
};
|
|
@@ -5,7 +5,7 @@ import { Action, ActionHandler } from '@a2ui-sdk/types/0.8';
|
|
|
5
5
|
*/
|
|
6
6
|
export interface ActionContextValue {
|
|
7
7
|
/** Dispatches an action with resolved context */
|
|
8
|
-
dispatchAction: (surfaceId: string, componentId: string, action: Action) => void;
|
|
8
|
+
dispatchAction: (surfaceId: string, componentId: string, action: Action, basePath: string | null) => void;
|
|
9
9
|
/** The action handler callback (if set) */
|
|
10
10
|
onAction: ActionHandler | null;
|
|
11
11
|
}
|
|
@@ -1,41 +1,45 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useCallback as
|
|
3
|
-
import { useDataModelContext as
|
|
4
|
-
import { resolveActionContext as
|
|
5
|
-
const s =
|
|
6
|
-
function
|
|
7
|
-
const { getDataModel: o } =
|
|
8
|
-
(n, a, r) => {
|
|
1
|
+
import { jsx as x } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback as C, useMemo as p, createContext as f, useContext as v } from "react";
|
|
3
|
+
import { useDataModelContext as A } from "./DataModelContext.js";
|
|
4
|
+
import { resolveActionContext as h } from "@a2ui-sdk/utils/0.8";
|
|
5
|
+
const s = f(null);
|
|
6
|
+
function g({ onAction: t, children: c }) {
|
|
7
|
+
const { getDataModel: o } = A(), e = C(
|
|
8
|
+
(n, a, r, u) => {
|
|
9
9
|
if (!t) {
|
|
10
10
|
console.warn("A2UI: Action dispatched but no handler is registered");
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
const
|
|
13
|
+
const d = o(n), l = h(
|
|
14
|
+
r.context,
|
|
15
|
+
d,
|
|
16
|
+
u
|
|
17
|
+
), m = {
|
|
14
18
|
surfaceId: n,
|
|
15
19
|
name: r.name,
|
|
16
|
-
context:
|
|
20
|
+
context: l,
|
|
17
21
|
sourceComponentId: a
|
|
18
22
|
};
|
|
19
|
-
t(
|
|
23
|
+
t(m);
|
|
20
24
|
},
|
|
21
25
|
[t, o]
|
|
22
|
-
), i =
|
|
26
|
+
), i = p(
|
|
23
27
|
() => ({
|
|
24
28
|
dispatchAction: e,
|
|
25
29
|
onAction: t ?? null
|
|
26
30
|
}),
|
|
27
31
|
[e, t]
|
|
28
32
|
);
|
|
29
|
-
return /* @__PURE__ */
|
|
33
|
+
return /* @__PURE__ */ x(s.Provider, { value: i, children: c });
|
|
30
34
|
}
|
|
31
|
-
function
|
|
32
|
-
const t =
|
|
35
|
+
function D() {
|
|
36
|
+
const t = v(s);
|
|
33
37
|
if (!t)
|
|
34
38
|
throw new Error("useActionContext must be used within an ActionProvider");
|
|
35
39
|
return t;
|
|
36
40
|
}
|
|
37
41
|
export {
|
|
38
42
|
s as ActionContext,
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
g as ActionProvider,
|
|
44
|
+
D as useActionContext
|
|
41
45
|
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ScopeValue } from '@a2ui-sdk/types/0.8';
|
|
3
|
+
/**
|
|
4
|
+
* Context for tracking collection scopes.
|
|
5
|
+
*
|
|
6
|
+
* When rendering children from template binding (e.g., List with `{"componentId": "item", "dataBinding": "/items"}`),
|
|
7
|
+
* each item gets its own scope with a base path like "/items/0", "/items/1", etc.
|
|
8
|
+
*
|
|
9
|
+
* Components use this context to resolve relative paths within their scope.
|
|
10
|
+
*/
|
|
11
|
+
export declare const ScopeContext: import('react').Context<ScopeValue>;
|
|
12
|
+
/**
|
|
13
|
+
* Props for ScopeProvider.
|
|
14
|
+
*/
|
|
15
|
+
export interface ScopeProviderProps {
|
|
16
|
+
/** The base path for this scope (e.g., "/items/0") */
|
|
17
|
+
basePath: string;
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Provider for creating a new scope.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* // In ListComponent when rendering template children:
|
|
26
|
+
* {items.map(([key]) => (
|
|
27
|
+
* <ScopeProvider key={key} basePath={`${dataPath}/${key}`}>
|
|
28
|
+
* <ComponentRenderer surfaceId={surfaceId} componentId={templateComponentId} />
|
|
29
|
+
* </ScopeProvider>
|
|
30
|
+
* ))}
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function ScopeProvider({ basePath, children }: ScopeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
/**
|
|
35
|
+
* Hook to access the current scope.
|
|
36
|
+
*
|
|
37
|
+
* @returns The current scope value
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```tsx
|
|
41
|
+
* function MyComponent() {
|
|
42
|
+
* const { basePath } = useScope()
|
|
43
|
+
* // basePath is null for root scope, or something like "/items/0" for item scope
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function useScope(): ScopeValue;
|
|
48
|
+
/**
|
|
49
|
+
* Hook to get the base path for the current scope.
|
|
50
|
+
*
|
|
51
|
+
* @returns The base path (null for root scope, string for nested scope)
|
|
52
|
+
*/
|
|
53
|
+
export declare function useScopeBasePath(): string | null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { useContext as c, createContext as u } from "react";
|
|
3
|
+
const s = {
|
|
4
|
+
basePath: null
|
|
5
|
+
}, t = u(s);
|
|
6
|
+
function f({ basePath: e, children: o }) {
|
|
7
|
+
const n = { basePath: e };
|
|
8
|
+
return /* @__PURE__ */ r(t.Provider, { value: n, children: o });
|
|
9
|
+
}
|
|
10
|
+
function a() {
|
|
11
|
+
return c(t);
|
|
12
|
+
}
|
|
13
|
+
function l() {
|
|
14
|
+
const { basePath: e } = a();
|
|
15
|
+
return e;
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
t as ScopeContext,
|
|
19
|
+
f as ScopeProvider,
|
|
20
|
+
a as useScope,
|
|
21
|
+
l as useScopeBasePath
|
|
22
|
+
};
|
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
import { useMemo as i } from "react";
|
|
2
2
|
import { useDataModelContext as l } from "../contexts/DataModelContext.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { useScope as m } from "../contexts/ScopeContext.js";
|
|
4
|
+
import { resolveValue as p, resolvePath as d } from "@a2ui-sdk/utils/0.8";
|
|
5
|
+
function c(o, t, e) {
|
|
6
|
+
const { getDataModel: a } = l(), { basePath: r } = m();
|
|
6
7
|
return i(() => {
|
|
7
|
-
const
|
|
8
|
-
return
|
|
9
|
-
}, [
|
|
8
|
+
const n = a(o);
|
|
9
|
+
return p(t, n, r, e);
|
|
10
|
+
}, [a, o, t, r, e]);
|
|
10
11
|
}
|
|
11
|
-
function
|
|
12
|
+
function b(o) {
|
|
12
13
|
const { getDataModel: t } = l();
|
|
13
|
-
return i(() => t(
|
|
14
|
+
return i(() => t(o), [t, o]);
|
|
14
15
|
}
|
|
15
|
-
function
|
|
16
|
-
const { getDataModel:
|
|
17
|
-
const
|
|
18
|
-
return
|
|
19
|
-
}, [
|
|
20
|
-
t && "path" in t
|
|
21
|
-
|
|
16
|
+
function x(o, t, e) {
|
|
17
|
+
const { getDataModel: a, setDataValue: r } = l(), { basePath: n } = m(), M = i(() => {
|
|
18
|
+
const s = a(o);
|
|
19
|
+
return p(t, s, n, e);
|
|
20
|
+
}, [a, o, t, n, e]), D = i(() => (s) => {
|
|
21
|
+
if (t && "path" in t) {
|
|
22
|
+
const h = d(t.path, n);
|
|
23
|
+
r(o, h, s);
|
|
24
|
+
}
|
|
25
|
+
}, [r, o, t, n]);
|
|
22
26
|
return [M, D];
|
|
23
27
|
}
|
|
24
28
|
export {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
c as useDataBinding,
|
|
30
|
+
b as useDataModel,
|
|
31
|
+
x as useFormBinding
|
|
28
32
|
};
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { useCallback as i } from "react";
|
|
2
|
+
import { useActionContext as n } from "../contexts/ActionContext.js";
|
|
3
|
+
import { useScopeBasePath as r } from "../contexts/ScopeContext.js";
|
|
4
|
+
function u() {
|
|
5
|
+
const { dispatchAction: t } = n(), o = r();
|
|
6
|
+
return i(
|
|
7
|
+
(c, e, s) => {
|
|
8
|
+
t(c, e, s, o);
|
|
9
|
+
},
|
|
10
|
+
[t, o]
|
|
11
|
+
);
|
|
5
12
|
}
|
|
6
13
|
export {
|
|
7
|
-
|
|
14
|
+
u as useDispatchAction
|
|
8
15
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a2ui-sdk/react",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "A2UI SDK for React",
|
|
5
5
|
"homepage": "https://a2ui-sdk.js.org/",
|
|
6
6
|
"repository": {
|
|
@@ -50,8 +50,6 @@
|
|
|
50
50
|
"react-dom": "^19.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@a2ui-sdk/types": "0.2.0",
|
|
54
|
-
"@a2ui-sdk/utils": "0.2.0",
|
|
55
53
|
"@testing-library/dom": "^10.4.1",
|
|
56
54
|
"@testing-library/jest-dom": "^6.9.1",
|
|
57
55
|
"@testing-library/react": "^16.3.1",
|
|
@@ -68,6 +66,8 @@
|
|
|
68
66
|
"vitest": "^4.0.16"
|
|
69
67
|
},
|
|
70
68
|
"dependencies": {
|
|
69
|
+
"@a2ui-sdk/types": "0.2.2",
|
|
70
|
+
"@a2ui-sdk/utils": "0.2.2",
|
|
71
71
|
"@radix-ui/react-checkbox": "^1.3.3",
|
|
72
72
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
73
73
|
"@radix-ui/react-label": "^2.1.8",
|