@rameshnaik/prompt-ui
v0.1.0
Published
Framework-agnostic Web Component library for prompt-driven generative UI — charts, tables, list-detail views from natural language.
Maintainers
Readme
@rameshnaik/prompt-ui
Framework-agnostic Web Component library for prompt-driven generative UI. Type a natural language prompt and get charts, tables, list-detail views, theme changes, and more — all generated on-the-fly from your data.
Works with React, Angular, Vue, Svelte, and vanilla HTML/JS — zero framework lock-in.
Installation
npm install @rameshnaik/prompt-ui chart.js jspdf html-to-imageQuick Start by Framework
All examples below use the same sample data and fields:
const fields = [
{ key: "name", label: "Name", type: "string" },
{ key: "department", label: "Department", type: "string" },
{ key: "hours", label: "Hours", type: "number" },
];
const data = [
{ name: "Alice", department: "Sales", hours: 40 },
{ name: "Bob", department: "Engineering", hours: 45 },
{ name: "Carol", department: "Sales", hours: 38 },
];React
The library ships a /react sub-entrypoint with a usePromptUI hook and built-in JSX type declarations — no boilerplate files needed.
import { usePromptUI } from "@rameshnaik/prompt-ui/react";
import type { FieldDescriptor } from "@rameshnaik/prompt-ui";
const FIELDS: FieldDescriptor[] = [
{ key: "name", label: "Name", type: "string" },
{ key: "department", label: "Department", type: "string" },
{ key: "hours", label: "Hours", type: "number" },
];
const DATA = [
{ name: "Alice", department: "Sales", hours: 40 },
{ name: "Bob", department: "Engineering", hours: 45 },
];
const EXAMPLES = ["Pie chart by department", "Sort by hours descending"];
export default function TimecardPage() {
const promptUI = usePromptUI({ fields: FIELDS });
return (
<>
<prompt-ui-bar ref={promptUI.bar} examplePrompts={EXAMPLES} />
<prompt-ui-canvas
ref={promptUI.canvas}
data={DATA as unknown as Record<string, unknown>[]}
fields={FIELDS}
/>
{/* ... rest of your page */}
</>
);
}What usePromptUI does:
- Creates a
PromptUIControllerinstance (once, persisted across re-renders) - Returns
promptUI.barandpromptUI.canvasref callbacks that wire the controller to each Web Component - Keeps
fieldsin sync when they change - Registers the custom elements automatically via side-effect import
Why
ref? React doesn't natively set JS object properties on custom elements. The ref callback bridges this gap. Other frameworks don't need it.
Angular
Angular binds properties to custom elements natively with [property] syntax. Just add CUSTOM_ELEMENTS_SCHEMA to your module or standalone component.
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import { PromptUIController } from "@rameshnaik/prompt-ui";
import "@rameshnaik/prompt-ui";
@Component({
selector: "app-timecard",
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<prompt-ui-bar
[controller]="controller"
[examplePrompts]="examples"
></prompt-ui-bar>
<prompt-ui-canvas
[controller]="controller"
[data]="data"
[fields]="fields"
></prompt-ui-canvas>
`,
})
export class TimecardComponent {
fields = [
{ key: "name", label: "Name", type: "string" },
{ key: "department", label: "Department", type: "string" },
{ key: "hours", label: "Hours", type: "number" },
];
data = [
{ name: "Alice", department: "Sales", hours: 40 },
{ name: "Bob", department: "Engineering", hours: 45 },
];
examples = ["Pie chart by department", "Sort by hours descending"];
controller = new PromptUIController({ fields: this.fields });
}No additional adapters or wrappers required.
Vue
Vue supports Web Components natively with :property binding. Add a custom element config to your vite.config.ts to suppress unknown-tag warnings.
vite.config.ts
import vue from "@vitejs/plugin-vue";
export default {
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith("prompt-ui") || tag === "viz-widget",
},
},
}),
],
};TimecardPage.vue
<script setup lang="ts">
import { PromptUIController } from "@rameshnaik/prompt-ui";
import type { FieldDescriptor } from "@rameshnaik/prompt-ui";
import "@rameshnaik/prompt-ui";
const fields: FieldDescriptor[] = [
{ key: "name", label: "Name", type: "string" },
{ key: "department", label: "Department", type: "string" },
{ key: "hours", label: "Hours", type: "number" },
];
const data = [
{ name: "Alice", department: "Sales", hours: 40 },
{ name: "Bob", department: "Engineering", hours: 45 },
];
const examples = ["Pie chart by department", "Sort by hours descending"];
const controller = new PromptUIController({ fields });
</script>
<template>
<prompt-ui-bar
:controller="controller"
:examplePrompts="examples"
/>
<prompt-ui-canvas
:controller="controller"
:data="data"
:fields="fields"
/>
</template>No additional adapters or wrappers required.
Svelte
Svelte treats custom elements as first-class citizens. Properties are passed directly.
<script lang="ts">
import { PromptUIController } from "@rameshnaik/prompt-ui";
import "@rameshnaik/prompt-ui";
const fields = [
{ key: "name", label: "Name", type: "string" },
{ key: "department", label: "Department", type: "string" },
{ key: "hours", label: "Hours", type: "number" },
];
const data = [
{ name: "Alice", department: "Sales", hours: 40 },
{ name: "Bob", department: "Engineering", hours: 45 },
];
const examples = ["Pie chart by department", "Sort by hours descending"];
const controller = new PromptUIController({ fields });
</script>
<prompt-ui-bar
controller={controller}
examplePrompts={examples}
/>
<prompt-ui-canvas
controller={controller}
{data}
{fields}
/>No configuration or adapters required.
Vanilla HTML / No Framework
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Prompt UI Demo</title>
</head>
<body>
<prompt-ui-bar id="bar"></prompt-ui-bar>
<prompt-ui-canvas id="canvas"></prompt-ui-canvas>
<script type="module">
import { PromptUIController } from "@rameshnaik/prompt-ui";
const fields = [
{ key: "name", label: "Name", type: "string" },
{ key: "department", label: "Department", type: "string" },
{ key: "hours", label: "Hours", type: "number" },
];
const data = [
{ name: "Alice", department: "Sales", hours: 40 },
{ name: "Bob", department: "Engineering", hours: 45 },
];
const controller = new PromptUIController({
fields,
getData: () => data,
});
const bar = document.getElementById("bar");
bar.controller = controller;
bar.examplePrompts = ["Pie chart by department", "Sort by hours descending"];
const canvas = document.getElementById("canvas");
canvas.controller = controller;
canvas.data = data;
canvas.fields = fields;
</script>
</body>
</html>Framework Compatibility Summary
| Framework | Import | How properties are bound | Adapter needed? |
|---|---|---|---|
| React | @rameshnaik/prompt-ui/react | ref={promptUI.bar} | Built-in hook |
| Angular | @rameshnaik/prompt-ui | [controller]="ctrl" | No |
| Vue | @rameshnaik/prompt-ui | :controller="ctrl" | No |
| Svelte | @rameshnaik/prompt-ui | controller={ctrl} | No |
| Vanilla JS | @rameshnaik/prompt-ui | el.controller = ctrl | No |
Features
- Charts:
"pie chart by department","bar chart of hours with count" - Tables:
"show only Sales employees","sort by hours descending" - List-Detail:
"side panel view with title as Name" - Theme:
"apply dark theme","revert dark theme" - Widget Management:
"undo last widget","clear all" - Voice Input: Built-in microphone button using Web Speech API
- PDF Export: Download any generated widget as PDF
- Prompt History: Arrow-up/down to navigate past prompts
API Reference
PromptUIController
The central state manager. Create one instance per page and share it between the bar and canvas.
const controller = new PromptUIController(options);| Option | Type | Default | Description |
|---|---|---|---|
| fields | FieldDescriptor[] | required | Describes available data columns |
| getData | () => Record<string, unknown>[] | — | Returns current data at prompt time |
| parser | ParserFn | built-in rule-based | Custom parser function |
| maxWidgets | number | 6 | Max stacked widgets |
| maxHistory | number | 50 | Max prompt history entries |
Methods:
| Method | Description |
|---|---|
| submitPrompt(text) | Parse and execute a prompt |
| confirmAction() | Confirm a pending theme change |
| cancelAction() | Cancel a pending theme change |
| dismissWidget(id) | Remove a specific widget |
| undoLast() | Remove the most recent widget |
| clearAll() | Remove all widgets |
| navigateHistory(dir) | Navigate prompt history ("up" or "down") |
Properties (read-only):
| Property | Type | Description |
|---|---|---|
| widgets | ActiveWidget[] | Currently active widgets |
| history | string[] | Past prompts |
| error | string \| null | Current error message |
| toast | PromptToast \| null | Current toast notification |
| pendingConfirmation | PendingConfirmation \| null | Pending theme confirmation |
| isActive | boolean | Whether any widgets are shown |
Events:
| Event | Description |
|---|---|
| state-change | Fired whenever any state property changes |
<prompt-ui-bar>
The prompt input bar with voice input, undo, clear, and generate controls.
| Property | Type | Default | Description |
|---|---|---|---|
| controller | PromptUIController | required | The controller instance |
| placeholder | string | "Describe what you want to see…" | Input placeholder text |
| examplePrompts | string[] | [] | Example chips shown below the bar |
<prompt-ui-canvas>
Renders the generated widgets (charts, tables, list-detail views).
| Property | Type | Default | Description |
|---|---|---|---|
| controller | PromptUIController | required | The controller instance |
| data | Record<string, unknown>[] | [] | The dataset to visualize |
| fields | FieldDescriptor[] | [] | Field descriptors for the data |
usePromptUI (React only)
import { usePromptUI } from "@rameshnaik/prompt-ui/react";
const promptUI = usePromptUI({ fields });
// promptUI.controller — the PromptUIController instance
// promptUI.bar — ref callback for <prompt-ui-bar>
// promptUI.canvas — ref callback for <prompt-ui-canvas>License
MIT
