- OrgChart -> 조직도 and sub menus (개요, 부서별 색상, 전체 구성, 확장 조직도); Story IDs kept - 노선도 menu/page titles in Korean (제목, 정보, 노선·공간, 시설물) - Department Colors cards 3 columns (2 under 960px)
68 lines
4.4 KiB
TypeScript
68 lines
4.4 KiB
TypeScript
import { StrictMode, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||
import type { Meta, StoryObj } from '@storybook/react-vite';
|
||
import { OrgChart } from '@hm-design/org-chart-react/hm-dialog';
|
||
import {
|
||
companyColorPresets, createOrgChartExampleDataset, JsonOrgChartDataSource,
|
||
type CompanyId, type OrgChartAutoLayoutOptions, type OrgChartDataset, type OrgChartInteractionOptions,
|
||
} from '@hm-design/org-chart';
|
||
import engineUrl from '@hm-design/org-chart/engine.css?url';
|
||
import coreUrl from '@hm-design/org-chart/style.css?url';
|
||
import { StoryPage, StoryPageHeader } from '@/components/story-page';
|
||
import large from '../../examples/org-chart/data-expanded-large.json';
|
||
import './org-chart-stories.css';
|
||
import '../center/center-stories.css';
|
||
import './org-chart-expanded-story.css';
|
||
|
||
const template = large as OrgChartDataset;
|
||
const allCompanies = Object.values(companyColorPresets).map(company => company.companyId as CompanyId);
|
||
const compositionStylesheets = { engine: engineUrl, core: coreUrl };
|
||
const topNodes = { ptc: { title: '기술총괄', name: '가상책임자 5' } };
|
||
// Preview only: fixed sample (7 companies × 20 = 140) with the former default settings.
|
||
const layout: OrgChartAutoLayoutOptions = { type: 'tb', hybridStartDepth: 2, initialVisibleDepth: 'all' };
|
||
const interactions: OrgChartInteractionOptions = { collapse: true, zoom: true, pan: true };
|
||
|
||
// Story-only: hides Core's explanatory toolbar text (as-of date, selection count, Drag & Drop guide) on screen.
|
||
// The elements stay in the shadow DOM: the move feedback remains the cards' aria-describedby / live status
|
||
// (visually hidden), and the OrgChart browser checks still read their text.
|
||
const previewText = new CSSStyleSheet();
|
||
previewText.replaceSync(`
|
||
.hm-orgchart-date, .hm-orgchart-expanded-selection { display: none; }
|
||
.hm-orgchart-move-feedback { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
|
||
`);
|
||
function hidePreviewText(container: HTMLElement): () => void {
|
||
const adopt = () => {
|
||
const shadow = container.querySelector('.hm-orgchart-host')?.shadowRoot;
|
||
if (shadow && !shadow.adoptedStyleSheets.includes(previewText)) shadow.adoptedStyleSheets = [...shadow.adoptedStyleSheets, previewText];
|
||
};
|
||
const observer = new MutationObserver(adopt);
|
||
observer.observe(container, { childList: true, subtree: true });
|
||
adopt();
|
||
return () => observer.disconnect();
|
||
}
|
||
|
||
/** Existing Expanded Story only: a chart preview without setting panels. */
|
||
function ExpandedPreview() {
|
||
const [error, setError] = useState<string | null>(null);
|
||
const preview = useRef<HTMLDivElement>(null);
|
||
useLayoutEffect(() => hidePreviewText(preview.current!), []);
|
||
const source = useMemo(() => new JsonOrgChartDataSource(createOrgChartExampleDataset(template, {
|
||
scope: 'per-company', employeeCount: 20, companyIds: allCompanies,
|
||
})), []);
|
||
|
||
return <StoryPage className="hm-orgchart-story-page hm-orgchart-story-expanded">
|
||
<StoryPageHeader title="확장 조직도" />
|
||
{/* Preview first: the chart sits right under the page title; its own header already names it, so no section header. */}
|
||
<div className="hm-orgchart-story hm-orgchart-story-lead">
|
||
{error ? <p role="alert" className="hm-orgchart-story-note">{error}</p> : null}
|
||
<div ref={preview} className="hm-orgchart-story-preview sb-center">
|
||
<OrgChart dataSource={source} stylesheetUrls={compositionStylesheets} displayMode="readOnly" layoutMode="auto" autoLayout={layout} interactions={interactions} dragDropEnabled={false} selectedCompanyIds={allCompanies} companyTopNodes={topNodes} employeePopup="hm-dialog" className="hm-orgchart-story-chart" onLifecycleError={cause => setError(cause instanceof Error ? cause.message : '조직도 설정을 적용할 수 없습니다.')} onStateChange={state => { if (state.status === 'error') setError(state.issues.map(issue => issue.message).join(' / ')); }} />
|
||
</div>
|
||
</div>
|
||
</StoryPage>;
|
||
}
|
||
|
||
const meta = { title: '조직도/확장 조직도', component: ExpandedPreview, parameters: { layout: 'fullscreen', controls: { disable: true } }, decorators: [(Story) => <StrictMode><Story /></StrictMode>] } satisfies Meta<typeof ExpandedPreview>;
|
||
export default meta;
|
||
type Story = StoryObj<typeof meta>;
|
||
export const ExpandedOrgChart: Story = { name: '확장 조직도', parameters: { __id: 'orgchart--expanded-org-chart' } };
|