SmartGrid
GuideClient and server row models on AG Grid, with cross-page selection, quick search, and Excel export.
Open-source React 19 UI system
Forms, grids, calendars, and trees as config-driven components. One schema in, a finished screen out.
<SmartForm
schema={userSchema}
fields={[
{ name: "name", type: "text" },
{ name: "email", type: "email" },
{ name: "role", type: "select" },
]}
onSubmit={createUser}
/>
Every product needs a user table, a create form, a search bar, and a date picker. Most codebases rebuild them per feature, with slightly different validation, slightly different spacing, and entirely different bugs. Smart Component turns those recurring patterns into documented, tested building blocks instead of one-off glue.
It is not a component dump. It is a small set of engines with one shared convention, so the tenth screen costs less than the first.
Flat props replace six nested compound tags. The native primitives stay re-exported for the layouts config can't express.
One Zod schema drives validation, required marks, and TypeScript types. Nothing is declared twice.
No compiled bundle between you and the library. Trace any behavior straight to its file.
The same create-user screen, written twice. On the left, the hand-wired version every codebase accumulates. On the right, the form engine.
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [role, setRole] = useState<Role | null>(null);
const [errors, setErrors] = useState<Errors>({});
const [submitting, setSubmitting] = useState(false);
function validate() {
const next: Errors = {};
if (!name.trim()) next.name = "Name is required";
if (!EMAIL_RE.test(email)) next.email = "Invalid email";
// ...then the markup, the focus management,
// the reset logic, the error rendering.
// Repeated for every form in the app.
✕ Validation rules written twice: once in state, once in markup
✕ Error, loading, and reset state managed by hand
✕ Every form drifts a little further from the last one
const userSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
role: z.enum(roles),
});
<SmartForm
schema={userSchema}
fields={fields}
onSubmit={createUser}
/>
✓ One Zod schema drives rules, types, and required marks
✓ Field states, errors, and submit flow handled by the engine
✓ Every form in the app looks and behaves the same
No form context to wire, no column plumbing to memoize. Describe what the screen is, and the engine builds it.
Plain Zod. It already validates your API payloads; now it also declares your form.
const schema = z.object({
title: z.string().min(3),
due: z.date(),
assignee: z.string().email(),
});
UI-only concerns: labels, control types, layout. Twenty-plus field types, from currency to rich text.
const fields: FieldDefinition[] = [
{ name: "title", label: "Title", type: "text" },
{ name: "due", label: "Due date", type: "date" },
{ name: "assignee", label: "Assignee", type: "email" },
];
Validation, required asterisks, error placement, and the submit lifecycle all derive from the schema.
<SmartForm schema={schema} fields={fields} onSubmit={createTask} />
Change the schema and the form follows: new rule, new error copy, new required mark, new inferred type. There is no second place to update.
The ecosystem
Seven engines and a family of flat wrappers cover the surfaces products actually ship. Each one links to its consumer guide.
Client and server row models on AG Grid, with cross-page selection, quick search, and Excel export.
Month, week, day, and agenda views with recurrence, drag editing, and bookable availability slots.
Lazy loading, tri-state checks, inline rename, drag to reorder.
Declarative filter bars that prune empty values before they hit the API.
Lexical rich text with HTML or JSON values, images, code blocks, and page breaks.
Dual-list shuttle with typed change metadata for every move.
27 CRUD presets with icons, loading text, and permission gating.
SmartStepper and SmartToaster close the loop on every action.
The engines share one convention set, so learning the first component teaches you the other forty.
data /
setData
Every input-like component uses the same value contract, which is exactly why the form engine can drive any field type without adapters.
Each wrapper re-exports its native shadcn/ui primitives. When the flat API can't express a layout, drop down without changing imports.
Paged responses are parsed with Zod before they reach the grid, so a drifting API fails loudly at the boundary instead of quietly in a cell.
const fetchRows = createPageFetcher({
url: "/api/users",
itemSchema: userSchema, // Zod-checked rows
});
<SmartServerGrid
columnDefs={columns}
fetchRows={fetchRows}
persistStateKey="users-grid"
/>
<AddButton onClick={openCreate} />
<ExportButton loading={exporting} />
<DeleteButton permission="users:delete" />
A strict one-way dependency flow. Apps consume engines, engines compose primitives, and nothing reaches around a layer.
smart-component/ ├─ apps/ │ └─ web/ playground and demo routes ├─ packages/ │ └─ ui/ the library, exported as source │ ├─ components/ shadcn/ui primitives │ ├─ smart-components/ │ ├─ form/ │ ├─ data-grid/ │ ├─ search/ │ ├─ tree/ │ ├─ calendar/ │ └─ … ├─ docs/ guides, plus this page └─ scripts/ repo checks
Not a component dump, not a black-box framework. A middle layer that owns the repetitive 80% and hands you the keys for the rest.
| Concern | Hand-rolled UI | Copy-paste kits | Smart Component |
|---|---|---|---|
| New CRUD screen | Days of glue code | Copy, then rewire by hand | A schema and one component |
| Validation | Rewritten per form | Left as an exercise | One Zod schema, one source of truth |
| Consistency | Drifts per developer | Drifts per paste | One config map, shared conventions |
| Escape hatch | Everything is the escape hatch | Edit the copied source | Native primitives re-exported |
| Reading the source | Yours to document | Snapshots go stale | Source-first package, tested and documented |
Every entrypoint ships with a consumer guide. Start with the engine you need; the conventions carry over.
@iamsaroj/smart-ui/form
Data grid
@iamsaroj/smart-ui/data-grid
Search engine
@iamsaroj/smart-ui/search
Tree engine
@iamsaroj/smart-ui/tree
Transfer list engine
@iamsaroj/smart-ui/transfer-list
Calendar engine
@iamsaroj/smart-ui/calendar
Rich text editor
@iamsaroj/smart-ui/text-editor
Smart wrappers
@iamsaroj/smart-ui/smart-components/*
Every engine is typed, tested, and readable in an afternoon. If it saves your team a sprint, star the repo so the next team finds it.
git clone https://github.com/imsaroj/automatic-octo-fiesta && pnpm install && pnpm dev