본문으로 건너뛰기

예제

경로와 조직

Canonical 경로를 열고 계층 값을 탐색·선택하며 작업 탭을 전환하고 App 소유 조직 프로젝션을 렌더링합니다.

공개 계약NxCanonicalRoutePaneNxOrgChartNxColumnBrowserNxColumnPickerNxTabNav

실행 미리 보기

실시간

Canonical 경로 패널

호스트는 관리 작업 영역을 유지하고 canonical 경로가 레코드 상호작용을 소유합니다.

NxCanonicalRoutePane

계층 선택

계층을 화면에서 탐색하거나 같은 node를 선택 dialog에서 다시 사용합니다.

NxTabNav · NxColumnBrowser · NxColumnPicker
운영

조직 프로젝션

App은 중립적인 조직 항목과 레이블을 제공하고 호스트가 레이아웃, 포커스, 접근성 동작을 소유합니다.

NxOrgChart
2 of 2 visible
김민김민

복사 가능한 소스

코드 예시
TSX
import { useState } from "react";
import {
    NxButton,
    NxCanonicalRoutePane,
    NxColumnBrowser,
    NxColumnPicker,
    NxOrgChart,
    NxTabNav,
    type NxOrgChartLabels,
} from "@nexia/sdk/host";

const WORKSPACE_ROOTS = [
    {
        value: "operations",
        label: "Operations",
        children: [
            { value: "production", label: "Production" },
            { value: "maintenance", label: "Maintenance" },
        ],
    },
    {
        value: "quality",
        label: "Quality",
        children: [
            { value: "incoming", label: "Incoming inspection" },
            { value: "final", label: "Final inspection" },
        ],
    },
];

const labels: NxOrgChartLabels = {
    canvas: "Organization chart",
    focusNode: (label) => `Focus ${label}`,
    clearFocus: "Show full organization",
    expandSubtree: (label) => `Expand ${label}`,
    collapseSubtree: (label) => `Collapse ${label}`,
    showAllMembers: "Show all members",
    hideAllMembers: "Hide all members",
    showMembers: (label, count) => `Show ${count} members in ${label}`,
    hideMembers: (label, count) => `Hide ${count} members in ${label}`,
    memberList: (label) => `${label} members`,
    arrangeCards: "Arrange cards",
    resetLayout: "Reset layout",
    moveCard: (label) => `Move ${label}`,
    addChild: (label) => `Add a team below ${label}`,
    addMember: (label) => `Add a member to ${label}`,
    editColor: (label) => `Edit ${label} color`,
    visibleCount: (visible, total) => `${visible} of ${total} visible`,
    truncated: (limit, total) => `Showing ${limit} of ${total}`,
    root: "Root organization",
    moveNode: (label) => `Move ${label}`,
    moveKeyboardHint: "Use arrow keys to choose a new parent.",
    movePreview: (moving, parent, position, total) =>
        `Move ${moving} under ${parent}, position ${position} of ${total}`,
};

export function RouteAndOrganizationExample() {
    const [paneOpen, setPaneOpen] = useState(false);
    const [pickerOpen, setPickerOpen] = useState(false);
    const [activeTab, setActiveTab] = useState("browse");
    const [selectedArea, setSelectedArea] = useState<string | null>(
        "production",
    );
    const [selectedOrganizationId, setSelectedOrganizationId] = useState<
        string | null
    >(null);

    return (
        <div className="grid gap-6" data-pane-path="/apps/quality/inspections">
            <section className="rounded-control border border-border-subtle p-4">
                <h2 className="font-medium">Open a canonical Resource route</h2>
                <p className="mt-1 text-sm text-text-secondary">
                    Keep the management workspace mounted while the owning
                    Resource route handles the write.
                </p>
                <NxButton className="mt-4" onClick={() => setPaneOpen(true)}>
                    Review inspection
                </NxButton>
                <NxCanonicalRoutePane
                    open={paneOpen}
                    route="/apps/quality/inspections/inspection-1042"
                    closeRoute="/apps/quality/inspections"
                    title="Inspection INS-1042"
                    onOpenChange={setPaneOpen}
                />
            </section>

            <section className="grid gap-4 rounded-control border border-border-subtle p-4">
                <NxTabNav
                    items={[
                        { id: "browse", label: "Browse areas" },
                        { id: "recent", label: "Recent", badge: 3 },
                    ]}
                    value={activeTab}
                    onChange={setActiveTab}
                    aria-label="Area views"
                />
                <NxColumnBrowser
                    roots={WORKSPACE_ROOTS}
                    value={selectedArea}
                    onSelect={(value) => setSelectedArea(value)}
                    searchable
                    searchPlaceholder="Search areas"
                    ariaLabel="Operational areas"
                    heightClassName="h-72"
                    renderPreview={(node) => (
                        <p className="text-sm text-text-secondary">
                            Selected area: {node.label}
                        </p>
                    )}
                />
                <div>
                    <NxButton
                        variant="secondary"
                        onClick={() => setPickerOpen(true)}
                    >
                        Choose in a dialog
                    </NxButton>
                </div>
                <NxColumnPicker
                    open={pickerOpen}
                    onClose={() => setPickerOpen(false)}
                    title="Choose an operational area"
                    roots={WORKSPACE_ROOTS}
                    value={selectedArea}
                    searchable
                    searchPlaceholder="Search areas"
                    onSelect={(value) => {
                        setSelectedArea(value);
                        setPickerOpen(false);
                    }}
                />
            </section>

            <section className="rounded-control border border-border-subtle p-4">
                <h2 className="font-medium">
                    Render an organization projection
                </h2>
                <div className="mt-4 h-[28rem]">
                    <NxOrgChart
                        items={[
                            {
                                id: "operations",
                                parentId: null,
                                label: "Operations",
                                description: "Seoul Plant",
                            },
                            {
                                id: "quality",
                                parentId: "operations",
                                label: "Quality",
                                members: [{ id: "min", label: "Min Kim" }],
                            },
                        ]}
                        labels={labels}
                        selectedId={selectedOrganizationId}
                        onSelect={setSelectedOrganizationId}
                    />
                </div>
            </section>
        </div>
    );
}