Drop page / section descriptions, state notes and repeated captions from the representative Stories of 44 components, the Patterns, Center Graphic and OrgChart pages. Value readouts, spec lists and captions hide only on the representative page; hidden verification Stories keep them. Tabs Default API and the Filter Bar draft / applied counts move to the hidden DefaultApi and DraftApplied Stories; Center Overview is hidden with its direct URL kept. Story IDs are unchanged. Align the component, pattern and OrgChart docs with the pages, point the quality reference check at the DraftApplied Story, and make the P8 styles check expect no section header on the preview-only Expanded page.
309 lines
21 KiB
Markdown
309 lines
21 KiB
Markdown
# Expanded OrgChart 사용 및 스타일 — P7
|
||
|
||
2026-10-12 사용자 변경 요구사항으로 **현재 확장형 카드 외형과 크기를 유지**한다.
|
||
`Group 3391.svg`, `Group 1171288761.svg` 검색·재현·용도 배정은 이번 완료 조건에서 제외한다.
|
||
이 결정은 이전 P5-1B/P5-2/P5-3 검증 보고의 당시 미검증 기록을 변경하지 않는다.
|
||
Fixed의 승인 SVG·1920×914.5 구성·컬러·팝업은 기존 정책을 유지한다.
|
||
|
||
## Vanilla JS와 JSON Source
|
||
|
||
아래는 Vite를 사용하는 호스트의 공개 API 예시다. 순수 HTML 배포에서는 공개 CSS·ESM
|
||
산출물을 호스트가 제공하고 URL을 지정한다. 실행 가능한 HTML은
|
||
`examples/org-chart/expanded.html`과 `expanded-app.js`를 참고한다.
|
||
|
||
```js
|
||
import { createOrgChart, JsonOrgChartDataSource, getCompanyColorPreset } from '@hm-design/org-chart';
|
||
import engineCssUrl from '@hm-design/org-chart/engine.css?url';
|
||
import coreCssUrl from '@hm-design/org-chart/style.css?url';
|
||
import dataset from './data-expanded-small.json'; // 기존 20명 가상 JSON을 호스트에 복사
|
||
|
||
const chart = createOrgChart({
|
||
container: document.getElementById('chart'),
|
||
dataSource: new JsonOrgChartDataSource(dataset),
|
||
stylesheetUrls: { engine: engineCssUrl, core: coreCssUrl },
|
||
layoutMode: 'auto', // 'fixed' 또는 생략은 기존 Workdesk
|
||
displayMode: 'readOnly',
|
||
selectedCompanyIds: ['hanmac'], // 단일 회사
|
||
companyTopNodes: { hanmac: { title: '회장', display: 'card' } },
|
||
employeeConnections: { 'hanmac-office-0': 'left' },
|
||
zoom: { min: 0.05, max: 3, step: 1.2 },
|
||
});
|
||
await chart.mount();
|
||
await chart.setSelectedCompanies(['hanmac', 'saman']); // 복수 회사
|
||
await chart.setSelectedCompanies(); // 전체
|
||
await chart.setSelectedCompanies([]); // 명시적 빈 선택
|
||
chart.zoomTo(1); // 배율만 변경; 100% 도구 버튼은 이동 위치도 복원
|
||
chart.panBy(40, 0);
|
||
chart.fitToView();
|
||
console.log(chart.getViewportState(), getCompanyColorPreset('hanmac')?.primary);
|
||
// 호스트가 더 이상 컴포넌트를 사용하지 않을 때 chart.destroy()
|
||
```
|
||
|
||
`JsonOrgChartDataSource`는 인라인 JSON 또는 호스트가 제공하는 HTTP(S)/상대 URL을 받는다.
|
||
URL을 사용할 경우 `new JsonOrgChartDataSource('./data-expanded-large.json')`처럼 지정한다.
|
||
file:// Fetch는 지원하지 않는다. 이번 작업에 외부 API·서버·DB 구현은 추가하지 않았다.
|
||
기존 JSON 예시는 Small 20명/3회사, Medium 100명/5회사, Large 300명/7회사다.
|
||
P7의 7회사 합산·회사별 선택은 Large를 기반으로 아래 공개 helper를 사용한다.
|
||
|
||
Storybook·AI 생성 데이터의 조직 위계는 [AI 생성 정책 §2.1](ai-page-generation-rules.md#21-확장형-조직-위계-규칙)을 따른다. 셀의 직접 자식 및 모든 하위 계층에 팀을 배치하지 않으며 팀 → 셀은 허용한다. 셀을 일괄 말단으로 제한하지 않는다. fixture 생성기는 Large의 기존 ID·직원·분배를 유지하면서 `실 → 팀 → 셀`과 실 아래 형제 협력팀을 만든다. Small/Medium은 기존 구조를 유지한다. TB / LR / Hybrid는 같은 위계를 표시하고 helper는 template의 위계를 보존한다. 제품 Validator·Drag & Drop의 새 계층 거절 기능은 이번 데이터 정책에 포함되지 않는다.
|
||
|
||
## React
|
||
|
||
```tsx
|
||
import { useState } from 'react';
|
||
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 dataset from './data-expanded-small.json';
|
||
|
||
const source = new JsonOrgChartDataSource(dataset);
|
||
const stylesheets = { engine: engineUrl, core: coreUrl };
|
||
const topNodes = { hanmac: { title: '회장', display: 'card' as const } };
|
||
const connections = { 'hanmac-office-0': 'left' as const };
|
||
|
||
export function ExpandedExample() {
|
||
const [selected, setSelected] = useState<string[] | undefined>(['hanmac', 'saman']);
|
||
return <>
|
||
<button type="button" onClick={() => setSelected(undefined)}>전체 회사</button>
|
||
<OrgChart dataSource={source} stylesheetUrls={stylesheets} layoutMode="auto"
|
||
displayMode="readOnly" selectedCompanyIds={selected}
|
||
companyTopNodes={topNodes} employeeConnections={connections} />
|
||
</>;
|
||
}
|
||
```
|
||
|
||
위 native 버튼은 React 계약만 설명하는 최소 예시다. HM 화면에서는 실제 기존
|
||
`Button`, `Checkbox`, `Label`, `Select`를 조합한다. Expanded Story는 미리보기 전용이라 이 컨트롤을 포함하지 않는다.
|
||
Source·옵션 객체를 안정적으로 유지한다. Core 생성 옵션(layoutMode·TopNode·연결 방향·Zoom 범위)을
|
||
변경하면 React는 handle을 다시 생성한다. Vanilla는 새 handle을 생성한다.
|
||
`autoLayout`·`interactions`·회사 선택·팝업 선택은 기존 인스턴스에서 갱신한다.
|
||
회사 선택은 기존 setter/React prop으로 변경하며 원본 JSON과 parentId를 수정하지 않는다.
|
||
React에는 별도 레이아웃 알고리즘이나 imperative ref API가 없다.
|
||
|
||
## 테마·최상위 노드·연결 방향
|
||
|
||
회사 Root의 `Organization.companyId`가 자손에게 상속된다. 회사별 독립 Root와 기존
|
||
Employee 관계를 유지한다. `companyId` 생성 옵션은 기존 JSON의 회사 판별 fallback이며,
|
||
다중 회사 전체를 한 색으로 바꾸는 설정이 아니다.
|
||
|
||
| ID | 회사 | 메인 컬러 |
|
||
|---|---|---|
|
||
| hanmac | 한맥기술 | #CB2E28 |
|
||
| saman | 삼안 | #F08300 |
|
||
| jangheon-industry | 장헌산업 | #4580A6 |
|
||
| jangheon | 장헌 | #1D418D |
|
||
| ptc | 피티씨 | #84338E |
|
||
| halla | 한라산업개발 | #0068B7 |
|
||
| baron | 바론컨설턴트 | #0C367F |
|
||
|
||
표의 값은 기존 `getCompanyColorPreset(companyId)`에서 조회한다. 카드에 중복 하드코딩하지 않는다.
|
||
타이틀은 조직 회사, 카드 강조색은 알려진 직원 affiliation(미등록 시 조직 회사)의 프리셋을 쓴다.
|
||
현재 사용자 확정에 따라 모든 회사 타이틀은 normal/hover/focus/접힘/펼침에서 흰색을 유지한다.
|
||
이는 P7 시작 전 기존 미커밋 변경을 보존한 결과다. 삼안·장헌산업 흰 글자의 대비 진단은
|
||
접근성 승인으로 재분류하지 않으며, 이번 기능 확장으로 메인 컬러를 바꾸지 않는다.
|
||
|
||
`companyTopNodes`는 `employeeId`, `title`, `name`, `profileImage`, `organizationName`,
|
||
`display: 'card' | 'titleOnly' | 'hidden'`을 지원한다. 생략 시 Root의 leaderId를 사용하며,
|
||
employeeId는 그 Root에 소속된 기존 직원이어야 한다. null은 최상위 카드 배정을 제거한다.
|
||
표시 override는 원본 identity·팝업 데이터·callback·관계를 바꾸지 않는다.
|
||
|
||
`employeeConnections`의 지원 값은 `top | left | right`다. Depth를 기준으로 정하지 않는다.
|
||
직원 연결선의 실제 도착점과 같은 면에만 회사 Border를 표시하며, 조직장은 타이틀 아래
|
||
TB/Hybrid에서는 상단 연결을 사용한다. LR은 조직장·일반 직원 모두 왼쪽에서 연결되며
|
||
직원별 실제 도착 면과 왼쪽 Border가 일치한다. 다른 면은 중립, 강조는 inset이라 외형 크기가 변하지 않는다.
|
||
연결 없는 카드에 임의로 accent를 붙이는 별도 `none` API는 없다. 현재 Auto presenter의
|
||
렌더링된 카드는 모두 타이틀 또는 이전 카드/분기 rail과 연결된다.
|
||
|
||
## 접기·펼치기와 직원 팝업
|
||
|
||
그룹 타이틀 전체 native button은 click·Enter·Space로 접기/펼치기하며 `aria-expanded`와
|
||
표시 기호를 갱신한다. 조직장은 유지하고 일반 직원·자손을 숨기며 형제 상태는 독립이다.
|
||
부모 재확장 시 유효한 하위 상태를 유지한다. 하위 직원/조직 없는 타이틀은 disabled다.
|
||
그룹 링크는 별도 아이콘으로 페이지 이동과 토글 동작을 분리한다.
|
||
공개 프로그래밍 방식 collapse setter는 제공하지 않는다.
|
||
|
||
Vanilla 직원 카드는 click·Enter·Space로 공통 직원 정보 dialog를 연다. dialog는 변환 forest 밖의
|
||
native top layer에 표시되므로 Zoom과 Stage overflow의 영향을 받지 않는다.
|
||
ESC/닫기 버튼과 focus trap·카드 focus 복귀를 제공한다.
|
||
`onEmployeeClick(employee, context)` 지정 시 기본 팝업 대신 callback을 호출하며
|
||
호스트가 dialog 접근성·닫기·focus 복귀를 책임진다.
|
||
|
||
P5-4는 Tab으로 화면 밖 카드·타이틀에 도달하면 **배율을 유지하고 Pan으로 표시**한다.
|
||
드래그 직후 포인터 click만 억제하고 이후 Enter/Space 활성화는 허용한다.
|
||
실제 스크린리더 음성·실제 모바일 터치는 별도 검증 대상이다.
|
||
|
||
## 카드 CSS 관리
|
||
|
||
현재 기본 카드 크기는 일반 직원 width 114px/min-height 54px, 조직장·최상위
|
||
width 154px/min-height 72px이며 사진은 36×36px
|
||
비원형 슬롯이다. 직위/이름 10/13px, Noto Sans KR, padding 8px, 기본 border 1px,
|
||
inset accent 3px를 유지한다. 3글자 한글 이름은 `홍 길 동`처럼 표시하며 직위 공백은
|
||
표시 계층에서만 제거한다. 긴 가상 이름이 두 줄이면 일반 직원의 실측 높이는 67px로
|
||
자연 확장된다(기존 동작). 실제 profileImage를 우선하고 없음/실패는 기존 공통 사람 SVG다.
|
||
|
||
Card geometry는 `packages/org-chart/src/styles/org-chart-expanded.css`에 Auto 전용으로 관리한다.
|
||
원본 Fixed CSS·SVG·Theme는 수정하지 않는다. `layoutConfig`·카드 교체 API는 없다.
|
||
Auto 부모·자식 관계선과 직원 연결선은 전용 `--hm-orgchart-expanded-line-color`
|
||
변수(기본 `#738399`)를 공유한다. 카드의 중립 Border·회사별 Border 강조와 Fixed
|
||
연결선은 이 변수를 사용하지 않는다. 배경 또는 이 색상을 재정의할 때는 실제
|
||
합성 배경과 computed 표시색으로 비텍스트 대비 3:1 이상을 별도로 확인한다.
|
||
Core는 Shadow DOM을 사용하므로 일반 호스트 CSS selector는 내부 카드에 닿지 않는다.
|
||
|
||
향후 별도 디자인 변경이 승인된다면 호스트가 공개 Core CSS 뒤에 다음 override를 결합한
|
||
CSS 자산을 만들고 그 URL을 `stylesheetUrls.core`로 제공할 수 있다(이번에는 적용하지 않음).
|
||
`--hm-orgchart-expanded-*` 중 내부 선언이 있는 변수는 호스트 div에 설정하면 덮어써질 수
|
||
있으므로 **Shadow DOM에 로드되는 CSS의 `.hm-orgchart-expanded`에서 재정의**한다.
|
||
|
||
```css
|
||
/* 공개 Core CSS 다음에 결합하는 Auto 전용 예시. 임의 신규 API가 아니다. */
|
||
.hm-orgchart-expanded {
|
||
--hm-orgchart-expanded-card-width: 114px;
|
||
--hm-orgchart-expanded-card-height: 54px;
|
||
--hm-orgchart-expanded-leader-width: 154px;
|
||
--hm-orgchart-expanded-leader-height: 72px;
|
||
--hm-orgchart-expanded-card-accent-width: 3px;
|
||
--hm-orgchart-expanded-photo-size: 36px;
|
||
}
|
||
```
|
||
|
||
크기 변경 시 기존 ResizeObserver가 article의 실측 높이와 실제 endpoint를 재계산한다.
|
||
향후 변경에는 Fit·형제/하위 트리 겹침·텍스트 overflow를 다시 확인해야 한다.
|
||
P7도 기본 카드 geometry를 바꾸지 않는다. LR/Hybrid 300명과 2,100명의 실측은
|
||
과거 P5/P6 성능과 분리하여 P7 보고서에 기록한다.
|
||
|
||
과거 검증은 [P5-4 보고서](implementation-report-p5-4.md), P7 변경과 실측은
|
||
[P7 보고서](implementation-report-p7.md)를 참고한다.
|
||
|
||
## P7 데이터·레이아웃·독립 옵션
|
||
|
||
```js
|
||
import { createOrgChartExampleDataset } from '@hm-design/org-chart';
|
||
import template from './data-expanded-large.json';
|
||
|
||
const dataset = createOrgChartExampleDataset(template, {
|
||
scope: 'per-company', // 'total'이면 전체 7회사 합산 employeeCount
|
||
employeeCount: 300, // 20 | 100 | 300
|
||
companyIds: ['hanmac', 'saman'], // 생략하면 7회사, 이 예시는 600명
|
||
});
|
||
const chart = createOrgChart({
|
||
...configuredBaseOptions,
|
||
dataSource: new JsonOrgChartDataSource(dataset),
|
||
layoutMode: 'auto',
|
||
autoLayout: { type: 'lr', initialVisibleDepth: 'all' },
|
||
interactions: { collapse: false, zoom: true, pan: false },
|
||
});
|
||
await chart.mount();
|
||
await chart.setAutoLayout({ type: 'hybrid', hybridStartDepth: 3 });
|
||
await chart.setInteractions({ collapse: true }); // 다른 설정은 그대로
|
||
```
|
||
|
||
총량 모드는 회사별 가중 분배 후 선택한 회사만 필터링하며 재분배하지 않는다.
|
||
회사별 모드는 선택 회사마다 정확히 N명, 전체 7회사 × 300명 = 2,100명이다.
|
||
ID는 deterministic 가상 namespace로 생성하며 기존 직원 기록·조직 ID·부모 관계를 재사용한다.
|
||
원본은 변경하지 않고 반환 snapshot은 deep freeze한다. helper의 빈 회사 선택은 유효한
|
||
조직 데이터가 될 수 없어 거절하며, 화면의 빈 선택은 `setSelectedCompanies([])`로 표시한다.
|
||
|
||
| 옵션 | TB | LR | Hybrid | 제약 및 전환 |
|
||
|---|---|---|---|---|
|
||
| 레이아웃 `type` | 지원 | 지원 | 지원 | 다른 기능을 켤 필요 없음 |
|
||
| `hybridStartDepth: 2/3/4` | 적용 안 함 | 적용 안 함 | 지원 | Root=1Depth, 기본 3 |
|
||
| `hybridOrganizationIds` | 지정 그룹 자손 세로 배치 | 조합 거절 | 조합 거절 | LR/Hybrid 전환 전 목록 해제; Story는 자동 해제·disabled |
|
||
| `initialVisibleDepth: 1/2/3/'all'` | 지원 | 지원 | 지원 | 기본 all; 값을 바꾸면 접힘 상태를 초기 정책으로 재설정 |
|
||
| `interactions.collapse/zoom/pan` | 각각 지원 | 각각 지원 | 각각 지원 | 각각 기본 true; false도 다른 기능 사용을 막지 않음 |
|
||
| 회사 선택·직원 팝업 | 지원 | 지원 | 지원 | 특정 레이아웃·Zoom·Pan·접기 사용을 요구하지 않음 |
|
||
| Compact | 미지원 | 미지원 | 미지원 | 엔진 compact DOM/140×50 grid가 기존 HM 카드·접기 계약과 충돌 |
|
||
|
||
TB는 기존 경로를 유지한다. LR은 실제 dabeng `direction: 'l2r'`와 재귀 hierarchy를 사용한다.
|
||
원본 `.title/.content` 전용 회전 CSS는 HM 복합 article에 맞지 않아 Auto 범위에서
|
||
회전을 해제하고 부모 좌측·자식 우측·형제 세로 배치를 구성한다. Hybrid는 실제
|
||
`verticalLevel`/그룹 `hybrid`를 사용한다. 측정한 부모·자식 좌표로 연결선을 갱신하며
|
||
Fixed의 CSS·엔진 옵션·기존 native 팝업은 보존한다.
|
||
|
||
접기·레이아웃 전환은 유효한 조직 ID의 접힘 상태를 유지한다. 데이터·회사·레이아웃
|
||
전환은 표시된 카드·타이틀·연결선 전체 경계를 다시 측정하여 가로 중앙을 갱신한다.
|
||
자동 배치는 현재 배율을 유지하며 큰 조직도를 임의로 축소하지 않는다. 사용자가 Pan·Zoom·
|
||
100% 복원 또는 화면 밖 focus 노출로 이동한 뒤에는 데이터·회사·레이아웃 전환과 Resize에서도
|
||
배율·이동 위치를 보존한다. 명시적 Fit to View는 전체 표시 영역을 축소해 담고 가로·세로 중앙에
|
||
배치하며 자동 중앙 배치를 다시 허용한다. 개별 interaction/popup 변경은 기존 viewport와
|
||
접힘 상태를 보존한다. Pan을 꺼도 키보드로 화면 밖 카드에 도달하면 배율 유지·focus
|
||
노출을 제공한다. Fit/100% 복원은 Zoom/Pan 사용 여부와 독립적으로 가능하다.
|
||
2,100명 전체 Fit은 개요용으로 작게 축소되므로 카드 읽기에는 Zoom 또는 초기 Depth를 사용한다.
|
||
|
||
React에서 명시적인 `@hm-design/org-chart-react/hm-dialog` Entry와
|
||
`employeePopup="hm-dialog"`는 실제 공개 HM Dialog·Avatar·Button을 사용한다.
|
||
`'core'`가 기본, `'none'`은 카드의 클릭·button 의미를 제거하되 키보드 이동용 초점은 유지한다. `onEmployeeClick`을
|
||
지정하면 선택 모드와 관계없이 callback이 우선한다. HM 모드는
|
||
`@hm-design/ui@0.1.0` optional peer와 호스트 `index.css → hm-theme.css` 연결이 필요하다.
|
||
기본 Entry `@hm-design/org-chart-react`는 HM runtime/type Import 없이 Core 팝업을
|
||
사용한다. UI 설치만으로 전환하지 않는다. 다른 디자인 시스템은 기본 Entry에서
|
||
`employeePopup="adapter"`와 `employeePopupAdapter`를 명시하여 연결한다.
|
||
Core/Vanilla와 기존 데이터에는 React/HM 의존성이나 변경을 추가하지 않았다.
|
||
기존 HM 소비자는 Import만 `/hm-dialog`로 변경하고 기존 Props를 유지한다.
|
||
모든 bundler 조합은 별도 미검증이다.
|
||
|
||
```tsx
|
||
import { OrgChart } from '@hm-design/org-chart-react/hm-dialog';
|
||
|
||
<OrgChart dataSource={source} stylesheetUrls={stylesheets} layoutMode="auto"
|
||
autoLayout={{ type: 'lr', initialVisibleDepth: 2 }}
|
||
interactions={{ collapse: false, zoom: true, pan: false }}
|
||
employeePopup="hm-dialog" selectedCompanyIds={['hanmac', 'saman']} />
|
||
```
|
||
|
||
## P9.3 브라우저 소속 변경
|
||
|
||
P9.4의 공통 Core/React 옵션 `dragDropEnabled?: boolean`은 기본 OFF다. 아래 소속 변경은
|
||
ON에서 허용한다. React는 `dragDropEnabled={true}`, Vanilla는 생성 옵션 또는
|
||
`handle.setDragDropEnabled(true)`로 활성화한다. `handle.getDragDropEnabled()`로
|
||
현재 설정을 조회한다. OFF의 `handle.move()`는 `EDITING_DISABLED`를 반환하며 포인터와
|
||
Alt+M도 시작하지 않는다. 전환 시 진행 중 이동·Pointer capture·Drop 강조를 취소하고
|
||
이미 완료한 이동을 보존한다. 설정만 바꿀 때 데이터 재요청·재생성·레이아웃 갱신은 없다.
|
||
직원 정보, 그룹 접기·펼치기, Zoom/Pan/Fit은 기존 독립 설정을 따른다. Fixed는 변경하지 않는다.
|
||
|
||
Expanded Story(2026-10-22~)는 조직도만 보여주는 미리보기 전용 화면이다. 데이터 설정
|
||
(회사 선택·회사당 직원 수·데이터 적용·초기화), 레이아웃 설정, 인터랙션·직원 정보 설정
|
||
UI는 제거했다. 고정 표시 조건은 `createOrgChartExampleDataset`의 회사별 기준 7개 회사×20명=140명,
|
||
세로형 TB·전체 펼침, 접기·펼치기·Zoom·Pan·Fit 사용, 직원 클릭 HM Dialog, Drag & Drop OFF다.
|
||
공개 helper·`selectedCompanyIds`·`dragDropEnabled`·`onMove` 계약은 유지하며 다른 화면과
|
||
소비 프로젝트는 이 옵션들을 그대로 사용할 수 있다. Story 브라우저 검증(P7·P8·P9·P9.2~P9.5,
|
||
hierarchy, HM Story)은 이 고정 미리보기의 렌더링·접기·Zoom/Pan/Fit·HM Dialog만 확인하고,
|
||
소속 변경·Drag & Drop ON/OFF 전환·진행 중 취소는 `verify-p9-3-core.mjs`·`verify-p9-4-core.mjs`의 Vanilla Core 검증이 담당한다.
|
||
2026-10-23부터 Story는 Core 툴바의 안내 문구를 Story 전용 shadow stylesheet로 숨긴다. 기준일과
|
||
선택 회사·인원 요약은 표시하지 않고, Drag & Drop 이동 안내는 시각적으로만 숨겨 live status·
|
||
`aria-describedby`로 남긴다. DOM 요소와 접기·Zoom·Pan·Fit·HM Dialog 기능은 그대로다. Core·React 기본 표시와 공개 API는
|
||
바뀌지 않으며 소비 프로젝트가 이 숨김 방식을 따라 할 필요는 없다.
|
||
|
||
Expanded Story의 외곽 미리보기는 실제 Center Storybook 공통 카드 CSS의
|
||
`--sb-center-card-background` / `--sb-center-card-border` / `--sb-center-card-radius`를
|
||
재사용한다. 전용 `--hm-orgchart-expanded-preview-background`, `-border`, `-radius`
|
||
입력은 `.hm-orgchart-expanded` 외곽에만 적용한다. 직원 카드·회사 타이틀·Viewport의
|
||
색상 입력은 그대로이며, 입력을 생략한 Vanilla의 기존 기본 외곽 스타일은 유지한다.
|
||
|
||
Auto의 빈 공간 드래그는 기존 Pan이며 직원 카드·그룹 타이틀 드래그는 회사 내부 또는
|
||
회사 간 소속 변경이다. 직원 이동은 `organizationId`, 조직 그룹 이동은 `parentId`를
|
||
갱신한다. 같은 회사 내부에서는 파견 직원을 포함한 기존 `affiliationId`를 보존한다.
|
||
회사 간 직원 이동은 `affiliationId`도 대상 회사로 변경하고, 회사 간 그룹 이동은 이동
|
||
그룹과 하위 조직 전체의 `companyId`, 소속 직원 전체의 `affiliationId`도 대상 회사로
|
||
변경한 새 snapshot을 현재 Core 인스턴스에 적용한다. ID·하위 계층·
|
||
이름·직위·사진·조직장·정렬은 보존하며 회사 색상과 인원 집계는 대상 회사에 맞춰 갱신한다.
|
||
원본 JSON·회사 프리셋·서버 데이터는 변경하지 않는다.
|
||
그룹 클릭의 접기·펼치기와 직원 클릭의 정보 팝업은 유지하며 실제 드래그 뒤의 포인터
|
||
click은 억제한다. 자기 자신·자손을 부모로 지정하는 이동, 회사 Root 이동,
|
||
조직장 참조를 손상시키는 직원 이동은 거절하며 이유를 안내한다.
|
||
|
||
직원 카드 또는 그룹 타이틀에 초점을 둔 뒤 `Alt+M`으로 이동을 시작할 수 있다.
|
||
방향키로 대상을 선택하고 `Enter`로 확인하거나 `ESC`로 취소한다. 팝업을 꺼도 직원
|
||
카드는 이동 조작을 위한 초점을 제공한다. Fixed에는 소속 변경을 추가하지 않는다.
|
||
|
||
Core와 React의 `onMove(result: OrgChartMoveResult)`는 이동 성공·실패를 알린다.
|
||
`result.moved`로 성공을 구분하며, React는 성공한 이동 후 열린 HM 직원 Dialog를 닫는다.
|
||
React callback 변경은 최신 committed callback만 갱신하고 Core를 재생성하거나 reload하지 않는다.
|
||
|
||
소비 화면에서 회사 선택과 소속 변경을 함께 쓸 때는 모든 회사의 원본 예시를 하나의 세션
|
||
source로 유지하고 회사 선택을 `selectedCompanyIds`로 처리한다. 회사 숨김·다시 표시·빈
|
||
선택은 성공한 소속 변경을 보존한다. 새 예시가 필요하면 새 source를 만들며 파일을 다시
|
||
작성하거나 React key로 강제 remount하지 않는다. 직원 합계 등 파생 표시는 성공한 `onMove`의
|
||
`result.data`를 별도 read model로 읽고 source identity는 유지한다. 미리보기 전용 Expanded
|
||
Story는 회사 선택·Drag & Drop을 노출하지 않으므로 이 세션 흐름을 시연하지 않는다.
|