Build Module Studio application composition
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { HTMLAttributes, ReactNode } from "react";
|
||||
import { cn } from "./cn.js";
|
||||
import { SortableList } from "./DragDrop.js";
|
||||
|
||||
export interface AdminNavigationContext {
|
||||
id: string;
|
||||
@@ -16,12 +17,15 @@ export interface AdminNavigationItem {
|
||||
id: string;
|
||||
label: string;
|
||||
icon?: ReactNode;
|
||||
sortable?: boolean;
|
||||
}
|
||||
|
||||
export interface AdminNavigationPanelProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
|
||||
eyebrow?: string;
|
||||
title: ReactNode;
|
||||
contexts?: AdminNavigationContext[];
|
||||
headerActions?: ReactNode;
|
||||
contextSlot?: ReactNode;
|
||||
items: AdminNavigationItem[];
|
||||
activeId?: string;
|
||||
footer?: ReactNode;
|
||||
@@ -29,12 +33,15 @@ export interface AdminNavigationPanelProps extends Omit<HTMLAttributes<HTMLEleme
|
||||
navigationLabel?: string;
|
||||
onClose: () => void;
|
||||
onItemChange: (id: string) => void;
|
||||
onItemsReorder?: (ids: string[]) => void;
|
||||
}
|
||||
|
||||
export function AdminNavigationPanel({
|
||||
eyebrow = "NODE.DC",
|
||||
title,
|
||||
contexts = [],
|
||||
headerActions,
|
||||
contextSlot,
|
||||
items,
|
||||
activeId,
|
||||
footer,
|
||||
@@ -42,21 +49,27 @@ export function AdminNavigationPanel({
|
||||
navigationLabel = "Разделы администрирования",
|
||||
onClose,
|
||||
onItemChange,
|
||||
onItemsReorder,
|
||||
className,
|
||||
...props
|
||||
}: AdminNavigationPanelProps) {
|
||||
return (
|
||||
<aside className={cn("nodedc-admin-panel", className)} data-has-contexts={contexts.length > 0 ? "true" : undefined} {...props}>
|
||||
<aside className={cn("nodedc-admin-panel", className)} data-has-contexts={contexts.length > 0 || contextSlot ? "true" : undefined} {...props}>
|
||||
<header className="nodedc-admin-panel__head">
|
||||
<div>
|
||||
<p>{eyebrow}</p>
|
||||
<h2>{title}</h2>
|
||||
</div>
|
||||
<button type="button" className="nodedc-admin-panel__close" aria-label={closeLabel} onClick={onClose}>
|
||||
<span className="nodedc-close-mark" aria-hidden="true" />
|
||||
</button>
|
||||
<div className="nodedc-admin-panel__head-actions">
|
||||
{headerActions}
|
||||
<button type="button" className="nodedc-admin-panel__close" aria-label={closeLabel} onClick={onClose}>
|
||||
<span className="nodedc-close-mark" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{contextSlot ? <div className="nodedc-admin-panel__context-slot">{contextSlot}</div> : null}
|
||||
|
||||
{contexts.length > 0 ? <div className="nodedc-admin-panel__contexts">
|
||||
{contexts.map((context) => (
|
||||
<div className="nodedc-admin-panel__context-group" key={context.id}>
|
||||
@@ -83,7 +96,7 @@ export function AdminNavigationPanel({
|
||||
</div> : null}
|
||||
|
||||
<nav className="nodedc-admin-panel__nav" aria-label={navigationLabel}>
|
||||
{items.map((item) => (
|
||||
{items.filter((item) => !item.sortable).map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
@@ -95,6 +108,29 @@ export function AdminNavigationPanel({
|
||||
<span>{item.label}</span>
|
||||
</button>
|
||||
))}
|
||||
{items.some((item) => item.sortable) ? (
|
||||
<SortableList
|
||||
className="nodedc-admin-panel__sortable-nav"
|
||||
items={items.filter((item) => item.sortable)}
|
||||
getId={(item) => item.id}
|
||||
onReorder={(next) => onItemsReorder?.(next.map((item) => item.id))}
|
||||
>
|
||||
{(item, { handle }) => (
|
||||
<div className="nodedc-admin-panel__sortable-row">
|
||||
<button
|
||||
type="button"
|
||||
className="nodedc-admin-panel__nav-item"
|
||||
data-active={activeId === item.id ? "true" : undefined}
|
||||
onClick={() => onItemChange(item.id)}
|
||||
>
|
||||
<span className="nodedc-admin-panel__nav-icon" aria-hidden="true">{item.icon}</span>
|
||||
<span>{item.label}</span>
|
||||
</button>
|
||||
{handle}
|
||||
</div>
|
||||
)}
|
||||
</SortableList>
|
||||
) : null}
|
||||
</nav>
|
||||
|
||||
{footer ? <footer className="nodedc-admin-panel__footer">{footer}</footer> : null}
|
||||
|
||||
Reference in New Issue
Block a user