@a2ui-sdk/react 0.2.1 → 0.3.0

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 CHANGED
@@ -15,7 +15,129 @@ npm install @a2ui-sdk/react
15
15
 
16
16
  ## Usage
17
17
 
18
- ### Basic Usage
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} onAction={handleAction}>
39
- <A2UIRenderer />
160
+ <A2UIProvider messages={messages}>
161
+ <A2UIRenderer onAction={handleAction} />
40
162
  </A2UIProvider>
41
163
  )
42
164
  }
43
165
  ```
44
166
 
45
- ### With Custom Components
167
+ #### Custom Components
46
168
 
47
- You can override default components or add new ones via the `components` prop:
169
+ Override or extend the standard catalog the same way as in v0.8:
48
170
 
49
171
  ```tsx
50
- import { A2UIProvider, A2UIRenderer, useDataBinding } from '@a2ui-sdk/react/0.9'
172
+ import {
173
+ A2UIProvider,
174
+ A2UIRenderer,
175
+ standardCatalog,
176
+ type A2UIMessage,
177
+ type A2UIAction,
178
+ } from '@a2ui-sdk/react/0.9'
51
179
 
52
- // Custom component implementation
53
- function MyCustomText({ text }: { text: DynamicString }) {
54
- const resolvedText = useDataBinding(text)
55
- return <span className="my-custom-style">{resolvedText}</span>
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
- messages={messages}
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,
@@ -92,6 +221,10 @@ import {
92
221
  useScope,
93
222
  useScopeBasePath,
94
223
 
224
+ // Context Providers & Hooks
225
+ ActionProvider,
226
+ useActionContext,
227
+
95
228
  // Types
96
229
  type A2UIMessage,
97
230
  type A2UIAction,
@@ -124,12 +257,21 @@ import {
124
257
  A2UIRenderer,
125
258
  ComponentRenderer,
126
259
 
260
+ // Catalog
261
+ standardCatalog,
262
+
127
263
  // Hooks
128
264
  useDispatchAction,
129
265
  useDataBinding,
130
266
  useFormBinding,
131
267
  useSurfaceContext,
132
268
  useDataModelContext,
269
+ useScope,
270
+ useScopeBasePath,
271
+
272
+ // Context Providers & Hooks
273
+ ActionProvider,
274
+ useActionContext,
133
275
 
134
276
  // Types
135
277
  type A2UIMessage,
@@ -139,6 +281,7 @@ import {
139
281
  type ComponentsMap,
140
282
  type Action,
141
283
  type ValueSource,
284
+ type ScopeValue,
142
285
  } from '@a2ui-sdk/react/0.8'
143
286
  ```
144
287
 
@@ -197,6 +340,46 @@ const { valid, errors } = useValidation(checks)
197
340
  // errors: string[] - list of failed validation messages
198
341
  ```
199
342
 
343
+ ### ActionProvider & useActionContext
344
+
345
+ For advanced use cases, you can create custom action handling middleware by using `ActionProvider` and `useActionContext` directly. This is useful when you need to intercept, transform, or augment actions before they reach your action handler.
346
+
347
+ ```tsx
348
+ import {
349
+ A2UIProvider,
350
+ A2UIRenderer,
351
+ ActionProvider,
352
+ useActionContext,
353
+ } from '@a2ui-sdk/react/0.9'
354
+
355
+ function ActionLogger({ children }: { children: React.ReactNode }) {
356
+ const { onAction } = useActionContext()
357
+
358
+ // You can access the action handler here
359
+ // and potentially wrap it with logging or other middleware logic
360
+
361
+ return <>{children}</>
362
+ }
363
+
364
+ function App() {
365
+ const handleAction = (action: A2UIAction) => {
366
+ console.log('Action:', action)
367
+ }
368
+
369
+ return (
370
+ <A2UIProvider messages={messages}>
371
+ <ActionProvider onAction={handleAction}>
372
+ <ActionLogger>
373
+ <A2UIRenderer />
374
+ </ActionLogger>
375
+ </ActionProvider>
376
+ </A2UIProvider>
377
+ )
378
+ }
379
+ ```
380
+
381
+ **Note:** In most cases, you don't need to use `ActionProvider` directly as `A2UIProvider` already includes it. Use this only for advanced customization scenarios.
382
+
200
383
  ## License
201
384
 
202
385
  Apache-2.0
@@ -1,58 +1,51 @@
1
1
  import { jsx as t } from "react/jsx-runtime";
2
- import { memo as u } from "react";
3
- import { useDataModel as d } from "../../hooks/useDataBinding.js";
4
- import { cn as y } from "../../../lib/utils.js";
5
- import { getValueByPath as j } from "@a2ui-sdk/utils/0.8";
6
- import { ComponentRenderer as r } from "../ComponentRenderer.js";
7
- const v = {
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
- }, x = {
15
+ }, j = {
15
16
  start: "items-start",
16
17
  center: "items-center",
17
18
  end: "items-end",
18
19
  stretch: "items-stretch"
19
- }, C = u(function({
20
- surfaceId: s,
20
+ }, x = a(function({
21
+ surfaceId: n,
21
22
  children: e,
22
- distribution: m = "start",
23
- alignment: a = "stretch"
23
+ distribution: s = "start",
24
+ alignment: m = "stretch"
24
25
  }) {
25
- const c = d(s), n = y(
26
+ const i = c(n), { basePath: p } = d(), o = l(
26
27
  "flex flex-col gap-4",
27
- v[m],
28
- x[a]
28
+ y[s],
29
+ j[m]
29
30
  );
30
- if (e?.explicitList)
31
- return /* @__PURE__ */ t("div", { className: n, children: e.explicitList.map((o) => /* @__PURE__ */ t(
32
- r,
33
- {
34
- surfaceId: s,
35
- componentId: o
36
- },
37
- o
38
- )) });
39
- if (e?.template) {
40
- const { componentId: o, dataBinding: p } = e.template, i = j(c, p);
41
- if (!i || typeof i != "object")
42
- return /* @__PURE__ */ t("div", { className: n });
43
- const l = Object.entries(i);
44
- return /* @__PURE__ */ t("div", { className: n, children: l.map(([f]) => /* @__PURE__ */ t(
45
- r,
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
- C.displayName = "A2UI.Column";
48
+ x.displayName = "A2UI.Column";
56
49
  export {
57
- C as ColumnComponent
50
+ x as ColumnComponent
58
51
  };
@@ -1,51 +1,44 @@
1
1
  import { jsx as t } from "react/jsx-runtime";
2
- import { memo as d } from "react";
3
- import { useDataModel as x } from "../../hooks/useDataBinding.js";
4
- import { cn as u } from "../../../lib/utils.js";
5
- import { getValueByPath as v } from "@a2ui-sdk/utils/0.8";
6
- import { ComponentRenderer as r } from "../ComponentRenderer.js";
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
- }, g = d(function({
13
- surfaceId: n,
13
+ }, u = a(function({
14
+ surfaceId: o,
14
15
  children: e,
15
- direction: s = "vertical",
16
- alignment: a = "stretch"
16
+ direction: i = "vertical",
17
+ alignment: n = "stretch"
17
18
  }) {
18
- const p = x(n), o = u(
19
+ const s = l(o), { basePath: p } = x(), m = c(
19
20
  "flex gap-3",
20
- s === "horizontal" ? "flex-row" : "flex-col",
21
- L[a]
21
+ i === "horizontal" ? "flex-row" : "flex-col",
22
+ L[n]
22
23
  );
23
- if (e?.explicitList)
24
- return /* @__PURE__ */ t("div", { className: o, children: e.explicitList.map((i) => /* @__PURE__ */ t(
25
- r,
26
- {
27
- surfaceId: n,
28
- componentId: i
29
- },
30
- i
31
- )) });
32
- if (e?.template) {
33
- const { componentId: i, dataBinding: c } = e.template, m = v(p, c);
34
- if (!m || typeof m != "object")
35
- return /* @__PURE__ */ t("div", { className: o });
36
- const l = Object.entries(m);
37
- return /* @__PURE__ */ t("div", { className: o, children: l.map(([f]) => /* @__PURE__ */ t(
38
- r,
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
- g.displayName = "A2UI.List";
41
+ u.displayName = "A2UI.List";
49
42
  export {
50
- g as ListComponent
43
+ u as ListComponent
51
44
  };
@@ -1,58 +1,51 @@
1
1
  import { jsx as t } from "react/jsx-runtime";
2
- import { memo as l } from "react";
3
- import { useDataModel as u } from "../../hooks/useDataBinding.js";
4
- import { cn as y } from "../../../lib/utils.js";
5
- import { getValueByPath as j } from "@a2ui-sdk/utils/0.8";
6
- import { ComponentRenderer as r } from "../ComponentRenderer.js";
7
- const v = {
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
- }, w = {
15
+ }, j = {
15
16
  start: "items-start",
16
17
  center: "items-center",
17
18
  end: "items-end",
18
19
  stretch: "items-stretch"
19
- }, x = l(function({
20
- surfaceId: s,
20
+ }, w = a(function({
21
+ surfaceId: o,
21
22
  children: e,
22
- distribution: m = "start",
23
- alignment: a = "stretch"
23
+ distribution: s = "start",
24
+ alignment: i = "stretch"
24
25
  }) {
25
- const p = u(s), n = y(
26
+ const m = c(o), { basePath: p } = d(), n = f(
26
27
  "flex flex-row gap-3",
27
- v[m],
28
- w[a]
28
+ y[s],
29
+ j[i]
29
30
  );
30
- if (e?.explicitList)
31
- return /* @__PURE__ */ t("div", { className: n, children: e.explicitList.map((o) => /* @__PURE__ */ t(
32
- r,
33
- {
34
- surfaceId: s,
35
- componentId: o
36
- },
37
- o
38
- )) });
39
- if (e?.template) {
40
- const { componentId: o, dataBinding: c } = e.template, i = j(p, c);
41
- if (!i || typeof i != "object")
42
- return /* @__PURE__ */ t("div", { className: n });
43
- const f = Object.entries(i);
44
- return /* @__PURE__ */ t("div", { className: n, children: f.map(([d]) => /* @__PURE__ */ t(
45
- r,
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
- x.displayName = "A2UI.Row";
48
+ w.displayName = "A2UI.Row";
56
49
  export {
57
- x as RowComponent
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 m } from "react/jsx-runtime";
2
- import { useCallback as x, useMemo as C, createContext as p, useContext as f } from "react";
3
- import { useDataModelContext as v } from "./DataModelContext.js";
4
- import { resolveActionContext as A } from "@a2ui-sdk/utils/0.8";
5
- const s = p(null);
6
- function P({ onAction: t, children: c }) {
7
- const { getDataModel: o } = v(), e = x(
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 u = o(n), d = A(r.context, u), l = {
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: d,
20
+ context: l,
17
21
  sourceComponentId: a
18
22
  };
19
- t(l);
23
+ t(m);
20
24
  },
21
25
  [t, o]
22
- ), i = C(
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__ */ m(s.Provider, { value: i, children: c });
33
+ return /* @__PURE__ */ x(s.Provider, { value: i, children: c });
30
34
  }
31
- function g() {
32
- const t = f(s);
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
- P as ActionProvider,
40
- g as useActionContext
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 { resolveValue as m } from "@a2ui-sdk/utils/0.8";
4
- function s(n, t, o) {
5
- const { getDataModel: e } = l();
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 a = e(n);
8
- return m(t, a, o);
9
- }, [e, n, t, o]);
8
+ const n = a(o);
9
+ return p(t, n, r, e);
10
+ }, [a, o, t, r, e]);
10
11
  }
11
- function u(n) {
12
+ function b(o) {
12
13
  const { getDataModel: t } = l();
13
- return i(() => t(n), [t, n]);
14
+ return i(() => t(o), [t, o]);
14
15
  }
15
- function h(n, t, o) {
16
- const { getDataModel: e, setDataValue: a } = l(), M = i(() => {
17
- const r = e(n);
18
- return m(t, r, o);
19
- }, [e, n, t, o]), D = i(() => (r) => {
20
- t && "path" in t && a(n, t.path, r);
21
- }, [a, n, t]);
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
- s as useDataBinding,
26
- u as useDataModel,
27
- h as useFormBinding
29
+ c as useDataBinding,
30
+ b as useDataModel,
31
+ x as useFormBinding
28
32
  };
@@ -1,6 +1,7 @@
1
1
  import { Action } from '@a2ui-sdk/types/0.8';
2
2
  /**
3
3
  * Returns a function to dispatch actions.
4
+ * Automatically captures the current scope context for action resolution.
4
5
  *
5
6
  * @returns A function that dispatches actions
6
7
  *
@@ -1,8 +1,15 @@
1
- import { useActionContext as o } from "../contexts/ActionContext.js";
2
- function c() {
3
- const { dispatchAction: t } = o();
4
- return t;
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
- c as useDispatchAction
14
+ u as useDispatchAction
8
15
  };
@@ -44,3 +44,4 @@ export { useDispatchAction } from './hooks/useDispatchAction';
44
44
  export { useDataBinding, useFormBinding } from './hooks/useDataBinding';
45
45
  export { useSurfaceContext } from './contexts/SurfaceContext';
46
46
  export { useDataModelContext } from './contexts/DataModelContext';
47
+ export { ActionProvider, useActionContext } from './contexts/ActionContext';
package/dist/0.8/index.js CHANGED
@@ -1,19 +1,22 @@
1
1
  import { A2UIProvider as r } from "./contexts/A2UIProvider.js";
2
2
  import { A2UIRenderer as n } from "./A2UIRenderer.js";
3
3
  import { ComponentRenderer as m } from "./components/ComponentRenderer.js";
4
- import { standardCatalog as x } from "./standard-catalog/index.js";
5
- import { useDispatchAction as d } from "./hooks/useDispatchAction.js";
4
+ import { standardCatalog as a } from "./standard-catalog/index.js";
5
+ import { useDispatchAction as i } from "./hooks/useDispatchAction.js";
6
6
  import { useDataBinding as s, useFormBinding as u } from "./hooks/useDataBinding.js";
7
- import { useSurfaceContext as c } from "./contexts/SurfaceContext.js";
8
- import { useDataModelContext as A } from "./contexts/DataModelContext.js";
7
+ import { useSurfaceContext as A } from "./contexts/SurfaceContext.js";
8
+ import { useDataModelContext as g } from "./contexts/DataModelContext.js";
9
+ import { ActionProvider as l, useActionContext as v } from "./contexts/ActionContext.js";
9
10
  export {
10
11
  r as A2UIProvider,
11
12
  n as A2UIRenderer,
13
+ l as ActionProvider,
12
14
  m as ComponentRenderer,
13
- x as standardCatalog,
15
+ a as standardCatalog,
16
+ v as useActionContext,
14
17
  s as useDataBinding,
15
- A as useDataModelContext,
16
- d as useDispatchAction,
18
+ g as useDataModelContext,
19
+ i as useDispatchAction,
17
20
  u as useFormBinding,
18
- c as useSurfaceContext
21
+ A as useSurfaceContext
19
22
  };
@@ -34,3 +34,4 @@ export { useDataBinding, useFormBinding, useStringBinding, useDataModel, } from
34
34
  export { useValidation } from './hooks/useValidation';
35
35
  export { useSurfaceContext } from './contexts/SurfaceContext';
36
36
  export { useScope, useScopeBasePath } from './contexts/ScopeContext';
37
+ export { ActionProvider, useActionContext } from './contexts/ActionContext';
package/dist/0.9/index.js CHANGED
@@ -1,24 +1,27 @@
1
1
  import { A2UIProvider as r } from "./contexts/A2UIProvider.js";
2
2
  import { A2UIRenderer as n } from "./A2UIRenderer.js";
3
- import { ComponentRenderer as p } from "./components/ComponentRenderer.js";
3
+ import { ComponentRenderer as a } from "./components/ComponentRenderer.js";
4
4
  import { standardCatalog as s } from "./standard-catalog/index.js";
5
- import { useDispatchAction as d } from "./hooks/useDispatchAction.js";
6
- import { useDataBinding as u, useDataModel as x, useFormBinding as c, useStringBinding as g } from "./hooks/useDataBinding.js";
7
- import { useValidation as S } from "./hooks/useValidation.js";
8
- import { useSurfaceContext as A } from "./contexts/SurfaceContext.js";
9
- import { useScope as D, useScopeBasePath as h } from "./contexts/ScopeContext.js";
5
+ import { useDispatchAction as x } from "./hooks/useDispatchAction.js";
6
+ import { useDataBinding as f, useDataModel as u, useFormBinding as c, useStringBinding as g } from "./hooks/useDataBinding.js";
7
+ import { useValidation as B } from "./hooks/useValidation.js";
8
+ import { useSurfaceContext as S } from "./contexts/SurfaceContext.js";
9
+ import { useScope as D, useScopeBasePath as P } from "./contexts/ScopeContext.js";
10
+ import { ActionProvider as v, useActionContext as I } from "./contexts/ActionContext.js";
10
11
  export {
11
12
  r as A2UIProvider,
12
13
  n as A2UIRenderer,
13
- p as ComponentRenderer,
14
+ v as ActionProvider,
15
+ a as ComponentRenderer,
14
16
  s as standardCatalog,
15
- u as useDataBinding,
16
- x as useDataModel,
17
- d as useDispatchAction,
17
+ I as useActionContext,
18
+ f as useDataBinding,
19
+ u as useDataModel,
20
+ x as useDispatchAction,
18
21
  c as useFormBinding,
19
22
  D as useScope,
20
- h as useScopeBasePath,
23
+ P as useScopeBasePath,
21
24
  g as useStringBinding,
22
- A as useSurfaceContext,
23
- S as useValidation
25
+ S as useSurfaceContext,
26
+ B as useValidation
24
27
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a2ui-sdk/react",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "A2UI SDK for React",
5
5
  "homepage": "https://a2ui-sdk.js.org/",
6
6
  "repository": {
@@ -66,8 +66,8 @@
66
66
  "vitest": "^4.0.16"
67
67
  },
68
68
  "dependencies": {
69
- "@a2ui-sdk/types": "0.2.1",
70
- "@a2ui-sdk/utils": "0.2.1",
69
+ "@a2ui-sdk/types": "0.3.0",
70
+ "@a2ui-sdk/utils": "0.3.0",
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",