@meganovaai/app-kit
v0.7.0
Published
Design tokens, UI primitives, and access-control-aware data components for React.
Downloads
730
Readme
@meganovaai/app-kit
A React design system: design tokens, UI primitives, and access-control-aware data components.
Install
npm install @meganovaai/app-kitPeer dependencies
app-kit shares React and a few context-bearing libraries with the host app so there's exactly one instance of each (multiple copies cause React "invalid hook call" errors).
Required (every consumer):
npm install react react-dom lucide-reactOptional — the heavier components live on subpath entries so you install only what you use:
| Import | Peer deps to install |
|---|---|
| @meganovaai/app-kit/board → Board | @dnd-kit/core |
| @meganovaai/app-kit/datagrid → DataGrid | @tanstack/react-table |
| @meganovaai/app-kit/form → FormField | react-hook-form @hookform/resolvers zod |
| @meganovaai/app-kit/chat → chat primitives | react-markdown remark-gfm |
The root entry (Button, Card, Tag, AdminPage, EmptyState, DataRow,
ErrorBanner, FieldGate, utilities) needs no optional peers.
Styles
Import the CSS once at your app entry:
import "@meganovaai/app-kit/tokens.css"; // design tokens
import "@meganovaai/app-kit/styles.css"; // primitives (AdminPage, Button, Card, Tag…)
import "@meganovaai/app-kit/data.css"; // data components (DataGrid, Board, FieldGate)What's included
UI primitives — AdminPage, Card, DataRow, Button, EmptyState,
ErrorBanner, Tag (+ hashTone).
Data components (subpath entries) — DataGrid (TanStack Table), Board
(dnd-kit kanban — click a card to open, drag to move), FormField
(react-hook-form + zod; re-exports zodResolver).
Field-level access control — FieldGate / useFieldAccess over a
FieldVisibility { visibleFields?, writableFields? } contract.
App shell — AppShell (the 3-panel layout: sidebar | main | aside),
Sidebar + SidebarItem (collapsible left nav with persistence), SidePanel
(a click-collapse right panel — e.g. an AI assistant — that folds to a slim rail).
Chat primitives (/chat subpath) — useChatStream (a headless,
transport-injected streaming hook with send / stop / regenerate),
parseAgUiStream (an AG-UI SSE parser for proxied streams), ChatThread
(with a renderMessage slot for custom entries), ChatMessage (markdown +
streaming caret), MessageActions (copy / regenerate), ChatInput
(Enter-to-send, attach, send ⇄ stop), Markdown. Styles:
import "@meganovaai/app-kit/chat.css".
Utilities — daysSince, overdueStatus.
Usage
import { AppShell, Sidebar, SidebarItem, SidePanel, Button } from "@meganovaai/app-kit";
import { Board } from "@meganovaai/app-kit/board";
import { useChatStream, ChatThread, ChatInput, parseAgUiStream } from "@meganovaai/app-kit/chat";
// 3-panel app: nav | content | collapsible AI panel
<AppShell
sidebar={
<Sidebar brand={<Logo />} storageKey="myapp.sidebar">
<SidebarItem icon={<HomeIcon />} label="Home" href="/" active />
</Sidebar>
}
aside={
<SidePanel title="Assistant" storageKey="myapp.assistant">
<AssistantPanel />
</SidePanel>
}
>
<Board columns={columns} cards={cards} onMove={move} />
</AppShell>;
// streaming chat wired to any backend (transport-injected)
const chat = useChatStream({
transport: async function* (text, signal) {
const res = await fetch("/api/chat", { method: "POST", body: JSON.stringify({ text }), signal });
yield* parseAgUiStream(res.body!);
},
});
<ChatThread messages={chat.messages} onRegenerate={chat.regenerate} />;
<ChatInput status={chat.status} onSend={chat.send} onStop={chat.stop} />;Field-level access control
The server computes per-record access and strips non-visible field values
before sending; FieldGate renders accordingly, so the UI never displays or
lets you edit a field the caller can't see:
import { FieldGate } from "@meganovaai/app-kit";
<FieldGate access={record._access} field="amount">
<DataRow label="Amount">{record.amount}</DataRow>
</FieldGate>With no contract, FieldGate degrades to all-visible (and warns once) — safe in
dev, but the security guarantee comes from the server stripping the values.
Versioning
Follows semver — breaking API or token changes bump the major. Pin a caret range in consumers.
License
Copyright © Nebula Nova INC. All rights reserved.
Free to view and evaluate for non-commercial purposes. Commercial use requires a license — contact Nebula Nova INC. See LICENSE.
