feat(org-chart): implement expandable layout and multi-company navigation
Integrate P5-1B through P5-4 shared Core layout, collapse, zoom/pan/fit, company roots and keyboard accessibility. Include React/HTML examples, virtual 20/100/300 employee fixtures, focused checks and the additive data contract.
This commit is contained in:
1 parent
a92913d6bc
commit
064517ec46
30 files changed
+7532
-183
No files matched your search
@@ -13,6 +13,8 @@ export interface EmployeeCardOptions {
|
||||
cardAsset?: DepartmentCardAsset | RepresentativeCardAsset;
|
||||
/** Full Composition presentation only; the employee dataset is untouched. */
|
||||
workdeskPresentation?: boolean;
|
||||
/** Auto content presentation, independent of Fixed SVG geometry. */
|
||||
expandedPresentation?: boolean;
|
||||
/** Compact read-only status groups already convey this label in their header. */
|
||||
hideStatusLabel?: boolean;
|
||||
}
|
||||
@@ -31,15 +33,16 @@ export function createEmployeeCard(
|
||||
const leader = options.kind !== 'employee';
|
||||
const representative = options.kind === 'topLeader' || options.cardAsset?.size === 'representative';
|
||||
const compactStatus = Boolean(options.workdeskPresentation && options.hideStatusLabel && !options.cardAsset);
|
||||
const styledCard = Boolean(options.cardAsset) || compactStatus;
|
||||
const presentationName = options.workdeskPresentation || representative;
|
||||
const styledCard = Boolean(options.cardAsset) || compactStatus || options.expandedPresentation;
|
||||
const presentationName = options.workdeskPresentation || (representative && !options.expandedPresentation);
|
||||
const displayName = presentationName ? '홍길동' : employee.name;
|
||||
const displayedName = presentationName ? '홍 길 동' : displayName;
|
||||
const displayedName = presentationName ? '홍 길 동' : options.expandedPresentation && /^[가-힣]{3}$/u.test(displayName) ? [...displayName].join(' ') : displayName;
|
||||
const card = document.createElement('div');
|
||||
card.className = `hm-orgchart-employee${leader ? ' hm-orgchart-leader' : ''}`;
|
||||
card.dataset.employeeId = employee.id;
|
||||
card.dataset.cardKind = options.kind;
|
||||
card.dataset.workStatus = employee.workStatus;
|
||||
if (options.expandedPresentation) card.dataset.cardPresentation = 'expanded';
|
||||
if (options.workdeskPresentation) card.dataset.workdeskPresentation = 'true';
|
||||
if (compactStatus) card.dataset.cardLayout = 'compact';
|
||||
if (options.cardAsset) {
|
||||
@@ -81,14 +84,15 @@ export function createEmployeeCard(
|
||||
|
||||
const details = document.createElement('div');
|
||||
details.className = 'hm-orgchart-employee-details';
|
||||
const displayedPosition = representative ? '대표이사' : employee.position.replace(/\s+/gu, '');
|
||||
const displayedPosition = representative && !options.expandedPresentation ? '대표이사' : employee.position.replace(/\s+/gu, '');
|
||||
const position = text(document, 'span', 'hm-orgchart-person-role', displayedPosition);
|
||||
const name = text(document, 'strong', 'hm-orgchart-person-name', displayedName);
|
||||
if (presentationName) {
|
||||
position.setAttribute('aria-label', representative ? displayedPosition : employee.position);
|
||||
name.setAttribute('aria-label', displayName);
|
||||
}
|
||||
const inlineRoleBadge = styledCard && !representative;
|
||||
if (options.expandedPresentation) position.setAttribute('aria-label', employee.position);
|
||||
const inlineRoleBadge = styledCard && !representative && !options.expandedPresentation;
|
||||
const positionRow = inlineRoleBadge ? document.createElement('div') : null;
|
||||
if (positionRow) {
|
||||
positionRow.className = 'hm-orgchart-position-row';
|
||||
@@ -104,7 +108,7 @@ export function createEmployeeCard(
|
||||
// Representative cards show only position/name in every consumer. Raw employee
|
||||
// roles remain available to dialogs/statistics; other cards keep their policy.
|
||||
const hideExecutiveBadge = options.workdeskPresentation && employee.jobTitle?.trim() === '경영진';
|
||||
if (!representative && !hideExecutiveBadge && (employee.jobTitle || (leader && !options.cardAsset))) {
|
||||
if (!representative && !options.expandedPresentation && !hideExecutiveBadge && (employee.jobTitle || (leader && !options.cardAsset))) {
|
||||
const rawBadge = employee.jobTitle || '조직장';
|
||||
const badge = text(document, 'span', 'hm-orgchart-job-title', options.workdeskPresentation ? rawBadge.replace(/\s+/gu, '') : rawBadge);
|
||||
if (options.workdeskPresentation) badge.setAttribute('aria-label', employee.jobTitle || '조직장');
|
||||
|
||||
Reference in new issue
Block a user