Files
invyone/frontend/types/component-events.ts
T
DDD1542 2f398ae0b3 chore: 제어모드 IDE 작업 + v2/legacy 레지스트리 컴포넌트 폐기
- 제어모드 IDE: ControlCardPanel, control/ide/* (Canvas/LeftRail/RightRail/PanZoomStage/V3RuleNode 등), schemas, lib/api/control
- 레지스트리 정리: aggregation-widget, status-count, section-card/paper, table-list(legacy/v2), tabs-widget 폐기 → table/_shared/ 로 통합
- InvLegacyButtonConfigPanel cp 마이그레이션
- canonical data view cleanup 후속 노트
2026-05-19 21:31:03 +09:00

231 lines
6.2 KiB
TypeScript

/**
* V2 컴포넌트 간 통신 이벤트 타입 정의
*
* 모든 V2 컴포넌트는 이 파일에 정의된 이벤트 타입을 사용해야 합니다.
* 이벤트 발행/구독 시 타입 안전성을 보장합니다.
*/
// ============================================================
// 이벤트 상세 데이터 타입 (event.detail)
// ============================================================
/**
* 테이블 리스트 데이터 변경 이벤트
* 발행: v2-table-list
* 구독: stats, v2-repeat-container
*/
export interface TableListDataChangeDetail {
component_id: string;
table_name: string;
data: any[];
selected_rows: string[] | number[];
}
/**
* 리피터 데이터 변경 이벤트
* 발행: v2-unified-repeater
* 구독: stats, v2-repeat-container
*/
export interface RepeaterDataChangeDetail {
component_id: string;
table_name: string;
data: any[];
selected_data?: any[];
}
/**
* 폼 저장 전 이벤트
* 발행: buttonActions, UnifiedFormContext
* 구독: v2-unified-repeater, simple-repeater-table, modal-repeater-table 등
*/
export interface BeforeFormSaveDetail {
form_data: Record<string, any>;
skip_default_save?: boolean;
}
/**
* 폼 저장 후 이벤트
* 발행: UnifiedFormContext
* 구독: 저장 결과 처리 컴포넌트들
*/
export interface AfterFormSaveDetail {
success: boolean;
data?: any;
error?: string;
}
/**
* 리피터 저장 이벤트 (마스터-디테일 FK 연결용)
* 발행: InteractiveScreenViewerDynamic
* 구독: v2-unified-repeater
*/
export interface RepeaterSaveDetail {
parent_id?: string | number;
master_record_id: string | number;
main_form_data: Record<string, any>;
table_name: string;
}
/**
* 테이블 새로고침 이벤트
* 발행: v2-button-primary, buttonActions
* 구독: v2-table-list, v2-split-panel-layout
*/
export interface RefreshTableDetail {
table_name?: string;
component_id?: string;
}
/**
* 컴포넌트 간 데이터 전달 이벤트
* 발행: buttonActions
* 구독: v2-unified-repeater
*/
export interface ComponentDataTransferDetail {
source_component_id: string;
target_component_id: string;
data: any[];
mode: "append" | "replace" | "merge";
mapping_rules?: Array<{
source_field: string;
target_field: string;
default_value?: any;
}>;
}
/**
* 분할 패널 간 데이터 전달 이벤트
* 발행: buttonActions
* 구독: v2-unified-repeater, repeater-field-group
*/
export interface SplitPanelDataTransferDetail {
source_position: "left" | "right";
target_position: "left" | "right";
data: any[];
mode: "append" | "replace" | "merge";
mapping_rules?: Array<{
source_field: string;
target_field: string;
default_value?: any;
}>;
}
/**
* 연관 데이터 버튼 선택 이벤트
* 발행: related-data-buttons
* 구독: v2-table-list
*/
export interface RelatedButtonSelectDetail {
target_table: string;
filter_column: string;
filter_value: any;
selected_data?: any;
}
/**
* 모달 제어 이벤트
*/
export interface EditModalDetail {
screen_id?: number;
record_id?: string | number;
data?: any;
}
// ============================================================
// 이벤트 이름 상수
// ============================================================
export const V2_EVENTS = {
// 데이터 변경 이벤트
TABLE_LIST_DATA_CHANGE: "tableListDataChange",
REPEATER_DATA_CHANGE: "repeaterDataChange",
// 폼 저장 이벤트
BEFORE_FORM_SAVE: "beforeFormSave",
AFTER_FORM_SAVE: "afterFormSave",
REPEATER_SAVE: "repeaterSave",
// UI 갱신 이벤트
REFRESH_TABLE: "refreshTable",
// 데이터 전달 이벤트
COMPONENT_DATA_TRANSFER: "componentDataTransfer",
SPLIT_PANEL_DATA_TRANSFER: "splitPanelDataTransfer",
// 모달 제어 이벤트
OPEN_EDIT_MODAL: "openEditModal",
CLOSE_EDIT_MODAL: "closeEditModal",
SAVE_SUCCESS_IN_MODAL: "saveSuccessInModal",
// 연관 데이터 버튼 이벤트
RELATED_BUTTON_SELECT: "related-button-select",
RELATED_BUTTON_REGISTER: "related-button-register",
RELATED_BUTTON_UNREGISTER: "related-button-unregister",
} as const;
// ============================================================
// Window EventMap 확장 (타입 안전한 이벤트 리스너)
// ============================================================
declare global {
interface WindowEventMap {
// 데이터 변경 이벤트
[V2_EVENTS.TABLE_LIST_DATA_CHANGE]: CustomEvent<TableListDataChangeDetail>;
[V2_EVENTS.REPEATER_DATA_CHANGE]: CustomEvent<RepeaterDataChangeDetail>;
// 폼 저장 이벤트
[V2_EVENTS.BEFORE_FORM_SAVE]: CustomEvent<BeforeFormSaveDetail>;
[V2_EVENTS.AFTER_FORM_SAVE]: CustomEvent<AfterFormSaveDetail>;
[V2_EVENTS.REPEATER_SAVE]: CustomEvent<RepeaterSaveDetail>;
// UI 갱신 이벤트
[V2_EVENTS.REFRESH_TABLE]: CustomEvent<RefreshTableDetail>;
// 데이터 전달 이벤트
[V2_EVENTS.COMPONENT_DATA_TRANSFER]: CustomEvent<ComponentDataTransferDetail>;
[V2_EVENTS.SPLIT_PANEL_DATA_TRANSFER]: CustomEvent<SplitPanelDataTransferDetail>;
// 연관 데이터 버튼 이벤트
[V2_EVENTS.RELATED_BUTTON_SELECT]: CustomEvent<RelatedButtonSelectDetail>;
}
}
// ============================================================
// 유틸리티 함수
// ============================================================
/**
* 타입 안전한 이벤트 발행 함수
*/
export function dispatchV2Event<K extends keyof WindowEventMap>(
eventName: K,
detail: WindowEventMap[K] extends CustomEvent<infer D> ? D : never
): void {
if (typeof window !== "undefined") {
window.dispatchEvent(new CustomEvent(eventName, { detail }));
}
}
/**
* 타입 안전한 이벤트 구독 함수
*/
export function subscribeV2Event<K extends keyof WindowEventMap>(
eventName: K,
handler: (event: WindowEventMap[K]) => void
): () => void {
if (typeof window === "undefined") {
return () => {};
}
window.addEventListener(eventName, handler as EventListener);
return () => {
window.removeEventListener(eventName, handler as EventListener);
};
}
// ============================================================
// 내보내기
// ============================================================
export type V2EventName = typeof V2_EVENTS[keyof typeof V2_EVENTS];