@pylonts/admin
v1.1.3
Published
React admin scaffold built on antd, providing layout, auth, and reusable table/export utilities.
Readme
@pylonts/admin
React admin scaffold built on antd, providing layout, auth, and reusable table/export utilities.
Quick Start
import { AdminApp } from '@pylonts/admin';
import type { AdminConfig, AdminPage } from '@pylonts/admin';
const config: AdminConfig = {
brand: {
name: 'My Admin',
subtitle: 'Management Dashboard',
icon: <ShopOutlined />,
},
auth: {
login: async (username, password) => { /* return true on success */ },
logout: () => { /* clear token/session */ },
isAuthenticated: () => { /* check login state */ },
},
loginHint: 'Demo: admin / admin',
};
const pages: AdminPage[] = [
{ section: 'Overview', path: 'dashboard', label: 'Dashboard', icon: <DashboardOutlined />, element: <Dashboard /> },
{ section: 'Manage', path: 'orders', label: 'Orders', icon: <OrderOutlined />, element: <Orders />, permission: 'order:view' },
];
createRoot(root).render(<AdminApp config={config} pages={pages} />);Auth & Route Guards (built-in)
| Guard | Route | Behavior |
|-------|-------|----------|
| RequireGuest | /login | Already authenticated → redirect to first page |
| RequireAuth | /* | Not authenticated → redirect to /login |
| hasPermission | per page | Page specifies permission and getPermissions() returns user's permissions → missing permission → redirect to /403 |
If getPermissions is not configured, all permission checks are bypassed.
Exports
Components
| Export | Description |
|--------|-------------|
| AdminApp | Root component: wraps BrowserRouter, antd ConfigProvider, layout, auth guards |
| AdminLayout | Sidebar + breadcrumb + content area layout |
| Sidebar | Collapsible sidebar with sectioned nav menu |
| PageHeader | Top header bar with breadcrumb and action slot |
| PageList | Generic Table + search form + pagination, forwardRef with reload() handle |
| ExportButton | Button that calls an async export function and triggers Blob download |
Utils
| Export | Description |
|--------|-------------|
| downloadCsv(csv, filename) | Trigger CSV download with BOM for Excel compatibility |
| fmtCurrency(value) | Format number string as ¥1,234.56 |
| fmtRate(value) | Format decimal as percentage 12.5% |
| rateToInput(raw) | Decimal → input value (multiply by 100) |
| inputToRate(input) | Input value → decimal (divide by 100) |
Types
| Export | Description |
|--------|-------------|
| AdminConfig | Brand info + auth + optional login hint |
| AdminAuth | login / logout / isAuthenticated / getPermissions? |
| AdminPage | section / path / label / icon / element / permission? |
| NavItem | Sidebar nav item: key / label / icon |
| NavSection | Sidebar nav group: section + items: NavItem[] |
| PageListHandle | reload() ref handle |
| PageListProps<T, F> | load / initialForm? / columns / rowKey / pageSize? / renderForm? |
PageList Usage
import { PageList } from '@pylonts/admin';
import type { PageListHandle } from '@pylonts/admin';
const ref = useRef<PageListHandle>(null);
<PageList
ref={ref}
load={async (page, form) => api.list({ page, ...form })}
columns={[{ title: 'Name', dataIndex: 'name' }]}
rowKey="id"
renderForm={(form, setForm, search) => (
<Space>
<Input value={form.keyword} onChange={e => setForm({ ...form, keyword: e.target.value })} />
<Button onClick={search}>Search</Button>
</Space>
)}
/>
ref.current?.reload(); // trigger refreshExportButton Usage
<ExportButton onExport={async () => ({ body: await api.exportAll(), filename: 'orders.csv' })}>
Export
</ExportButton>Peer Dependencies
react^19react-dom^19react-router-dom^7antd^6@ant-design/icons^6
Vite Config
If this package is linked via file: protocol, add dedupe to prevent duplicate React instances:
// vite.config.ts
export default defineConfig({
resolve: {
dedupe: ['react', 'react-dom'],
},
});