@kaily-ai/components-core
v0.1.1
Published
Framework-neutral dynamic widget UI spec renderer
Keywords
Readme
@kaily-ai/components-core
Shared dynamic UI component runtime for Kaily chat surfaces.
@kaily-ai/components-core gives Kaily apps one common contract for rendering AI-generated UI cards, forms, tables, lists, charts, and guided actions from JSON specs. It is used by Kaily surfaces such as Binary, Trinity, and Neo to keep component specs, action names, state rules, and rendering behavior consistent across products.
The package is framework-neutral. It does not bundle React, Preact, Material UI, Recharts, markdown, or icon libraries. Host apps provide their own element factory and component map, while this package handles the shared spec contract and renderer behavior.
Install
npm install @kaily-ai/components-corepnpm add @kaily-ai/components-coreRequires Node.js 20 or newer.
Why Use It
- Render the same dynamic component spec in React or Preact hosts.
- Share one JSON shape for AI-generated cards, forms, tables, lists, charts, and actions.
- Avoid string drift with exported constants for action types, function types, message roles, loading modes, condition operators, and state visibility.
- Keep builders, previews, widget rendering, prompt guards, and backend validators aligned.
- Reuse helpers for variables, repeats, conditional values, themes, form state, and function return schemas.
Quick Example
import { createElement as h } from "react";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import {
ACTION_TYPES,
createSpecRenderer,
createWidgetRegistry,
fillVariables,
} from "@kaily-ai/components-core";
const registry = createWidgetRegistry({
h,
components: {
Card,
CardContent,
Button,
Typography,
},
});
const Renderer = createSpecRenderer({ h, registry });
const spec = {
component: "Card",
children: [
{
component: "CardContent",
children: [
{ component: "Title", children: "Order {{orderId}}" },
{ component: "Text", children: "Status: {{status}}" },
{
component: "Button",
children: "Track order",
action: {
type: ACTION_TYPES.QUICK_REPLY,
value: "Track order {{orderId}}",
},
},
],
},
],
};
export function OrderCard() {
return (
<Renderer
node={fillVariables(spec, { orderId: "A-1024", status: "Shipped" })}
onAction={(action) => {
console.log(action);
}}
/>
);
}The same pattern works in Preact by passing Preact's compatible h or createElement function.
Shared Constants
Import constants from the package root and use them instead of hardcoded spec strings.
import {
ACTION_TYPES,
CONDITION_OPERATORS,
FOLLOW_UP_TYPES,
FUNCTION_TYPES,
LOADING_MODES,
MESSAGE_TYPES,
ROLES,
STATE_LOGIC,
STATE_VISIBILITY,
} from "@kaily-ai/components-core";Available constant groups:
| Export | Values |
| --- | --- |
| ACTION_TYPES | quick_reply, navigate, execute_function, callback, delay, setVariables, dismiss |
| FUNCTION_TYPES | sendMessage, link, dismiss, setVariables, client, server |
| FOLLOW_UP_TYPES | quick_reply, setVariables, dismiss |
| MESSAGE_TYPES | default, hidden |
| ROLES | user, assistant |
| LOADING_MODES | none, self, container |
| STATE_VISIBILITY | always, never, conditional |
| STATE_LOGIC | AND, OR |
| CONDITION_OPERATORS | eq, neq, contains, gt, lt, isEmpty, isNotEmpty |
Example:
const state = {
visibility: STATE_VISIBILITY.CONDITIONAL,
logic: STATE_LOGIC.AND,
conditions: [
{ field: "order.status", op: CONDITION_OPERATORS.EQ, value: "paid" },
],
};What A Spec Can Describe
Dynamic specs can include:
- Layouts:
Box,Stack,Row,Col,Spacer,Grid,Paper - Cards and media:
Card,CardContent,CardActions,CardMedia,Image - Text:
Text,Title,Subtitle,Caption,Markdown - Actions:
Button,IconButton,Chip,ToggleButton,ToggleButtonGroup - Forms:
Form,Input,Textarea,Select,Checkbox,Switch,Slider,Rating,RadioGroup,DateInput - Data display:
KeyValueRow,List,ListItem,ListView,Table - Feedback:
Alert,LinearProgress,CircularProgress,Skeleton,Tooltip - Charts:
ChartContainer,BarChart,LineChart,AreaChart,PieChart
Use SPEC_COMPONENT_NAMES when building suggestions or validating AI-generated specs. Use WIDGET_COMPONENT_NAMES when a host renderer needs the full internal component vocabulary.
import {
SPEC_COMPONENT_NAMES,
WIDGET_COMPONENT_NAMES,
} from "@kaily-ai/components-core";Host App Responsibilities
This package provides the shared runtime, but the host app stays in control of product behavior.
Host apps provide:
- The framework element factory, such as React or Preact
createElement. - Real component implementations, such as Material UI, Recharts, markdown, and icon components.
- Action handling for quick replies, navigation, callbacks, variable updates, dismissals, and server/client functions.
- Theme creation, color tokens, and surface-specific styling.
- Optional form state handling through
getFormStateandonFormChange.
This split keeps the core reusable while letting each Kaily surface render with its own UI stack.
Useful Exports
import {
ACTION_TYPES,
CHECKBOX_COMPONENTS,
CONDITION_OPERATORS,
DUAL_ARG_COMPONENTS,
FOLLOW_UP_TYPES,
FORM_COMPONENTS,
FUNCTION_TYPES,
LOADING_MODES,
MESSAGE_TYPES,
ROLES,
SPEC_COMPONENT_NAMES,
STATE_LOGIC,
STATE_VISIBILITY,
WIDGET_COMPONENT_NAMES,
createDynamicErrorBoundary,
createSpecRenderer,
createWidgetRegistry,
createWidgetTheme,
evaluateConditions,
extractReturnSchema,
fillVariables,
isSpecNodeForRegistry,
normalizeReturnSchema,
resolveTemplate,
tokensFromBinaryColors,
} from "@kaily-ai/components-core";Common Helpers
createWidgetRegistry: creates the component registry for a host renderer.createSpecRenderer: renders recursive spec nodes using a host registry.fillVariables: resolves{{variable}}placeholders,$repeat, and$cond.evaluateConditions: evaluates state visibility conditions.createWidgetThemeandtokensFromBinaryColors: map host color settings into a widget theme.normalizeReturnSchemaandextractReturnSchema: normalize function outputs before merging them into component variables.
Package Notes
This is a restricted Kaily package. It is intended for Kaily services and surfaces that need to render or validate dynamic component specs.
