242 lines
6.6 KiB
TypeScript
242 lines
6.6 KiB
TypeScript
|
|
/**
|
||
|
|
* V2 컴포넌트 간 통신 이벤트 타입 정의
|
||
|
|
*
|
||
|
|
* 모든 V2 컴포넌트는 이 파일에 정의된 이벤트 타입을 사용해야 합니다.
|
||
|
|
* 이벤트 발행/구독 시 타입 안전성을 보장합니다.
|
||
|
|
*/
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// 이벤트 상세 데이터 타입 (event.detail)
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 테이블 리스트 데이터 변경 이벤트
|
||
|
|
* 발행: v2-table-list
|
||
|
|
* 구독: v2-aggregation-widget, v2-repeat-container
|
||
|
|
*/
|
||
|
|
export interface TableListDataChangeDetail {
|
||
|
|
componentId: string;
|
||
|
|
tableName: string;
|
||
|
|
data: any[];
|
||
|
|
selectedRows: string[] | number[];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 리피터 데이터 변경 이벤트
|
||
|
|
* 발행: v2-unified-repeater
|
||
|
|
* 구독: v2-aggregation-widget, v2-repeat-container
|
||
|
|
*/
|
||
|
|
export interface RepeaterDataChangeDetail {
|
||
|
|
componentId: string;
|
||
|
|
tableName: string;
|
||
|
|
data: any[];
|
||
|
|
selectedData?: any[];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 폼 저장 전 이벤트
|
||
|
|
* 발행: buttonActions, UnifiedFormContext
|
||
|
|
* 구독: v2-unified-repeater, simple-repeater-table, modal-repeater-table 등
|
||
|
|
*/
|
||
|
|
export interface BeforeFormSaveDetail {
|
||
|
|
formData: Record<string, any>;
|
||
|
|
skipDefaultSave?: boolean;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 폼 저장 후 이벤트
|
||
|
|
* 발행: UnifiedFormContext
|
||
|
|
* 구독: 저장 결과 처리 컴포넌트들
|
||
|
|
*/
|
||
|
|
export interface AfterFormSaveDetail {
|
||
|
|
success: boolean;
|
||
|
|
data?: any;
|
||
|
|
error?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 리피터 저장 이벤트 (마스터-디테일 FK 연결용)
|
||
|
|
* 발행: InteractiveScreenViewerDynamic
|
||
|
|
* 구독: v2-unified-repeater
|
||
|
|
*/
|
||
|
|
export interface RepeaterSaveDetail {
|
||
|
|
parentId?: string | number;
|
||
|
|
masterRecordId: string | number;
|
||
|
|
mainFormData: Record<string, any>;
|
||
|
|
tableName: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 테이블 새로고침 이벤트
|
||
|
|
* 발행: v2-button-primary, buttonActions
|
||
|
|
* 구독: v2-table-list, v2-split-panel-layout
|
||
|
|
*/
|
||
|
|
export interface RefreshTableDetail {
|
||
|
|
tableName?: string;
|
||
|
|
componentId?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카드 디스플레이 새로고침 이벤트
|
||
|
|
* 발행: buttonActions, InteractiveScreenViewerDynamic
|
||
|
|
* 구독: v2-card-display
|
||
|
|
*/
|
||
|
|
export interface RefreshCardDisplayDetail {
|
||
|
|
componentId?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 컴포넌트 간 데이터 전달 이벤트
|
||
|
|
* 발행: buttonActions
|
||
|
|
* 구독: v2-unified-repeater
|
||
|
|
*/
|
||
|
|
export interface ComponentDataTransferDetail {
|
||
|
|
sourceComponentId: string;
|
||
|
|
targetComponentId: string;
|
||
|
|
data: any[];
|
||
|
|
mode: "append" | "replace" | "merge";
|
||
|
|
mappingRules?: Array<{
|
||
|
|
sourceField: string;
|
||
|
|
targetField: string;
|
||
|
|
defaultValue?: any;
|
||
|
|
}>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 분할 패널 간 데이터 전달 이벤트
|
||
|
|
* 발행: buttonActions
|
||
|
|
* 구독: v2-unified-repeater, repeater-field-group
|
||
|
|
*/
|
||
|
|
export interface SplitPanelDataTransferDetail {
|
||
|
|
sourcePosition: "left" | "right";
|
||
|
|
targetPosition: "left" | "right";
|
||
|
|
data: any[];
|
||
|
|
mode: "append" | "replace" | "merge";
|
||
|
|
mappingRules?: Array<{
|
||
|
|
sourceField: string;
|
||
|
|
targetField: string;
|
||
|
|
defaultValue?: any;
|
||
|
|
}>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 연관 데이터 버튼 선택 이벤트
|
||
|
|
* 발행: related-data-buttons
|
||
|
|
* 구독: v2-table-list
|
||
|
|
*/
|
||
|
|
export interface RelatedButtonSelectDetail {
|
||
|
|
targetTable: string;
|
||
|
|
filterColumn: string;
|
||
|
|
filterValue: any;
|
||
|
|
selectedData?: any;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 모달 제어 이벤트
|
||
|
|
*/
|
||
|
|
export interface EditModalDetail {
|
||
|
|
screenId?: number;
|
||
|
|
recordId?: 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",
|
||
|
|
REFRESH_CARD_DISPLAY: "refreshCardDisplay",
|
||
|
|
|
||
|
|
// 데이터 전달 이벤트
|
||
|
|
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.REFRESH_CARD_DISPLAY]: CustomEvent<RefreshCardDisplayDetail>;
|
||
|
|
|
||
|
|
// 데이터 전달 이벤트
|
||
|
|
[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];
|