autoui-react 0.0.3-alpha
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 +244 -0
- package/dist/index.css +56 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +546 -0
- package/dist/index.d.ts +546 -0
- package/dist/index.js +1466 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1449 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +65 -0
package/README.md
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# autoui-react
|
|
2
|
+
|
|
3
|
+
A React + TypeScript runtime that **generates goal-oriented UIs in real-time** using an LLM + your data schema.
|
|
4
|
+
|
|
5
|
+
> Import one component, declare your schema, give a goal, get a working multi-step UI with implicit shimmer fallbacks.
|
|
6
|
+
|
|
7
|
+
## Inspiration
|
|
8
|
+
|
|
9
|
+
This library was inspired by the paper ["Generative and Malleable User Interfaces with Generative and Evolving Task-Driven Data Model"](https://dl.acm.org/doi/10.1145/3706598.3713285) (CHI 2025), which proposes a model-driven approach to UI generation. The paper introduces the concept of using LLMs to interpret users' goals and generate data models that serve as the foundation for UI generation - a concept this library puts into practice.
|
|
10
|
+
|
|
11
|
+
As the paper states, "We adopt the canonical perspective that user interfaces are graphical representations of underlying data models that describe the intended tasks" and proposes "leveraging Large Language Models (LLMs) to interpret users' prompts and generate a task-driven data model—a structured representation of the essential entities, relationships, and data properties relevant to the intended task."
|
|
12
|
+
|
|
13
|
+
This library implements this approach, using LLMs to interpret a goal and schema to generate a UI specification that can be rendered with React components.
|
|
14
|
+
|
|
15
|
+
## Feature Highlights
|
|
16
|
+
|
|
17
|
+
- **Declarative input only** – supply schema + goal; runtime handles the rest
|
|
18
|
+
- **Incremental AI planning** – UI evolves one interaction at a time
|
|
19
|
+
- **Partial UI updates** – only refresh the parts of the UI that need updating
|
|
20
|
+
- **Zero-config fallbacks** – shimmer placeholders generated automatically
|
|
21
|
+
- **Adapter pattern** – map abstract nodes → any React component library (starting with shadcn)
|
|
22
|
+
- **Type-safety end-to-end** – all AI messages validated by Zod
|
|
23
|
+
- **Streaming UX** – uses @vercel/ai to stream planner output and render progressively
|
|
24
|
+
- **System events** – hook into the AI planning lifecycle to observe or extend behavior
|
|
25
|
+
- **Schema adapters** – connect to multiple database types with Drizzle support out of the box
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install autoui-react
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```jsx
|
|
36
|
+
import { AutoUI } from 'autoui-react';
|
|
37
|
+
import { emailsTable, usersTable } from './schema';
|
|
38
|
+
|
|
39
|
+
function App() {
|
|
40
|
+
return (
|
|
41
|
+
<AutoUI
|
|
42
|
+
schema={{ emails: emailsTable, users: usersTable }}
|
|
43
|
+
goal="Create an email inbox with list and detail views"
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
That's it! AutoUI will:
|
|
50
|
+
1. Generate a UI based on your schema and goal
|
|
51
|
+
2. Show shimmer placeholders while loading
|
|
52
|
+
3. Handle data binding and events automatically
|
|
53
|
+
|
|
54
|
+
## API Reference
|
|
55
|
+
|
|
56
|
+
### `<AutoUI>` Component
|
|
57
|
+
|
|
58
|
+
| Prop | Type | Required | Description |
|
|
59
|
+
|------|------|----------|-------------|
|
|
60
|
+
| `schema` | `Record<string, unknown>` \| `AdapterConfig` | Yes | Your data schema or schema adapter config |
|
|
61
|
+
| `goal` | `string` | Yes | What you want the UI to do |
|
|
62
|
+
| `componentAdapter` | `'shadcn'` | No | UI component library to use (default: `'shadcn'`) |
|
|
63
|
+
| `userContext` | `Record<string, unknown>` | No | User information (id, role, etc.) |
|
|
64
|
+
| `onEvent` | `(evt: UIEvent) => void` | No | Callback for UI events |
|
|
65
|
+
| `eventHooks` | `{ [eventType]: EventHook[] }` | No | UI event hooks for interception |
|
|
66
|
+
| `systemEventHooks` | `{ [SystemEventType]: SystemEventHook[] }` | No | Hooks into internal system events |
|
|
67
|
+
| `enablePartialUpdates` | `boolean` | No | Only update parts of the UI that change (default: `true`) |
|
|
68
|
+
| `updatePatterns` | `{ enable* }` | No | Configure which partial update patterns to use |
|
|
69
|
+
| `debugMode` | `boolean` | No | Enable console logging of system events |
|
|
70
|
+
| `mockMode` | `boolean` | No | Use mock data for development (default: `true` in dev) |
|
|
71
|
+
| `planningConfig` | `{ prefetchDepth?, temperature?, streaming? }` | No | Configure the AI planning process |
|
|
72
|
+
|
|
73
|
+
### Partial UI Updates
|
|
74
|
+
|
|
75
|
+
AutoUI can selectively update only the portions of the UI that need to change, rather than regenerating the entire interface on each interaction. This results in:
|
|
76
|
+
|
|
77
|
+
- **Better performance**: Only updating what changes is more efficient
|
|
78
|
+
- **Improved UX**: Maintains UI state between interactions
|
|
79
|
+
- **Reduced LLM usage**: Smaller, more focused prompts
|
|
80
|
+
|
|
81
|
+
To use partial updates:
|
|
82
|
+
|
|
83
|
+
```jsx
|
|
84
|
+
<AutoUI
|
|
85
|
+
schema={mySchema}
|
|
86
|
+
goal="Create a project dashboard with list and detail views"
|
|
87
|
+
enablePartialUpdates={true}
|
|
88
|
+
updatePatterns={{
|
|
89
|
+
enableDetailViews: true, // Show/hide details in a side panel
|
|
90
|
+
enableDropdowns: true, // Add dropdown menus to elements
|
|
91
|
+
enableExpandCollapse: true, // Expand/collapse sections
|
|
92
|
+
enableFormNavigation: true, // Navigate multi-step forms
|
|
93
|
+
}}
|
|
94
|
+
/>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The AI will now intelligently determine which parts of the UI to update based on user interactions. For example, clicking on an item in a list will only update the detail view rather than regenerating the entire page.
|
|
98
|
+
|
|
99
|
+
### Schema Configuration
|
|
100
|
+
|
|
101
|
+
AutoUI supports different ways to provide your data schema:
|
|
102
|
+
|
|
103
|
+
#### 1. Direct Schema Object
|
|
104
|
+
|
|
105
|
+
```jsx
|
|
106
|
+
<AutoUI
|
|
107
|
+
schema={{
|
|
108
|
+
users: {
|
|
109
|
+
tableName: 'users',
|
|
110
|
+
columns: {
|
|
111
|
+
id: { type: 'serial', primaryKey: true },
|
|
112
|
+
name: { type: 'text', notNull: true },
|
|
113
|
+
email: { type: 'text', notNull: true },
|
|
114
|
+
},
|
|
115
|
+
sampleData: [
|
|
116
|
+
{ id: 1, name: 'John', email: 'john@example.com' }
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
}}
|
|
120
|
+
goal="Create a user management interface"
|
|
121
|
+
/>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### 2. Using Drizzle Adapter
|
|
125
|
+
|
|
126
|
+
```jsx
|
|
127
|
+
import { AutoUI } from 'autoui-react';
|
|
128
|
+
import { db } from './db'; // Your Drizzle instance
|
|
129
|
+
import { users, posts } from './schema'; // Drizzle schema
|
|
130
|
+
|
|
131
|
+
function MyApp() {
|
|
132
|
+
return (
|
|
133
|
+
<AutoUI
|
|
134
|
+
schema={{
|
|
135
|
+
type: 'drizzle',
|
|
136
|
+
options: {
|
|
137
|
+
schema: { users, posts },
|
|
138
|
+
client: {
|
|
139
|
+
client: db,
|
|
140
|
+
// Optional custom query function
|
|
141
|
+
queryFn: async (tableName, query) => {
|
|
142
|
+
// Custom query logic here
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}}
|
|
148
|
+
goal="Create a user management dashboard"
|
|
149
|
+
/>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### 3. Using Mock Data
|
|
155
|
+
|
|
156
|
+
```jsx
|
|
157
|
+
<AutoUI
|
|
158
|
+
schema={{
|
|
159
|
+
type: 'drizzle',
|
|
160
|
+
options: {
|
|
161
|
+
schema: { users, posts },
|
|
162
|
+
useMockData: true,
|
|
163
|
+
mockData: {
|
|
164
|
+
users: [
|
|
165
|
+
{ id: 1, name: 'John', email: 'john@example.com' },
|
|
166
|
+
{ id: 2, name: 'Jane', email: 'jane@example.com' }
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}}
|
|
171
|
+
goal="Create a user management dashboard"
|
|
172
|
+
/>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### System Events
|
|
176
|
+
|
|
177
|
+
AutoUI provides hooks into its internal planning and rendering process through system events. You can subscribe to these events to monitor or extend the functionality.
|
|
178
|
+
|
|
179
|
+
```jsx
|
|
180
|
+
import { AutoUI, SystemEventType } from 'autoui-react';
|
|
181
|
+
|
|
182
|
+
function MyApp() {
|
|
183
|
+
return (
|
|
184
|
+
<AutoUI
|
|
185
|
+
schema={mySchema}
|
|
186
|
+
goal="Create a user management dashboard"
|
|
187
|
+
systemEventHooks={{
|
|
188
|
+
// Log when planning starts
|
|
189
|
+
[SystemEventType.PLAN_START]: [(event) => {
|
|
190
|
+
console.log('Planning started with input:', event.plannerInput);
|
|
191
|
+
}],
|
|
192
|
+
|
|
193
|
+
// Measure performance of data fetching
|
|
194
|
+
[SystemEventType.DATA_FETCH_COMPLETE]: [(event) => {
|
|
195
|
+
console.log(`Fetched ${event.results.length} rows from ${event.tableName} in ${event.executionTimeMs}ms`);
|
|
196
|
+
}]
|
|
197
|
+
}}
|
|
198
|
+
/>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### Available System Events
|
|
204
|
+
|
|
205
|
+
| Event Type | Description | Data Properties |
|
|
206
|
+
|------------|-------------|-----------------|
|
|
207
|
+
| `PLAN_START` | Planning process started | `plannerInput` |
|
|
208
|
+
| `PLAN_PROMPT_CREATED` | Prompt for LLM generated | `prompt` |
|
|
209
|
+
| `PLAN_RESPONSE_CHUNK` | Received chunk from LLM | `chunk`, `isComplete` |
|
|
210
|
+
| `PLAN_COMPLETE` | Planning process completed | `layout`, `executionTimeMs` |
|
|
211
|
+
| `PLAN_ERROR` | Error during planning | `error` |
|
|
212
|
+
| `BINDING_RESOLUTION_START` | Started resolving data bindings | `layout` |
|
|
213
|
+
| `BINDING_RESOLUTION_COMPLETE` | Completed binding resolution | `originalLayout`, `resolvedLayout` |
|
|
214
|
+
| `DATA_FETCH_START` | Started fetching data | `tableName`, `query` |
|
|
215
|
+
| `DATA_FETCH_COMPLETE` | Completed data fetch | `tableName`, `results`, `executionTimeMs` |
|
|
216
|
+
| `RENDER_START` | Started rendering | `layout` |
|
|
217
|
+
| `RENDER_COMPLETE` | Completed rendering | `layout`, `renderTimeMs` |
|
|
218
|
+
|
|
219
|
+
## Development
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# Install dependencies
|
|
223
|
+
npm install
|
|
224
|
+
|
|
225
|
+
# Run development build with watch mode
|
|
226
|
+
npm run dev
|
|
227
|
+
|
|
228
|
+
# Run tests
|
|
229
|
+
npm test
|
|
230
|
+
|
|
231
|
+
# Build for production
|
|
232
|
+
npm run build
|
|
233
|
+
|
|
234
|
+
# Run the example app
|
|
235
|
+
npm run example
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
MIT
|
|
241
|
+
|
|
242
|
+
## Contributing
|
|
243
|
+
|
|
244
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
package/dist/index.css
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/* src/styles/autoui.css */
|
|
2
|
+
.autoui-root {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
height: 100%;
|
|
6
|
+
width: 100%;
|
|
7
|
+
}
|
|
8
|
+
.autoui-loading {
|
|
9
|
+
width: 100%;
|
|
10
|
+
height: 100%;
|
|
11
|
+
}
|
|
12
|
+
.autoui-shimmer-container {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
gap: 1rem;
|
|
16
|
+
padding: 1rem;
|
|
17
|
+
}
|
|
18
|
+
.autoui-shimmer-header {
|
|
19
|
+
height: 2.5rem;
|
|
20
|
+
background-color: #e5e7eb;
|
|
21
|
+
border-radius: 0.25rem;
|
|
22
|
+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
23
|
+
}
|
|
24
|
+
.autoui-shimmer-content {
|
|
25
|
+
height: 16rem;
|
|
26
|
+
background-color: #e5e7eb;
|
|
27
|
+
border-radius: 0.25rem;
|
|
28
|
+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
29
|
+
}
|
|
30
|
+
@keyframes pulse {
|
|
31
|
+
0%, 100% {
|
|
32
|
+
opacity: 1;
|
|
33
|
+
}
|
|
34
|
+
50% {
|
|
35
|
+
opacity: 0.5;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
.autoui-content {
|
|
39
|
+
flex: 1;
|
|
40
|
+
width: 100%;
|
|
41
|
+
}
|
|
42
|
+
.autoui-error {
|
|
43
|
+
padding: 1rem;
|
|
44
|
+
border: 1px solid #fca5a5;
|
|
45
|
+
background-color: #fee2e2;
|
|
46
|
+
color: #b91c1c;
|
|
47
|
+
border-radius: 0.25rem;
|
|
48
|
+
margin-top: 1rem;
|
|
49
|
+
}
|
|
50
|
+
.autoui-error-title {
|
|
51
|
+
font-weight: 600;
|
|
52
|
+
}
|
|
53
|
+
.autoui-error-message {
|
|
54
|
+
font-size: 0.875rem;
|
|
55
|
+
}
|
|
56
|
+
/*# sourceMappingURL=index.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/styles/autoui.css"],"sourcesContent":["/* AutoUI Component Styles */\n\n.autoui-root {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n}\n\n/* Loading states */\n.autoui-loading {\n width: 100%;\n height: 100%;\n}\n\n.autoui-shimmer-container {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n padding: 1rem;\n}\n\n.autoui-shimmer-header {\n height: 2.5rem;\n background-color: #e5e7eb;\n border-radius: 0.25rem;\n animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n\n.autoui-shimmer-content {\n height: 16rem;\n background-color: #e5e7eb;\n border-radius: 0.25rem;\n animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n\n@keyframes pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n\n/* Content */\n.autoui-content {\n flex: 1;\n width: 100%;\n}\n\n/* Error states */\n.autoui-error {\n padding: 1rem;\n border: 1px solid #fca5a5;\n background-color: #fee2e2;\n color: #b91c1c;\n border-radius: 0.25rem;\n margin-top: 1rem;\n}\n\n.autoui-error-title {\n font-weight: 600;\n}\n\n.autoui-error-message {\n font-size: 0.875rem;\n} "],"mappings":";AAEA,CAAC;AACC,WAAS;AACT,kBAAgB;AAChB,UAAQ;AACR,SAAO;AACT;AAGA,CAAC;AACC,SAAO;AACP,UAAQ;AACV;AAEA,CAAC;AACC,WAAS;AACT,kBAAgB;AAChB,OAAK;AACL,WAAS;AACX;AAEA,CAAC;AACC,UAAQ;AACR,oBAAkB;AAClB,iBAAe;AACf,aAAW,MAAM,GAAG,aAAa,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG;AACnD;AAEA,CAAC;AACC,UAAQ;AACR,oBAAkB;AAClB,iBAAe;AACf,aAAW,MAAM,GAAG,aAAa,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG;AACnD;AAEA,WAVa;AAWX;AACE,aAAS;AACX;AACA;AACE,aAAS;AACX;AACF;AAGA,CAAC;AACC,QAAM;AACN,SAAO;AACT;AAGA,CAAC;AACC,WAAS;AACT,UAAQ,IAAI,MAAM;AAClB,oBAAkB;AAClB,SAAO;AACP,iBAAe;AACf,cAAY;AACd;AAEA,CAAC;AACC,eAAa;AACf;AAEA,CAAC;AACC,aAAW;AACb;","names":[]}
|