@json-render/react 0.2.0 → 0.4.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 +250 -183
- package/dist/chunk-IGPI5WNB.mjs +52 -0
- package/dist/chunk-IGPI5WNB.mjs.map +1 -0
- package/dist/index.d.mts +188 -16
- package/dist/index.d.ts +188 -16
- package/dist/index.js +195 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +153 -38
- package/dist/index.mjs.map +1 -1
- package/dist/schema.d.mts +106 -0
- package/dist/schema.d.ts +106 -0
- package/dist/schema.js +77 -0
- package/dist/schema.js.map +1 -0
- package/dist/schema.mjs +9 -0
- package/dist/schema.mjs.map +1 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -1,238 +1,305 @@
|
|
|
1
1
|
# @json-render/react
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Visibility Filtering**: Components automatically show/hide based on visibility conditions
|
|
8
|
-
- **Action Handling**: Built-in action execution with confirmation dialogs
|
|
9
|
-
- **Validation**: Field validation with error display
|
|
10
|
-
- **Data Binding**: Two-way data binding between UI and data model
|
|
11
|
-
- **Streaming**: Progressive rendering from streamed UI trees
|
|
3
|
+
React renderer for json-render. Turn JSON specs into React components with data binding, visibility, and actions.
|
|
12
4
|
|
|
13
5
|
## Installation
|
|
14
6
|
|
|
15
7
|
```bash
|
|
16
|
-
npm install @json-render/react @json-render/core
|
|
17
|
-
# or
|
|
18
|
-
pnpm add @json-render/react @json-render/core
|
|
8
|
+
npm install @json-render/react @json-render/core zod
|
|
19
9
|
```
|
|
20
10
|
|
|
21
11
|
## Quick Start
|
|
22
12
|
|
|
23
|
-
###
|
|
24
|
-
|
|
25
|
-
```tsx
|
|
26
|
-
import { JSONUIProvider, Renderer, useUIStream } from '@json-render/react';
|
|
27
|
-
|
|
28
|
-
// Define your component registry
|
|
29
|
-
const registry = {
|
|
30
|
-
Card: ({ element, children }) => (
|
|
31
|
-
<div className="card">
|
|
32
|
-
<h3>{element.props.title}</h3>
|
|
33
|
-
{children}
|
|
34
|
-
</div>
|
|
35
|
-
),
|
|
36
|
-
Button: ({ element, onAction }) => (
|
|
37
|
-
<button onClick={() => onAction?.(element.props.action)}>
|
|
38
|
-
{element.props.label}
|
|
39
|
-
</button>
|
|
40
|
-
),
|
|
41
|
-
};
|
|
13
|
+
### 1. Create a Catalog
|
|
42
14
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
15
|
+
```typescript
|
|
16
|
+
import { defineCatalog } from "@json-render/core";
|
|
17
|
+
import { schema } from "@json-render/react";
|
|
18
|
+
import { z } from "zod";
|
|
19
|
+
|
|
20
|
+
export const catalog = defineCatalog(schema, {
|
|
21
|
+
components: {
|
|
22
|
+
Card: {
|
|
23
|
+
props: z.object({
|
|
24
|
+
title: z.string(),
|
|
25
|
+
description: z.string().nullable(),
|
|
26
|
+
}),
|
|
27
|
+
description: "A card container",
|
|
28
|
+
},
|
|
29
|
+
Button: {
|
|
30
|
+
props: z.object({
|
|
31
|
+
label: z.string(),
|
|
32
|
+
action: z.string(),
|
|
33
|
+
}),
|
|
34
|
+
description: "A clickable button",
|
|
35
|
+
},
|
|
36
|
+
Input: {
|
|
37
|
+
props: z.object({
|
|
38
|
+
label: z.string(),
|
|
39
|
+
placeholder: z.string().nullable(),
|
|
40
|
+
}),
|
|
41
|
+
description: "Text input field",
|
|
42
|
+
},
|
|
47
43
|
},
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
actions: {
|
|
45
|
+
submit: { description: "Submit the form" },
|
|
46
|
+
cancel: { description: "Cancel and close" },
|
|
50
47
|
},
|
|
51
|
-
};
|
|
48
|
+
});
|
|
49
|
+
```
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
const { tree, isStreaming, send, clear } = useUIStream({
|
|
55
|
-
api: '/api/generate',
|
|
56
|
-
});
|
|
51
|
+
### 2. Define Component Implementations
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
53
|
+
```tsx
|
|
54
|
+
import { defineRegistry, useData } from "@json-render/react";
|
|
55
|
+
import { catalog } from "./catalog";
|
|
56
|
+
|
|
57
|
+
export const { registry } = defineRegistry(catalog, {
|
|
58
|
+
components: {
|
|
59
|
+
Card: ({ props, children }) => (
|
|
60
|
+
<div className="card">
|
|
61
|
+
<h3>{props.title}</h3>
|
|
62
|
+
{props.description && <p>{props.description}</p>}
|
|
63
|
+
{children}
|
|
64
|
+
</div>
|
|
65
|
+
),
|
|
66
|
+
Button: ({ props, onAction }) => (
|
|
67
|
+
<button onClick={() => onAction?.({ name: props.action })}>
|
|
68
|
+
{props.label}
|
|
69
|
+
</button>
|
|
70
|
+
),
|
|
71
|
+
Input: ({ props }) => {
|
|
72
|
+
const { get, set } = useData();
|
|
73
|
+
return (
|
|
74
|
+
<label>
|
|
75
|
+
{props.label}
|
|
76
|
+
<input
|
|
77
|
+
placeholder={props.placeholder ?? ""}
|
|
78
|
+
value={get("/form/value") ?? ""}
|
|
79
|
+
onChange={(e) => set("/form/value", e.target.value)}
|
|
80
|
+
/>
|
|
81
|
+
</label>
|
|
82
|
+
);
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
73
86
|
```
|
|
74
87
|
|
|
75
|
-
###
|
|
88
|
+
### 3. Render Specs
|
|
76
89
|
|
|
77
90
|
```tsx
|
|
78
|
-
import {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
ValidationProvider,
|
|
83
|
-
useData,
|
|
84
|
-
useVisibility,
|
|
85
|
-
useActions,
|
|
86
|
-
useFieldValidation,
|
|
87
|
-
} from '@json-render/react';
|
|
88
|
-
|
|
89
|
-
// Data context
|
|
90
|
-
function MyComponent() {
|
|
91
|
-
const { data, get, set } = useData();
|
|
92
|
-
const value = get('/user/name');
|
|
93
|
-
|
|
91
|
+
import { Renderer, DataProvider, ActionProvider } from "@json-render/react";
|
|
92
|
+
import { registry } from "./registry";
|
|
93
|
+
|
|
94
|
+
function App({ spec }) {
|
|
94
95
|
return (
|
|
95
|
-
<
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
<DataProvider initialData={{ form: { value: "" } }}>
|
|
97
|
+
<ActionProvider handlers={{
|
|
98
|
+
submit: () => console.log("Submit"),
|
|
99
|
+
}}>
|
|
100
|
+
<Renderer spec={spec} registry={registry} />
|
|
101
|
+
</ActionProvider>
|
|
102
|
+
</DataProvider>
|
|
99
103
|
);
|
|
100
104
|
}
|
|
105
|
+
```
|
|
101
106
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return <div>Visible content</div>;
|
|
107
|
+
## Spec Format
|
|
108
|
+
|
|
109
|
+
The React renderer uses an element tree format:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
interface Spec {
|
|
113
|
+
root: Element;
|
|
111
114
|
}
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
<button
|
|
119
|
-
onClick={() => execute(action)}
|
|
120
|
-
disabled={loadingActions.has(action.name)}
|
|
121
|
-
>
|
|
122
|
-
{action.name}
|
|
123
|
-
</button>
|
|
124
|
-
);
|
|
116
|
+
interface Element {
|
|
117
|
+
type: string; // Component name from catalog
|
|
118
|
+
props: object; // Component props
|
|
119
|
+
children?: Element[]; // Nested elements
|
|
120
|
+
visible?: VisibilityCondition;
|
|
125
121
|
}
|
|
122
|
+
```
|
|
126
123
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
|
|
141
|
-
|
|
124
|
+
Example spec:
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"root": {
|
|
129
|
+
"type": "Card",
|
|
130
|
+
"props": { "title": "Welcome" },
|
|
131
|
+
"children": [
|
|
132
|
+
{
|
|
133
|
+
"type": "Input",
|
|
134
|
+
"props": { "label": "Name", "placeholder": "Enter name" }
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"type": "Button",
|
|
138
|
+
"props": { "label": "Submit", "action": "submit" }
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
142
|
}
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
-
|
|
145
|
+
## Contexts
|
|
146
|
+
|
|
147
|
+
### DataProvider
|
|
148
|
+
|
|
149
|
+
Share data across components with JSON Pointer paths:
|
|
146
150
|
|
|
147
151
|
```tsx
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
} = useUIStream({
|
|
158
|
-
api: '/api/generate',
|
|
159
|
-
onComplete: (tree) => console.log('Done:', tree),
|
|
160
|
-
onError: (err) => console.error('Error:', err),
|
|
161
|
-
});
|
|
152
|
+
<DataProvider initialData={{ user: { name: "John" } }}>
|
|
153
|
+
{children}
|
|
154
|
+
</DataProvider>
|
|
155
|
+
|
|
156
|
+
// In components:
|
|
157
|
+
const { data, get, set } = useData();
|
|
158
|
+
const name = get("/user/name"); // "John"
|
|
159
|
+
set("/user/age", 25);
|
|
160
|
+
```
|
|
162
161
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
162
|
+
### ActionProvider
|
|
163
|
+
|
|
164
|
+
Handle actions from components:
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
<ActionProvider
|
|
168
|
+
onAction={(action) => {
|
|
169
|
+
if (action === "submit") handleSubmit();
|
|
170
|
+
if (action === "cancel") handleCancel();
|
|
171
|
+
}}
|
|
172
|
+
>
|
|
173
|
+
{children}
|
|
174
|
+
</ActionProvider>
|
|
173
175
|
```
|
|
174
176
|
|
|
175
|
-
|
|
177
|
+
### VisibilityProvider
|
|
176
178
|
|
|
177
|
-
|
|
179
|
+
Control element visibility based on data:
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
<VisibilityProvider>
|
|
183
|
+
{children}
|
|
184
|
+
</VisibilityProvider>
|
|
185
|
+
|
|
186
|
+
// Elements can use visibility conditions:
|
|
187
|
+
{
|
|
188
|
+
"type": "Alert",
|
|
189
|
+
"props": { "message": "Error!" },
|
|
190
|
+
"visible": { "path": "/form/hasError" }
|
|
191
|
+
}
|
|
192
|
+
```
|
|
178
193
|
|
|
179
|
-
|
|
180
|
-
- `DataProvider` - Data model context
|
|
181
|
-
- `VisibilityProvider` - Visibility evaluation context
|
|
182
|
-
- `ActionProvider` - Action execution context
|
|
183
|
-
- `ValidationProvider` - Validation context
|
|
194
|
+
### ValidationProvider
|
|
184
195
|
|
|
185
|
-
|
|
196
|
+
Add field validation:
|
|
186
197
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
198
|
+
```tsx
|
|
199
|
+
<ValidationProvider>
|
|
200
|
+
{children}
|
|
201
|
+
</ValidationProvider>
|
|
202
|
+
|
|
203
|
+
// Use validation hooks:
|
|
204
|
+
const { errors, validate } = useFieldValidation("/form/email", {
|
|
205
|
+
checks: [
|
|
206
|
+
{ fn: "required", message: "Email required" },
|
|
207
|
+
{ fn: "email", message: "Invalid email" },
|
|
208
|
+
],
|
|
209
|
+
});
|
|
210
|
+
```
|
|
196
211
|
|
|
197
|
-
|
|
212
|
+
## Hooks
|
|
198
213
|
|
|
199
|
-
|
|
200
|
-
|
|
214
|
+
| Hook | Purpose |
|
|
215
|
+
|------|---------|
|
|
216
|
+
| `useData()` | Access data context (`data`, `get`, `set`) |
|
|
217
|
+
| `useDataValue(path)` | Get single value from data |
|
|
218
|
+
| `useVisibility()` | Access visibility evaluation |
|
|
219
|
+
| `useIsVisible(condition)` | Check if condition is met |
|
|
220
|
+
| `useActions()` | Access action context |
|
|
221
|
+
| `useFieldValidation(path, config)` | Field validation state |
|
|
201
222
|
|
|
202
|
-
|
|
223
|
+
## Visibility Conditions
|
|
203
224
|
|
|
204
|
-
|
|
205
|
-
|
|
225
|
+
```typescript
|
|
226
|
+
// Simple path check (truthy)
|
|
227
|
+
{ "path": "/user/isAdmin" }
|
|
228
|
+
|
|
229
|
+
// Auth state
|
|
230
|
+
{ "auth": "signedIn" }
|
|
231
|
+
|
|
232
|
+
// Comparisons
|
|
233
|
+
{ "eq": [{ "path": "/status" }, "active"] }
|
|
234
|
+
{ "gt": [{ "path": "/count" }, 10] }
|
|
235
|
+
|
|
236
|
+
// Logical operators
|
|
237
|
+
{
|
|
238
|
+
"and": [
|
|
239
|
+
{ "path": "/feature/enabled" },
|
|
240
|
+
{ "not": { "path": "/maintenance" } }
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
{
|
|
245
|
+
"or": [
|
|
246
|
+
{ "path": "/user/isAdmin" },
|
|
247
|
+
{ "path": "/user/isModerator" }
|
|
248
|
+
]
|
|
249
|
+
}
|
|
250
|
+
```
|
|
206
251
|
|
|
207
252
|
## Component Props
|
|
208
253
|
|
|
209
|
-
|
|
254
|
+
When using `defineRegistry`, components receive these props:
|
|
210
255
|
|
|
211
256
|
```typescript
|
|
212
|
-
interface
|
|
213
|
-
|
|
214
|
-
children?: ReactNode;
|
|
215
|
-
onAction?: (action:
|
|
216
|
-
loading?: boolean;
|
|
257
|
+
interface ComponentContext<P> {
|
|
258
|
+
props: P; // Typed props from the catalog
|
|
259
|
+
children?: React.ReactNode; // Rendered children
|
|
260
|
+
onAction?: (action: { name: string; params?: Record<string, unknown> }) => void;
|
|
261
|
+
loading?: boolean; // Whether the parent is loading
|
|
217
262
|
}
|
|
218
263
|
```
|
|
219
264
|
|
|
220
|
-
##
|
|
265
|
+
## Generate AI Prompts
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
const systemPrompt = catalog.prompt();
|
|
269
|
+
// Returns detailed prompt with component/action descriptions
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Full Example
|
|
221
273
|
|
|
222
274
|
```tsx
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
275
|
+
import { defineCatalog } from "@json-render/core";
|
|
276
|
+
import { schema, defineRegistry, Renderer } from "@json-render/react";
|
|
277
|
+
import { z } from "zod";
|
|
278
|
+
|
|
279
|
+
const catalog = defineCatalog(schema, {
|
|
280
|
+
components: {
|
|
281
|
+
Greeting: {
|
|
282
|
+
props: z.object({ name: z.string() }),
|
|
283
|
+
description: "Displays a greeting",
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
actions: {},
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
const { registry } = defineRegistry(catalog, {
|
|
290
|
+
components: {
|
|
291
|
+
Greeting: ({ props }) => <h1>Hello, {props.name}!</h1>,
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const spec = {
|
|
296
|
+
root: {
|
|
297
|
+
type: "Greeting",
|
|
298
|
+
props: { name: "World" },
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
function App() {
|
|
303
|
+
return <Renderer spec={spec} registry={registry} />;
|
|
237
304
|
}
|
|
238
305
|
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// src/schema.ts
|
|
2
|
+
import { defineSchema } from "@json-render/core";
|
|
3
|
+
var schema = defineSchema((s) => ({
|
|
4
|
+
// What the AI-generated SPEC looks like
|
|
5
|
+
spec: s.object({
|
|
6
|
+
/** Root element key */
|
|
7
|
+
root: s.string(),
|
|
8
|
+
/** Flat map of elements by key */
|
|
9
|
+
elements: s.record(
|
|
10
|
+
s.object({
|
|
11
|
+
/** Unique key for this element */
|
|
12
|
+
key: s.string(),
|
|
13
|
+
/** Component type from catalog */
|
|
14
|
+
type: s.ref("catalog.components"),
|
|
15
|
+
/** Component props */
|
|
16
|
+
props: s.propsOf("catalog.components"),
|
|
17
|
+
/** Child element keys (flat reference) */
|
|
18
|
+
children: s.array(s.string()),
|
|
19
|
+
/** Parent element key (null for root) */
|
|
20
|
+
parentKey: s.string(),
|
|
21
|
+
/** Visibility condition */
|
|
22
|
+
visible: s.any()
|
|
23
|
+
})
|
|
24
|
+
)
|
|
25
|
+
}),
|
|
26
|
+
// What the CATALOG must provide
|
|
27
|
+
catalog: s.object({
|
|
28
|
+
/** Component definitions */
|
|
29
|
+
components: s.map({
|
|
30
|
+
/** Zod schema for component props */
|
|
31
|
+
props: s.zod(),
|
|
32
|
+
/** Slots for this component. Use ['default'] for children, or named slots like ['header', 'footer'] */
|
|
33
|
+
slots: s.array(s.string()),
|
|
34
|
+
/** Description for AI generation hints */
|
|
35
|
+
description: s.string()
|
|
36
|
+
}),
|
|
37
|
+
/** Action definitions (optional) */
|
|
38
|
+
actions: s.map({
|
|
39
|
+
/** Zod schema for action params */
|
|
40
|
+
params: s.zod(),
|
|
41
|
+
/** Description for AI generation hints */
|
|
42
|
+
description: s.string()
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
}));
|
|
46
|
+
var elementTreeSchema = schema;
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
schema,
|
|
50
|
+
elementTreeSchema
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=chunk-IGPI5WNB.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts"],"sourcesContent":["import { defineSchema } from \"@json-render/core\";\n\n/**\n * The schema for @json-render/react\n *\n * Defines:\n * - Spec: A flat tree of elements with keys, types, props, and children references\n * - Catalog: Components with props schemas, and optional actions\n */\nexport const schema = defineSchema((s) => ({\n // What the AI-generated SPEC looks like\n spec: s.object({\n /** Root element key */\n root: s.string(),\n /** Flat map of elements by key */\n elements: s.record(\n s.object({\n /** Unique key for this element */\n key: s.string(),\n /** Component type from catalog */\n type: s.ref(\"catalog.components\"),\n /** Component props */\n props: s.propsOf(\"catalog.components\"),\n /** Child element keys (flat reference) */\n children: s.array(s.string()),\n /** Parent element key (null for root) */\n parentKey: s.string(),\n /** Visibility condition */\n visible: s.any(),\n }),\n ),\n }),\n\n // What the CATALOG must provide\n catalog: s.object({\n /** Component definitions */\n components: s.map({\n /** Zod schema for component props */\n props: s.zod(),\n /** Slots for this component. Use ['default'] for children, or named slots like ['header', 'footer'] */\n slots: s.array(s.string()),\n /** Description for AI generation hints */\n description: s.string(),\n }),\n /** Action definitions (optional) */\n actions: s.map({\n /** Zod schema for action params */\n params: s.zod(),\n /** Description for AI generation hints */\n description: s.string(),\n }),\n }),\n}));\n\n/**\n * Type for the React schema\n */\nexport type ReactSchema = typeof schema;\n\n/**\n * Infer the spec type from a catalog\n */\nexport type ReactSpec<TCatalog> = typeof schema extends {\n createCatalog: (catalog: TCatalog) => { _specType: infer S };\n}\n ? S\n : never;\n\n// Backward compatibility aliases\n/** @deprecated Use `schema` instead */\nexport const elementTreeSchema = schema;\n/** @deprecated Use `ReactSchema` instead */\nexport type ElementTreeSchema = ReactSchema;\n/** @deprecated Use `ReactSpec` instead */\nexport type ElementTreeSpec<T> = ReactSpec<T>;\n"],"mappings":";AAAA,SAAS,oBAAoB;AAStB,IAAM,SAAS,aAAa,CAAC,OAAO;AAAA;AAAA,EAEzC,MAAM,EAAE,OAAO;AAAA;AAAA,IAEb,MAAM,EAAE,OAAO;AAAA;AAAA,IAEf,UAAU,EAAE;AAAA,MACV,EAAE,OAAO;AAAA;AAAA,QAEP,KAAK,EAAE,OAAO;AAAA;AAAA,QAEd,MAAM,EAAE,IAAI,oBAAoB;AAAA;AAAA,QAEhC,OAAO,EAAE,QAAQ,oBAAoB;AAAA;AAAA,QAErC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA;AAAA,QAE5B,WAAW,EAAE,OAAO;AAAA;AAAA,QAEpB,SAAS,EAAE,IAAI;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAAA;AAAA,EAGD,SAAS,EAAE,OAAO;AAAA;AAAA,IAEhB,YAAY,EAAE,IAAI;AAAA;AAAA,MAEhB,OAAO,EAAE,IAAI;AAAA;AAAA,MAEb,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA;AAAA,MAEzB,aAAa,EAAE,OAAO;AAAA,IACxB,CAAC;AAAA;AAAA,IAED,SAAS,EAAE,IAAI;AAAA;AAAA,MAEb,QAAQ,EAAE,IAAI;AAAA;AAAA,MAEd,aAAa,EAAE,OAAO;AAAA,IACxB,CAAC;AAAA,EACH,CAAC;AACH,EAAE;AAkBK,IAAM,oBAAoB;","names":[]}
|