Files
pipeline/.cursor/skills/component-registry/reference.md
T
2026-03-12 18:47:42 +09:00

3.0 KiB

TableListComponent 상세 참조

주요 상태 (State)

// 데이터
const [tableData, setTableData] = useState<any[]>([]);
const [filteredData, setFilteredData] = useState<any[]>([]);
const [loading, setLoading] = useState(false);

// 편집
const [editingCell, setEditingCell] = useState<{
  rowIndex: number; colIndex: number; columnName: string; originalValue: any;
} | null>(null);
const [pendingChanges, setPendingChanges] = useState<Map<string, Map<string, any>>>(new Map());
const [validationErrors, setValidationErrors] = useState<Map<string, Map<string, string>>>(new Map());

// 필터
const [headerFilters, setHeaderFilters] = useState<Map<string, Set<string>>>(new Map());
const [filterGroups, setFilterGroups] = useState<FilterGroup[]>([]);
const [globalSearchText, setGlobalSearchText] = useState("");

// 컬럼
const [columnWidths, setColumnWidths] = useState<Record<string, number>>({});
const [columnOrder, setColumnOrder] = useState<string[]>([]);
const [columnVisibility, setColumnVisibility] = useState<Record<string, boolean>>({});

// 선택/정렬/페이지네이션
const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set());
const [sortBy, setSortBy] = useState<string>("");
const [sortOrder, setSortOrder] = useState<"asc" | "desc">("asc");
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(20);

타입 정의

type ValidationRule = {
  required?: boolean;
  min?: number; max?: number;
  minLength?: number; maxLength?: number;
  pattern?: RegExp;
  customMessage?: string;
  validate?: (value: any, row: any) => string | null;
};

interface FilterCondition {
  id: string; column: string;
  operator: "equals" | "notEquals" | "contains" | "notContains" |
            "startsWith" | "endsWith" | "greaterThan" | "lessThan" |
            "greaterOrEqual" | "lessOrEqual" | "isEmpty" | "isNotEmpty";
  value: string;
}

interface FilterGroup { id: string; logic: "AND" | "OR"; conditions: FilterCondition[]; }

interface TableState {
  columnWidths: Record<string, number>;
  columnOrder: string[];
  sortBy: string; sortOrder: "asc" | "desc";
  frozenColumns: string[];
  columnVisibility: Record<string, boolean>;
}

캐싱 전략

const tableColumnCache = new Map<string, { columns: any[]; timestamp: number }>();
const TABLE_CACHE_TTL = 5 * 60 * 1000; // 5분

키보드 네비게이션

동작
Arrow Keys 셀 이동
Tab/Shift+Tab 다음/이전 셀
F2 편집 모드
Enter 저장 후 아래로
Escape 편집 취소
Ctrl+C 복사
Delete 셀 값 삭제

필수 Import

import React, { useState, useEffect, useMemo, useCallback, useRef } from "react";
import { TableListConfig, ColumnConfig } from "./types";
import { tableTypeApi } from "@/lib/api/screen";
import { entityJoinApi } from "@/lib/api/entityJoin";
import { codeCache } from "@/lib/caching/codeCache";
import * as XLSX from "xlsx";
import { toast } from "sonner";