feat(org-chart): add core cards and fixed-layout integration

This commit is contained in:
shkim4 committed 2026-10-12 17:58:30 +09:00
1 parent d18e3c3380
commit 61c6f8d1f1
161 files changed
+13044 -1

No files matched your search

+56
View File
@@ -0,0 +1,56 @@
import { StrictMode, useMemo, useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from '@hm-design/ui';
import { OrgChart } from '@hm-design/org-chart-react';
import { JsonOrgChartDataSource } 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 fixture from '../../examples/org-chart/data-p1.json';
import './org-chart-stories.css';
import { CoreComponentPreview } from './core-component-preview';
const compositionSource = new JsonOrgChartDataSource(fixture);
const compositionStylesheets = { engine: engineUrl, core: coreUrl };
/** View-only Workdesk composition: the same Core/React Wrapper with
* displayMode="readOnly". No Story notes, test controls or collapse buttons;
* JSON update/lifecycle and collapse checks stay in the internal Content Stories. */
function CompositionPreview() {
return <section className="hm-orgchart-story hm-orgchart-story-full" aria-label="Full Composition">
<OrgChart dataSource={compositionSource} stylesheetUrls={compositionStylesheets} displayMode="readOnly" className="hm-orgchart-story-chart" />
</section>;
}
function DepartmentTypographyPreview() {
const [longNames, setLongNames] = useState(false);
const data = useMemo(() => {
const data = structuredClone(fixture);
if (longNames) for (const id of ['mock-leader-00', 'mock-leader-01', 'mock-employee-01']) {
data.employees.find(item => item.id === id)!.name = '아주긴가상이름표시검증사례';
}
return data;
}, [longNames]);
return <section className="hm-orgchart-story">
<p className="hm-orgchart-story-note">기본 이름은 2–3음절의 가상 이름입니다. 긴 이름 검증에서는 폰트·사진·카드 크기를 유지하며 말줄임된 이름에 Hover 또는 Tab Focus로 전체 이름을 확인하고 Escape로 닫을 수 있습니다.</p>
<div className="hm-orgchart-story-controls"><Button appearance="outline" aria-pressed={longNames} onClick={() => setLongNames(value => !value)}>긴 이름 검증 {longNames ? '종료' : '시작'}</Button></div>
<CoreComponentPreview kind="DepartmentColors" data={data} />
</section>;
}
const meta = { title: 'OrgChart', component: CompositionPreview, parameters: { layout: 'padded', controls: { disable: true } }, decorators: [(Story) => <StrictMode><Story /></StrictMode>] } satisfies Meta<typeof CompositionPreview>;
export default meta;
type Story = StoryObj<typeof meta>;
export const LogoPersonnelSummary: Story = {
name: 'Logo · Personnel Summary',
render: () => <section className="hm-orgchart-story" aria-label="Logo · Personnel Summary">
<CoreComponentPreview kind="Logo" />
<CoreComponentPreview kind="PositionSummary" />
<CoreComponentPreview kind="AffiliationSummary" />
</section>,
};
export const DepartmentColors: Story = { name: 'Department Colors', render: () => <DepartmentTypographyPreview /> };
export const FullComposition: Story = { name: 'Full Composition' };
// Preserve existing standalone Story IDs for verification and direct links.
// The default manager excludes "internal"; user-facing navigation has three pages.
export const Logo: Story = { name: 'Logo', tags: ['internal'], render: () => <CoreComponentPreview kind="Logo" /> };
export const PositionSummary: Story = { name: 'Position Summary', tags: ['internal'], render: () => <><p className="hm-orgchart-story-note">가상 직원 데이터 자동 집계 · 실제 운영 인원수가 아닙니다.</p><CoreComponentPreview kind="PositionSummary" /></> };
export const AffiliationSummary: Story = { name: 'Affiliation Summary', tags: ['internal'], render: () => <><p className="hm-orgchart-story-note">가상 직원 데이터 자동 집계 · 실제 운영 인원수가 아닙니다.</p><CoreComponentPreview kind="AffiliationSummary" /></> };