@rulab/adminjs-components
v0.6.1
Published
Prebuilt AdminJS features for common UI needs.
Readme
adminjs-components
Prebuilt AdminJS components and features for common UI needs: colored status badges, slug and UUID generation, Editor.js content (images and file attachments), sortable string lists, drag-and-drop list ordering, singleton resources, tabs layout, record preview, and QR codes for templated URLs.
Install
pnpm add @rulab/adminjs-components
# or
npm install @rulab/adminjs-componentsQuick start
import AdminJS from "adminjs";
import { ComponentLoader } from "adminjs";
import { setComponentLoader, ColorStatusFeature } from "@rulab/adminjs-components";
const componentLoader = new ComponentLoader();
setComponentLoader(componentLoader);
const admin = new AdminJS({
componentLoader,
resources: [
{
resource: YourResource,
features: [
ColorStatusFeature({
key: "status",
availableValues: [
{ value: "draft", label: "Draft", color: "#64748b" },
{ value: "published", label: "Published", color: "#16a34a" },
],
}),
],
},
],
});You can also pass componentLoader into every feature instead of calling
setComponentLoader.
Components and features
- Singleton — register first when used with other features
- ColorStatus
- Slug
- UUID
- Editor
- StringList
- SortableList
- Tabs
- Preview
- QrCode
Singleton
Makes a resource behave as a singleton: opening the list redirects to new when there are no rows, to edit when there is exactly one row, or shows the normal list with an error notice when more than one row exists.
Feature order: add SingletonFeature() first in the resource features
array when you combine it with other features. AdminJS merges list.after
hooks in registration order; if another feature has already registered
list.after before Singleton applies, singleton behaviour is turned off and you
get a notice asking you to move Singleton earlier. That matters especially for
@adminjs/upload, which adds a list.after that expects records to exist —
Singleton must merge before upload so the hook chain stays correct.
Exception: if another feature defines a custom list handler, register
SingletonFeature after that feature so the custom handler still runs as
intended (see inline comments in the source for details).
import { SingletonFeature } from "@rulab/adminjs-components";
features: [
SingletonFeature(),
// …other features (e.g. EditorFeature with @adminjs/upload, TabsFeature)
];ColorStatus
Renders a colored badge in edit/list/show based on a list of available values.
By default (nullable: false) the first option is auto-selected in new records.
Set nullable: true to allow an empty value.
import { ColorStatusFeature } from "@rulab/adminjs-components";
features: [
ColorStatusFeature({
key: "status",
nullable: false, // optional, default false
availableValues: [
{ value: "draft", label: "Draft", color: "#64748b" },
{ value: "review", label: "In review", color: "#f59e0b" },
{ value: "published", label: "Published", color: "#16a34a" },
],
}),
]Slug
Generates a slug from another field and stores it in the target property.
Use button to override the generate button label in edit view.
import { SlugFeature } from "@rulab/adminjs-components";
features: [
SlugFeature({
key: "slug",
source: "title",
button: "Create slug", // optional
}),
]UUID
Adds a UUID field with a "Generate UUID" button in edit view.
Use button to override the generate button label.
import { UuidFeature } from "@rulab/adminjs-components";
features: [
UuidFeature({
key: "uuid",
button: "Generate ID", // optional
}),
]Editor
Editor.js field for rich content. With uploadProvider (@adminjs/upload), the
editor enables image upload (@editorjs/image) and file attachments
(@editorjs/attaches — downloadable files with an editable title). Built-in
audio and video blocks are always available.
import { EditorFeature } from "@rulab/adminjs-components";
import { BaseProvider } from "@adminjs/upload";
const uploadProvider = new BaseProvider({
bucket: "my-bucket",
baseUrl: "https://cdn.example.com",
});
features: [
EditorFeature({
key: "content",
uploadProvider, // optional — enables Image + Attach file tools
}),
]StringList
Sortable list stored as a single string (pipe-separated by default).
Use separator to override the delimiter used for storing values.
In the list view values are always shown joined with ", ". If the
resulting string is longer than listMaxLength (default 80), it is truncated
with a clickable ... spoiler; when expanded, a clickable < collapses it
again.
import { StringListFeature } from "@rulab/adminjs-components";
features: [
StringListFeature({
key: "facts",
separator: "|", // optional, default "|"
listMaxLength: 80, // optional, default 80 — list-view spoiler threshold
}),
]SortableList
Replaces the default list view with a drag-and-drop table so you can reorder
records. New positions are saved to a numeric property on each record (default
sort) via a hidden resource action. The resource is sorted by that field by
default unless you already set sort in resource options.
import { SortableListFeature } from "@rulab/adminjs-components";
features: [
SortableListFeature({
sortField: "sort", // optional, default "sort" — must exist on your model
reorderActionName: "sortableListReorder", // optional, default shown
direction: "ASC", // optional: "ASC" | "DESC" — how order maps to numbers per page
}),
];Tabs
Groups edit/show fields into tabs based on property props.tab or
custom.tab. Fields without a tab go to a common group.
commonTabLabel is optional and defaults to "Common".
import { TabsFeature } from "@rulab/adminjs-components";
features: [
TabsFeature({
commonTabLabel: "General", // optional, default "Common"
}),
]
// resource options example
properties: {
title: { props: { tab: "Main" } },
description: { props: { tab: "Main" } },
seoTitle: { props: { tab: "SEO" } },
seoDescription: { props: { tab: "SEO" } },
},Preview
Adds a record action that renders an iframe preview. The url can include
template variables like $id or $slug.
import { PreviewFeature } from "@rulab/adminjs-components";
features: [
PreviewFeature({
url: "https://example.com/posts/$id",
actionName: "preview", // optional
}),
]QrCode
Property on edit / show that builds a QR code from a URL template
($id, $uuid, $slug, … — same $field syntax as Preview).
The generation flag is stored in the property named by key (empty = not
generated, ISO timestamp = generated). Use a different key per feature if
you need several QR codes on one resource. The QR image itself is not stored in
the database; it is rendered on the client from the resolved URL.
- Edit: if not generated — message + Generate; if generated — QR image + Download (with icon). Save the record after Generate so the flag persists.
- Show: view-only (message or QR image, no buttons).
Your entity must have a nullable string column matching key.
import { QrCodeFeature } from "@rulab/adminjs-components";
features: [
QrCodeFeature({
key: "homeQr",
url: "https://example.com/page/$id/$slug",
}),
]Utilities
setComponentLoader(loader)andgetComponentLoader()to reuse a single AdminJSComponentLoader.parseHtml(html)helper to transform stored Editor.js output into HTML.
