@zango-core/crud
v2.1.1
Published
Unified React CRUD components library for tables, forms and workflows.
Downloads
750
Readme
@zango-core/crud
Unified React CRUD components library for tables, forms and workflows — one of the Zango frontend packages.
@zango-core/crud renders CRUD interfaces directly from the metadata a Zango backend serves. It
pairs an advanced data table (built on TanStack Table) with a dynamic
form engine (built on react-jsonschema-form)
and a workflow/status-transition system, all driven by one shared, context-based state layer.
The package is hooks-first. useCrud and the table hooks give you the data, state and actions
with no UI attached, so you own the markup. CrudHandler is the drop-in alternative when a
standard table is what you want. Neither path is deprecated, and both run on the same engine.
Features
- Hooks first —
useCrud(namespaced, with ready-made prop bags),useTable(flat) and per-concern slice hooks expose state and actions with no UI attached. - Drop-in when you want it —
<CrudHandler api_endpoint="…" />renders a complete table, andcustomTableBodylets you swap only the list while keeping fetching, toolbar and detail view. - Dynamic forms — server-driven or local RJSF schemas via
FormRenderer, plus a themedFormHandlerwith render slots, custom footer buttons, and--form-*CSS-variable theming. - Workflows — status badges, tags, and form-based transitions out of the box.
- Mobile ready — below the mobile breakpoint the table switches to a card layout and drawers become full-screen overlays, with no extra configuration.
- Themeable — brand, gray and status colors come from CSS variables your app defines; see Theming.
- Granular subpath exports — import only what you need (
/core,/ui,/form,/table).
Installation
npm install @zango-core/crud
# or: bun add @zango-core/crudPeer dependencies
Install these alongside the library:
| Package | Version |
| --- | --- |
| react | ^17.0.0 \|\| ^18.0.0 |
| react-dom | ^17.0.0 \|\| ^18.0.0 |
| react-router-dom | 7.7.0 |
| @zango-core/components | ^1.0.1 |
Requires Node.js 18 or newer. The package is ESM-only ("type": "module").
Quick start
api_endpoint points at a Zango CRUD view: the backend serves the table data and the metadata
that drives it.
With hooks (primary)
Mount CrudHandler with a customTableBody. It provides the engine, and your body reads it with
useCrud() and renders the list however you like.
import { useCrud } from "@zango-core/crud/core";
import { CrudHandler, useTableContext } from "@zango-core/crud/table";
// Define the body at module scope so its reference stays stable.
function UserCards() {
const crud = useCrud();
const { openDetailDrawer } = useTableContext();
const rows = crud.table?.getRowModel().rows ?? [];
if (crud.isLoading && rows.length === 0) return <p>Loading…</p>;
return (
<div className="grid grid-cols-3 gap-4">
{rows.map((row) => (
<button key={row.id} type="button" onClick={() => openDetailDrawer(row)}>
{String(row.original.name)}
</button>
))}
</div>
);
}
export function Users() {
return <CrudHandler api_endpoint="/api/users/" showPagination={false} customTableBody={UserCards} />;
}For no CrudHandler chrome at all, mount TableProvider yourself and call useCrud() below it:
import { useCrud } from "@zango-core/crud/core";
import { TableProvider } from "@zango-core/crud/table";
function OrdersInner() {
const crud = useCrud();
return (
<>
<input value={crud.search.term} onChange={(e) => crud.search.setTerm(e.target.value)} />
<ul>
{crud.data.map((row) => (
<li key={String(row.object_uuid)}>{String(row.name)}</li>
))}
</ul>
<button type="button" disabled={!crud.pagination.canGoNext} onClick={crud.pagination.goToNextPage}>
Next
</button>
</>
);
}
export function Orders() {
return (
<TableProvider apiUrl="/api/orders/">
<OrdersInner />
</TableProvider>
);
}Choosing a hook
| You want | Use | Return shape |
| --- | --- | --- |
| Everything in one call, flat property names | useTable() | flat |
| Everything plus ready-made prop bags for the Crud* components | useCrud() | namespaced |
| Just one concern (search, filters, pagination, selection, columns, actions) | slice hooks such as useTableSearch() | flat, per concern |
useTable() and useCrud() return different shapes for the same data, so mixing them up gives
undefined rather than an error:
useTable().searchTerm; useTable().currentPage; // flat
useCrud().search.term; useCrud().pagination.currentPage; // namespaceduseCrud() also returns prop bags (headerProps, toolbarProps, tableProps, paginationProps,
filterProps, detailProps, addFormProps) that spread onto the presentational components in
@zango-core/crud/ui. The hooks guide has the full reference, provider
requirements and known pitfalls.
Drop-in component
When a standard table is enough, render CrudHandler alone:
import { CrudHandler } from "@zango-core/crud/table";
export function Users() {
return <CrudHandler api_endpoint="/api/users/" />;
}That renders a complete table: header, search, filters, pagination, and a detail drawer. See the CrudHandler guide for every prop.
Theming
Styles ship inside the JavaScript bundle and are injected automatically — there is no CSS file to import. The library reads its colors from CSS custom properties that your app defines. It does not ship brand colors, so define the brand scale at minimum:
:root {
--color-brand-25: #e9f6f4;
--color-brand-50: #d3ede9;
--color-brand-100: #b1e1da;
--color-brand-200: #8ecfc7;
--color-brand-300: #64bdb1;
--color-brand-400: #3fa99a;
--color-brand-500: #136f63; /* primary */
--color-brand-600: #0f5d53;
--color-brand-700: #0b4a43;
--color-brand-800: #083834;
--color-brand-900: #052b28;
--color-brand-950: #021815;
}Gray, success, error and warning scales (--color-gray-*, --color-success-*,
--color-error-*, --color-warning-*) can be overridden the same way, and --radius sets the
corner radius. Semantic tokens such as --primary and --ring are derived from the brand scale.
The full variable list is in CSS_VARIABLES.md, and per-element class and
style hooks are covered in the styling guide.
Entry points
The library ships multiple entry points so consumers only pull in what they use:
| Import | Contents |
| --- | --- |
| @zango-core/crud | Everything (convenience root barrel). |
| @zango-core/crud/core | Headless logic only — useCrud, CrudProvider, column and prop-bag helpers, types. No UI, no CSS. |
| @zango-core/crud/ui | Presentational Crud* components, cells and workflow primitives. Importing it also activates the toast notifier used by the headless hooks. |
| @zango-core/crud/form | FormRenderer, FormHandler, useForm, theming utilities. |
| @zango-core/crud/table | Table engine — CrudHandler, Table, TableProvider, all useTable* hooks. |
Documentation
Full guides live in docs/guide/:
- Building Custom CRUD Views with Hooks — provider hierarchy and the full hook reference.
- CrudHandler — the drop-in table component and its props.
- Forms —
FormRenderer+ the headlessFormHandler/useFormlayer and theming. - Workflow Components — status, tags, and transitions.
- Table Styling Customization — class and style-function system, and theming tokens.
- Render Props Customization — customizing Actions / Status / Tags columns.
- Custom Components API Reference — drop-in component reference.
Further references: CSS_VARIABLES.md (theming variables), BACKEND-CONTROL-FLAGS.md (metadata flags the backend can send), and TABLE_STYLING.md.
Upgrading to 2.x
@zango-core/componentsis now^1.0.1(was^0.2.x). Update the peer dependency.- New headless layer:
useCrud,CrudProvideranduseForm(see/coreand/form). useTableDatano longer accepts cell render props; pass them toTableProviderorCrudHandler.useTableActions().exportDatano longer supports"xlsx"; use"json"or"csv".useTablePaginationtakes optional overrides and works without a provider.
The full before/after table is in Building Custom CRUD Views with Hooks.
Development
git clone https://github.com/Healthlane-Technologies/pkg-zango-crud.git
cd pkg-zango-crud/crud/frontend
npm installCommon scripts:
| Script | Description |
| --- | --- |
| npm run dev | Start the development server (port 1234). |
| npm run dev:mock | Dev server with MSW mocks enabled. |
| npm run build | Build the library (all entry points). |
| npm test | Run the unit test suite (Vitest). |
| npm run test:e2e | Run the Playwright end-to-end suite. |
| npm run lint | Lint and format diagnostics (Biome). |
Contributing
Issues and pull requests are welcome. See CONTRIBUTING.md for setup, the
project layout, and the development workflow. In short: run npm run lint and npm test before
opening a PR, and follow Conventional Commits for commit
messages.
To report a security vulnerability, please follow SECURITY.md rather than filing a public issue.
License
This project uses a multi-license arrangement, matching the wider Zango project: documentation
(docs/) is licensed under CC BY-SA 4.0, client-side JavaScript under the MIT Expat license, and
all other content under the Apache License 2.0. See LICENSE for the full text.
Copyright © Healthlane Technologies Pvt. Ltd. ("Zango").
