Files
HMDesign/src/org-chart/org-chart-expanded.stories.tsx
T
shkim4 0f1574f80f style(storybook): localize 조직도 and 노선도 menus, Department Colors 3 columns
- OrgChart -> 조직도 and sub menus (개요, 부서별 색상, 전체 구성, 확장 조직도); Story IDs kept
- 노선도 menu/page titles in Korean (제목, 정보, 노선·공간, 시설물)
- Department Colors cards 3 columns (2 under 960px)
2026-11-09 18:26:11 +09:00

68 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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' } };