@elizaos/plugin-ui 2.0.0-alpha.1

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 ADDED
@@ -0,0 +1,318 @@
1
+ # @elizaos/plugin-ui
2
+
3
+ Schema-driven configuration UI for ElizaOS plugins. Provides 23 field type renderers, a responsive grid layout, validation, conditional visibility, and design tokens for consistent rendering.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @elizaos/plugin-ui
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```tsx
14
+ import { ConfigRenderer, defaultRegistry } from "@elizaos/plugin-ui";
15
+ import type { ConfigUiHint } from "@elizaos/plugin-ui";
16
+
17
+ const schema = {
18
+ type: "object",
19
+ properties: {
20
+ apiKey: { type: "string" },
21
+ model: { type: "string", enum: ["gpt-4", "gpt-3.5-turbo"] },
22
+ temperature: { type: "number", minimum: 0, maximum: 2 },
23
+ },
24
+ required: ["apiKey"],
25
+ };
26
+
27
+ const hints: Record<string, ConfigUiHint> = {
28
+ apiKey: { label: "API Key", sensitive: true, help: "Your API key" },
29
+ model: { label: "Model", type: "select", width: "half" },
30
+ temperature: { label: "Temperature", width: "half", min: 0, max: 2, step: 0.1 },
31
+ };
32
+
33
+ function PluginSettings() {
34
+ const [values, setValues] = useState({});
35
+ return (
36
+ <ConfigRenderer
37
+ schema={schema}
38
+ hints={hints}
39
+ values={values}
40
+ registry={defaultRegistry}
41
+ onChange={(key, value) => setValues(prev => ({ ...prev, [key]: value }))}
42
+ />
43
+ );
44
+ }
45
+ ```
46
+
47
+ ## Field Types (23)
48
+
49
+ ### Primitives
50
+
51
+ | Type | Description | Auto-detected from |
52
+ |------|-------------|-------------------|
53
+ | `text` | Single-line text input | Default for strings |
54
+ | `password` | Masked input with show/hide toggle | `sensitive: true` hint |
55
+ | `number` | Numeric input with min/max/step | `type: "number"` in schema |
56
+ | `boolean` | Toggle switch | `type: "boolean"` in schema |
57
+ | `textarea` | Multi-line text input | `maxLength > 200` in schema |
58
+
59
+ ### Selection
60
+
61
+ | Type | Description | Auto-detected from |
62
+ |------|-------------|-------------------|
63
+ | `select` | Dropdown selector | `enum` in schema (4+ options) |
64
+ | `multiselect` | Checkbox group for multiple values | `type: "array"` + `items.enum` |
65
+ | `radio` | Radio button group with descriptions | `hint.type: "radio"` |
66
+ | `checkbox-group` | Checkbox list with per-option descriptions | `hint.type: "checkbox-group"` |
67
+
68
+ ### Specialized
69
+
70
+ | Type | Description | Auto-detected from |
71
+ |------|-------------|-------------------|
72
+ | `url` | URL input with validation | `format: "uri"` in schema |
73
+ | `email` | Email input with validation | `format: "email"` in schema |
74
+ | `color` | Color picker swatch + hex input | `format: "color"` in schema |
75
+ | `date` | Date picker | `format: "date"` in schema |
76
+ | `datetime` | Date + time picker | `format: "date-time"` in schema |
77
+ | `json` | JSON editor with validation | `type: "object"` in schema |
78
+ | `code` | Monospaced code editor | `hint.type: "code"` |
79
+ | `markdown` | Markdown editor with preview toggle | `hint.type: "markdown"` |
80
+ | `file` | File path input | `hint.type: "file"` |
81
+
82
+ ### Layout & Structured
83
+
84
+ | Type | Description | Auto-detected from |
85
+ |------|-------------|-------------------|
86
+ | `array` | Add/remove items list | `type: "array"` in schema |
87
+ | `keyvalue` | Key-value pair editor | `additionalProperties` in schema |
88
+ | `group` | Fieldset container with legend | `hint.type: "group"` |
89
+ | `table` | Tabular data editor with rows/columns | `hint.type: "table"` |
90
+ | `custom` | Plugin-provided React component | `hint.type: "custom"` |
91
+
92
+ ## ConfigUiHint Reference
93
+
94
+ ```typescript
95
+ interface ConfigUiHint {
96
+ // Display
97
+ label?: string; // Field label
98
+ help?: string; // Help text below the field
99
+ placeholder?: string; // Input placeholder
100
+ icon?: string; // Icon identifier
101
+
102
+ // Behavior
103
+ type?: string; // Explicit field type override
104
+ sensitive?: boolean; // Mask value, show/hide toggle
105
+ readonly?: boolean; // Render as disabled
106
+ advanced?: boolean; // Show in collapsed "Advanced" section
107
+ hidden?: boolean; // Don't render at all
108
+
109
+ // Layout
110
+ order?: number; // Sort order (lower = first)
111
+ group?: string; // Group heading (e.g., "API Settings")
112
+ width?: "full" | "half" | "third"; // Grid column width
113
+
114
+ // Validation
115
+ pattern?: string; // Regex pattern for string values
116
+ patternError?: string; // Custom error message for pattern mismatch
117
+
118
+ // Conditional visibility
119
+ showIf?: {
120
+ field: string;
121
+ op: "eq" | "neq" | "in" | "truthy" | "falsy";
122
+ value?: unknown;
123
+ };
124
+
125
+ // For select / radio / multiselect / checkbox-group
126
+ options?: Array<{
127
+ value: string;
128
+ label: string;
129
+ description?: string;
130
+ icon?: string;
131
+ disabled?: boolean;
132
+ }>;
133
+
134
+ // For number fields
135
+ min?: number;
136
+ max?: number;
137
+ step?: number;
138
+ unit?: string; // Display unit (e.g., "ms", "tokens")
139
+
140
+ // For array fields
141
+ itemSchema?: ConfigUiHint;
142
+ minItems?: number;
143
+ maxItems?: number;
144
+
145
+ // For custom components
146
+ component?: string; // React component name
147
+ }
148
+ ```
149
+
150
+ ## Responsive Grid Layout
151
+
152
+ Fields support three width modes via `width` hint:
153
+
154
+ | Width | Desktop | Mobile |
155
+ |-------|---------|--------|
156
+ | `"full"` (default) | 100% | 100% |
157
+ | `"half"` | 50% | 100% |
158
+ | `"third"` | 33% | 100% |
159
+
160
+ ```typescript
161
+ const hints = {
162
+ firstName: { label: "First Name", width: "half" },
163
+ lastName: { label: "Last Name", width: "half" },
164
+ port: { label: "Port", width: "third" },
165
+ host: { label: "Host", width: "third" },
166
+ protocol: { label: "Protocol", width: "third" },
167
+ };
168
+ ```
169
+
170
+ ## Groups & Advanced Fields
171
+
172
+ Fields with the same `group` value are rendered together under a heading:
173
+
174
+ ```typescript
175
+ const hints = {
176
+ apiKey: { label: "API Key", group: "Authentication" },
177
+ apiSecret: { label: "API Secret", group: "Authentication", sensitive: true },
178
+ debugMode: { label: "Debug Mode", advanced: true },
179
+ logLevel: { label: "Log Level", advanced: true },
180
+ };
181
+ ```
182
+
183
+ Advanced fields are collapsed by default with an expandable toggle.
184
+
185
+ ## Conditional Visibility
186
+
187
+ Show or hide fields based on other field values:
188
+
189
+ ```typescript
190
+ const hints = {
191
+ authType: {
192
+ label: "Auth Type",
193
+ type: "radio",
194
+ options: [
195
+ { value: "apikey", label: "API Key" },
196
+ { value: "oauth", label: "OAuth" },
197
+ ],
198
+ },
199
+ apiKey: {
200
+ label: "API Key",
201
+ showIf: { field: "authType", op: "eq", value: "apikey" },
202
+ },
203
+ clientId: {
204
+ label: "Client ID",
205
+ showIf: { field: "authType", op: "eq", value: "oauth" },
206
+ },
207
+ };
208
+ ```
209
+
210
+ Operators: `eq`, `neq`, `in`, `truthy`, `falsy`.
211
+
212
+ ## Design Tokens
213
+
214
+ The `PluginUiTheme` interface defines standard design tokens:
215
+
216
+ ```typescript
217
+ import { DEFAULT_PLUGIN_UI_THEME } from "@elizaos/plugin-ui";
218
+
219
+ // Override specific tokens
220
+ const theme = {
221
+ ...DEFAULT_PLUGIN_UI_THEME,
222
+ fieldGap: "1.25rem",
223
+ inputHeight: "2.5rem",
224
+ };
225
+ ```
226
+
227
+ | Token | Default | CSS Variable |
228
+ |-------|---------|-------------|
229
+ | `fieldGap` | `1rem` | -- |
230
+ | `groupGap` | `1.5rem` | -- |
231
+ | `labelSize` | `0.8125rem` | -- |
232
+ | `helpSize` | `0.6875rem` | -- |
233
+ | `errorSize` | `0.6875rem` | -- |
234
+ | `labelColor` | `var(--txt)` | `--txt` |
235
+ | `helpColor` | `var(--muted)` | `--muted` |
236
+ | `errorColor` | `var(--destructive)` | `--destructive` |
237
+ | `borderColor` | `var(--border)` | `--border` |
238
+ | `focusRing` | `var(--accent)` | `--accent` |
239
+ | `inputHeight` | `2.25rem` | -- |
240
+ | `maxFieldWidth` | `32rem` | -- |
241
+
242
+ ## Custom Field Renderers
243
+
244
+ Plugin authors can create custom renderers:
245
+
246
+ ```tsx
247
+ import type { FieldRenderProps, FieldRenderer } from "@elizaos/plugin-ui";
248
+
249
+ const renderSliderField: FieldRenderer = (props: FieldRenderProps) => {
250
+ const value = typeof props.value === "number" ? props.value : 0;
251
+ return (
252
+ <input
253
+ type="range"
254
+ min={props.hint.min ?? 0}
255
+ max={props.hint.max ?? 100}
256
+ step={props.hint.step ?? 1}
257
+ value={value}
258
+ onChange={(e) => props.onChange(Number(e.target.value))}
259
+ disabled={props.readonly}
260
+ />
261
+ );
262
+ };
263
+ ```
264
+
265
+ Register custom renderers via `extendRegistry`:
266
+
267
+ ```tsx
268
+ import { extendRegistry, defaultRegistry } from "@elizaos/plugin-ui";
269
+
270
+ const myRegistry = extendRegistry(defaultRegistry, {
271
+ slider: renderSliderField,
272
+ });
273
+ ```
274
+
275
+ ## Validation
276
+
277
+ ConfigRenderer validates fields against JSON Schema and custom patterns:
278
+
279
+ - **Required fields**: Red accent bar + "Required" badge
280
+ - **Pattern validation**: Regex patterns with custom error messages
281
+ - **Zod validators**: Per-field-type validators (email format, URL format, etc.)
282
+ - **Inline errors**: Shown below each field
283
+ - **Summary**: Clickable error count at the top with scroll-to-field
284
+
285
+ ## API Reference
286
+
287
+ ### ConfigRenderer Props
288
+
289
+ | Prop | Type | Description |
290
+ |------|------|-------------|
291
+ | `schema` | `JsonSchemaObject` | JSON Schema for the config object |
292
+ | `hints` | `Record<string, ConfigUiHint>` | UI hints keyed by field name |
293
+ | `values` | `Record<string, unknown>` | Current config values |
294
+ | `registry` | `FieldRegistry` | Field type registry (use `defaultRegistry`) |
295
+ | `onChange` | `(key: string, value: unknown) => void` | Called when a field value changes |
296
+ | `onReveal?` | `(key: string) => Promise<string \| null>` | Reveal sensitive field value |
297
+ | `onAction?` | `(action: string, params?: Record<string, unknown>) => Promise<unknown>` | Handle field actions |
298
+
299
+ ### FieldRenderProps
300
+
301
+ | Prop | Type | Description |
302
+ |------|------|-------------|
303
+ | `key` | `string` | Config key (e.g., "OPENAI_API_KEY") |
304
+ | `value` | `unknown` | Current field value |
305
+ | `schema` | `JsonSchemaProperty` | JSON Schema for this field |
306
+ | `hint` | `ConfigUiHint` | UI rendering hints |
307
+ | `fieldType` | `string` | Resolved field type name |
308
+ | `onChange` | `(value: unknown) => void` | Update field value |
309
+ | `isSet` | `boolean` | Whether field has a configured value |
310
+ | `required` | `boolean` | Whether field is required |
311
+ | `errors?` | `string[]` | Validation errors |
312
+ | `readonly?` | `boolean` | Whether field is read-only |
313
+ | `onReveal?` | `() => Promise<string \| null>` | Reveal sensitive value |
314
+ | `onAction?` | `(action: string, params?) => Promise<unknown>` | Dispatch action |
315
+
316
+ ## License
317
+
318
+ MIT
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@elizaos/plugin-ui",
3
+ "version": "2.0.0-alpha.1",
4
+ "description": "Plugin UI SDK — schema-driven config renderers and field components for ElizaOS plugins",
5
+ "type": "module",
6
+ "main": "src/index.ts",
7
+ "types": "src/index.ts",
8
+ "exports": {
9
+ ".": "./src/index.ts",
10
+ "./types": "./src/types.ts"
11
+ },
12
+ "files": [
13
+ "src",
14
+ "README.md"
15
+ ],
16
+ "peerDependencies": {
17
+ "react": ">=18.0.0",
18
+ "zod": ">=3.0.0"
19
+ },
20
+ "license": "MIT"
21
+ }
package/src/index.ts ADDED
@@ -0,0 +1,90 @@
1
+ /**
2
+ * @elizaos/plugin-ui — Public SDK for plugin configuration UI.
3
+ *
4
+ * Provides:
5
+ * - ConfigRenderer: Schema-driven form component
6
+ * - Field renderers: 23 built-in field type renderers
7
+ * - Catalog utilities: defineCatalog, defineRegistry, resolveFields
8
+ * - Data binding: getByPath, setByPath, resolveDynamic, findFormValue
9
+ * - Visibility: evaluateVisibility, evaluateShowIf, evaluateLogicExpression
10
+ * - Validation: runValidation, builtInValidators, check helpers
11
+ * - Actions: ActionDefinition, ActionHandler types
12
+ * - Type definitions: FieldRenderProps, ConfigUiHint, JsonSchemaObject, etc.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * import { ConfigRenderer, defaultRegistry } from "@elizaos/plugin-ui";
17
+ * import type { FieldRenderProps } from "@elizaos/plugin-ui";
18
+ *
19
+ * <ConfigRenderer
20
+ * schema={mySchema}
21
+ * hints={myHints}
22
+ * values={configValues}
23
+ * registry={defaultRegistry}
24
+ * onChange={handleChange}
25
+ * />
26
+ * ```
27
+ *
28
+ * @module @elizaos/plugin-ui
29
+ */
30
+
31
+ export type {
32
+ // Action types
33
+ ActionDefinition,
34
+ ActionHandler,
35
+ CatalogConfig,
36
+ FieldCatalog,
37
+ FieldDefinition,
38
+ FieldRegistry,
39
+ FieldRenderer,
40
+ // Core types
41
+ FieldRenderProps,
42
+ JsonSchemaObject,
43
+ JsonSchemaProperty,
44
+ ResolvedField,
45
+ ValidationFunction,
46
+ } from "@app/components/config-catalog";
47
+ // ── Catalog & Registry ──────────────────────────────────────────────────
48
+ export {
49
+ builtInValidators,
50
+ check,
51
+ // Defaults
52
+ defaultCatalog,
53
+ // Factory functions
54
+ defineCatalog,
55
+ defineRegistry,
56
+ evaluateLogicExpression,
57
+ evaluateShowIf,
58
+ // Rich visibility utilities
59
+ evaluateVisibility,
60
+ findFormValue,
61
+ // Data binding utilities
62
+ getByPath,
63
+ interpolateString,
64
+ resolveDynamic,
65
+ resolveFields,
66
+ // Validation utilities
67
+ runValidation,
68
+ setByPath,
69
+ visibility,
70
+ } from "@app/components/config-catalog";
71
+
72
+ // ── Field Renderers ─────────────────────────────────────────────────────
73
+ export {
74
+ ConfigField,
75
+ defaultRenderers,
76
+ } from "@app/components/config-field";
77
+ export type {
78
+ ConfigRendererHandle,
79
+ ConfigRendererProps,
80
+ } from "@app/components/config-renderer";
81
+ // ── ConfigRenderer ──────────────────────────────────────────────────────
82
+ export {
83
+ ConfigRenderer,
84
+ defaultRegistry,
85
+ useConfigValidation,
86
+ } from "@app/components/config-renderer";
87
+ // ── Types ───────────────────────────────────────────────────────────────
88
+
89
+ // ── Zod re-export for field type definitions ────────────────────────────
90
+ export { z } from "zod";
package/src/types.ts ADDED
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Type-only exports for @elizaos/plugin-ui.
3
+ * Import from "@elizaos/plugin-ui/types" for zero-runtime type usage.
4
+ */
5
+
6
+ // ── Catalog types ───────────────────────────────────────────────────────
7
+ export type {
8
+ ActionDefinition,
9
+ ActionHandler,
10
+ CatalogConfig,
11
+ FieldCatalog,
12
+ FieldDefinition,
13
+ FieldRegistry,
14
+ FieldRenderer,
15
+ FieldRenderProps,
16
+ JsonSchemaObject,
17
+ JsonSchemaProperty,
18
+ ResolvedField,
19
+ ValidationFunction,
20
+ } from "@app/components/config-catalog";
21
+
22
+ // ── ConfigRenderer types ────────────────────────────────────────────────
23
+ export type {
24
+ ConfigRendererHandle,
25
+ ConfigRendererProps,
26
+ } from "@app/components/config-renderer";
27
+
28
+ // ── Core UI types ───────────────────────────────────────────────────────
29
+ export type {
30
+ ActionBinding,
31
+ ConfigUiHint,
32
+ ConfigUiHints,
33
+ DynamicValue,
34
+ LogicExpression,
35
+ PluginUiTheme,
36
+ ShowIfCondition,
37
+ ValidationCheck,
38
+ ValidationConfig,
39
+ VisibilityCondition,
40
+ } from "@app/types";