Data Components
useNucleusEntity, DataTable, FormBuilder & EntityShowcase
These four turn an entity definition into a working data UI. useNucleusEntity is the data engine (CRUD + pagination + search/sort/filter over the generated actions); DataTable renders rows; FormBuilder renders the create/edit form straight from your columns; and NucleusEntityShowcase wires useNucleusEntity + DataTable together with its own built-in create/edit form (not the FormBuilder component) into a complete admin screen for a table with almost no glue.
Because they all speak the same NucleusColumn shape your config already declares, the table, the form and the validation stay in lock-step with the schema — change a column and they follow.
useNucleusEntity#
The hook that does the data work. Give it an entity and your apiActions and it returns the rows plus everything needed to page, search, sort, filter and mutate them — each operation routed to that table's generated action.
options (input){ entity, apiActions, pageSize=20, initialSort=[], initialFilters=[] }OptionalBeyond entity and apiActions, the hook takes pageSize (default 20 — becomes the query limit in every fetch) and initialSort / initialFilters (both default []) which seed the sort and filter query state used by the initial-mount fetch. All three are optional.
data + metaitems / paginationOptionalitems, the pagination meta (page, totalItems, totalPages, hasNextPage…), isLoading, isLoadingMore and a top-level error state — ready to feed a table or list or build failure UI.
mutationsadd / update / delete / bulkOptionaladdItem, updateItem, deleteItem plus bulkAdd / bulkDelete call the generated CRUD/bulk actions and then re-fetch the list from the server (loadData in onAfterHandle, which resets to page 1) so the list reflects the server state — not an optimistic local mutation, and not a scroll-preserving re-fetch of the current page.
query statesearch / sort / filterOptionalHolds the search term, sort and filter conditions; setSearch / setSort / setFilters are plain state setters that only update the held values — they do NOT auto re-fetch (the only automatic fetch is the initial mount). Call loadData() to re-fetch through the Query API with the held (or explicitly passed) search/sort/filter values; refetch() is the argument-less shorthand that re-runs loadData() (resetting to page 1 with the held values). loadMore appends the next page (de-duplicated) for infinite lists, and the top-level hasMore boolean (mirroring meta.hasNextPage) tells you whether there is another page left to append. The hook also returns currentPage (the last-fetched page number) and setCurrentPage, so you can drive explicit page navigation as well.
DataTable#
A generic, headless-leaning data grid. It's typed on your row shape and supports inline editing, column resizing, sorting, selection and infinite scroll — pair it with useNucleusEntity or any data source.
columns / actionColumnsColumnDefinition<T>[]OptionalEach column sets header, width bounds, sortable / resizable / editable and optional cellRenderer / headerRenderer. editable columns get an editConfig (text / number / select / textarea). actionColumns render buttons per row.
configDataTableConfigOptionalToggles: isFrontendSort vs server sort, enableInfiniteScroll + threshold + pageSize, enableSelection, column resize and defaults. autoFetchUntilScroll keeps loading until the viewport fills.
callbacksDataTableCallbacks<T>OptionalonCellClick / onCellDoubleClick / onCellEdit, onSort, onLoadMore, onColumnResize (onRowResize exists on the type but is not yet wired — only column resize fires) — wire these to useNucleusEntity's loadMore / updateItem / sort to get a live editable grid.
statesloading / empty / selectionOptionalisPending drives the skeleton table; isLoading shows a full-table loading spinner; isLoadingMore + hasMoreData drive the infinite-scroll sentinel; emptyMessage and a selectionToolbar (over selected rows) round out the UX.
FormBuilder#
Renders a typed add/edit form from a NucleusColumn[] — the same column definitions your entity uses — with validation derived from each column. It's the write side that complements useNucleusEntity + DataTable.
columns + modeNucleusColumn[] · 'add' | 'edit'OptionalThe columns to render, in add or edit mode with initialValues. Field types map from the column type (number, boolean, date via DatePicker, enum via SelectBox, etc.).
validationColumnValidationOptionalminLength / maxLength / min / max / pattern / format (email, url, uuid, ipv4…) come straight off the column, mirroring the server's validatePayload — so client and API agree on what's valid.
fieldConfigsper-field overridesOptionalOverride label, placeholder, helperText, static options, span and order, and conditional visibility via showWhen — without leaving the column-driven model. Per-field custom rendering in FormBuilder is the top-level renderField prop, not a fieldConfigs override.
layout + useFormBuildervertical | horizontal | inlineOptionalGrid layout, size and column span control the look; the underlying useFormBuilder hook (state, setValue, validate, submit, getFieldProps) is exposed for fully custom forms.
NucleusEntityShowcase#
The batteries-included option: a complete CRUD surface for one entity — list (DataTable) + its own built-in create/edit form + detail — assembled over useNucleusEntity. The create/edit form is bespoke to the showcase (Checkbox / SelectBox / NucleusTextInput driven by the columns, plus a JSON textarea and an array tag-input, with fieldConfigs overrides), not the standalone FormBuilder component. Date columns render as plain NucleusTextInput fields in the form; DatePicker appears only in the showcase's date-range filter bar. The fastest path from 'I declared a table' to 'I have an admin screen'.
entity + apiActionsNucleusEntityOptionalPoint it at an entity and the generated actions; it infers columns, renders the grid and forms, and handles create/edit/delete and paging end to end. Foreign-key columns are auto-detected: each referenced table is fetched (via its GET_<TABLE> action) to populate the form's SelectBox, table cells render the related row as a clickable relation badge that opens a per-row detail modal, and FK values are normalized by references.foreignKey (falling back to the column name) on both edit-load and submit.
toggles + overridesoptional propsOptionalThe batteries-included screen stays tailorable: searchable / filterable / sortable / selectable toggles (all default on), the showAdd / showEdit / showDelete / showBulkDelete CRUD toggles (all default on, but showAdd / showEdit / showDelete are additionally suppressed when the entity excludes the corresponding POST / PUT / DELETE method — i.e. ANDed with the entity's excluded_methods; showBulkDelete is not), columnConfigs / fieldConfigs overrides, excludeColumns / excludeFields lists, pageSize (default 20), onRowClick, and the renderHeader / renderToolbar slots. title (defaults to the formatted table name) and description feed the default header when renderHeader is not supplied, and className is applied to the root container. (searchFields and showBulkAdd exist on the props type but are inert — the component destructures them unused.)
Related sections