@topgrid/grid-pro-header 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # @topgrid/grid-pro-header
2
+
3
+ Pro: Multi-row Header (Column Groups)
4
+
5
+ Provides multi-row header (column group) support for TOMIS Grid — merge columns under shared group headers, with full TanStack Table column group API integration.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pnpm add @topgrid/grid-pro-header
11
+ # or
12
+ npm install @topgrid/grid-pro-header
13
+ ```
14
+
15
+ ## License Activation
16
+
17
+ > **This is a Pro package requiring a valid license key.**
18
+
19
+ ```tsx
20
+ import { setLicenseKey } from '@topgrid/grid-license';
21
+
22
+ // Call once at your app entry point (e.g., main.tsx)
23
+ setLicenseKey('YOUR-LICENSE-KEY');
24
+ ```
25
+
26
+ Without a valid license, the component will render a watermark.
27
+ Contact [sales@topvel.com](mailto:sales@topvel.com) to obtain a license key.
28
+
29
+ ## Peer Dependencies
30
+
31
+ | Package | Version |
32
+ |---------|---------|
33
+ | `@tanstack/react-table` | `^8.0.0` |
34
+ | `react` | `^18.0.0 \|\| ^19.0.0` |
35
+ | `react-dom` | `^18.0.0 \|\| ^19.0.0` |
36
+
37
+ ## Usage
38
+
39
+ ```tsx
40
+ import { setLicenseKey } from '@topgrid/grid-license';
41
+ import { MultiRowHeader, createColumnGroup } from '@topgrid/grid-pro-header';
42
+
43
+ setLicenseKey('YOUR-LICENSE-KEY');
44
+
45
+ // Define column groups
46
+ const columnGroups = createColumnGroup([
47
+ {
48
+ header: 'Personal Info',
49
+ columns: [
50
+ { accessorKey: 'firstName', header: 'First Name' },
51
+ { accessorKey: 'lastName', header: 'Last Name' },
52
+ ],
53
+ },
54
+ {
55
+ header: 'Contact',
56
+ columns: [
57
+ { accessorKey: 'email', header: 'Email' },
58
+ { accessorKey: 'phone', header: 'Phone' },
59
+ ],
60
+ },
61
+ ]);
62
+
63
+ export function GroupedGrid({ data }) {
64
+ return (
65
+ <MultiRowHeader columns={columnGroups} data={data} />
66
+ );
67
+ }
68
+ ```
69
+
70
+ ## Main API
71
+
72
+ | Export | Description |
73
+ |--------|-------------|
74
+ | `MultiRowHeader` | Grid component with multi-row grouped header |
75
+ | `createColumnGroup` | Helper to define column group configurations |
76
+ | `GroupedHeaderGrid` | Legacy alias for `MultiRowHeader` (deprecated) |
77
+ | `ColumnGroupConfig` | Column group configuration type |
78
+ | `MultiRowHeaderProps` | Props type for `<MultiRowHeader>` |
79
+
80
+ ## License
81
+
82
+ SEE LICENSE IN [EULA.md](./EULA.md)
83
+
84
+ License terms subject to change. Contact [sales@topvel.com](mailto:sales@topvel.com) for current EULA.
85
+
86
+ ---
87
+
88
+ [Documentation](https://grid.tomis.dev) | [Pricing](https://topvel.com/grid/pricing)
package/dist/index.cjs ADDED
@@ -0,0 +1,229 @@
1
+ 'use strict';
2
+
3
+ var gridLicense = require('@topgrid/grid-license');
4
+ var react = require('react');
5
+ var reactTable = require('@tanstack/react-table');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ // src/index.ts
9
+
10
+ // src/createColumnGroup.ts
11
+ function createColumnGroup(config) {
12
+ return {
13
+ header: config.header,
14
+ columns: config.columns
15
+ };
16
+ }
17
+ function getHeaderLeftOffset(header) {
18
+ const direct = header.column.getStart("left");
19
+ if (direct !== void 0) return direct;
20
+ const firstLeaf = header.subHeaders[0]?.column;
21
+ return firstLeaf?.getStart("left") ?? 0;
22
+ }
23
+ function MultiRowHeader({
24
+ table,
25
+ enableStickyHeader,
26
+ frozenColumns,
27
+ enableGroupToggle
28
+ }) {
29
+ const _lic = gridLicense.useLicenseStatus();
30
+ const headerGroups = table.getHeaderGroups();
31
+ const visibleLeafCount = table.getVisibleLeafColumns().length;
32
+ return /* @__PURE__ */ jsxRuntime.jsxs("thead", { className: "bg-gray-50", children: [
33
+ _lic.watermarkRequired && visibleLeafCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
34
+ "tr",
35
+ {
36
+ ...enableStickyHeader === true ? { className: "sticky top-0 z-20" } : {},
37
+ children: /* @__PURE__ */ jsxRuntime.jsx(
38
+ "th",
39
+ {
40
+ colSpan: visibleLeafCount,
41
+ className: "relative bg-yellow-50 px-4 py-1 text-center text-xs text-gray-500",
42
+ children: /* @__PURE__ */ jsxRuntime.jsx(gridLicense.Watermark, { required: true })
43
+ }
44
+ )
45
+ }
46
+ ) : null,
47
+ headerGroups.map((headerGroup, rowIndex) => {
48
+ const trProps = {
49
+ ...enableStickyHeader === true && rowIndex === 0 && {
50
+ className: "sticky top-0 z-10"
51
+ },
52
+ ...enableStickyHeader === true && rowIndex > 0 && {
53
+ className: "sticky z-10",
54
+ style: {
55
+ top: `calc(var(--grid-header-row-height, 40px) * ${rowIndex})`
56
+ }
57
+ }
58
+ };
59
+ return /* @__PURE__ */ jsxRuntime.jsx("tr", { ...trProps, children: headerGroup.headers.map((header) => {
60
+ const isFrozen = (frozenColumns ?? 0) > 0 && header.column.getIsPinned() === "left";
61
+ const frozenZClass = isFrozen && enableStickyHeader === true ? "sticky z-30" : isFrozen ? "sticky z-20" : "";
62
+ const thStyle = isFrozen ? { left: `${getHeaderLeftOffset(header)}px` } : {};
63
+ const isLeaf = header.subHeaders.length === 0;
64
+ const allLeavesHidden = !isLeaf && header.column.getLeafColumns().every((c) => !c.getIsVisible());
65
+ const groupClickHandler = enableGroupToggle === true && !isLeaf ? () => {
66
+ const leafCols = header.column.getLeafColumns();
67
+ leafCols.forEach((c) => c.toggleVisibility(allLeavesHidden));
68
+ } : void 0;
69
+ const effectiveColSpan = enableGroupToggle === true && allLeavesHidden ? 1 : header.colSpan;
70
+ if (header.isPlaceholder) {
71
+ return /* @__PURE__ */ jsxRuntime.jsx(
72
+ "th",
73
+ {
74
+ colSpan: effectiveColSpan,
75
+ className: `px-4 py-3 border border-gray-200${frozenZClass ? ` ${frozenZClass}` : ""}`,
76
+ ...isFrozen ? { style: thStyle } : {}
77
+ },
78
+ header.id
79
+ );
80
+ }
81
+ return /* @__PURE__ */ jsxRuntime.jsx(
82
+ "th",
83
+ {
84
+ colSpan: effectiveColSpan,
85
+ className: `px-4 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider border border-gray-200 whitespace-nowrap select-none${header.column.getCanSort() && isLeaf ? " cursor-pointer hover:bg-gray-100" : ""}${enableGroupToggle === true && !isLeaf ? " cursor-pointer hover:bg-gray-100" : ""}${frozenZClass ? ` ${frozenZClass}` : ""}`,
86
+ ...isFrozen ? { style: thStyle } : {},
87
+ onClick: isLeaf ? header.column.getToggleSortingHandler() : groupClickHandler,
88
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-1", children: [
89
+ reactTable.flexRender(header.column.columnDef.header, header.getContext()),
90
+ header.column.getCanSort() && isLeaf && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: { asc: "\u25B2", desc: "\u25BC" }[header.column.getIsSorted()] ?? "\u21C5" }),
91
+ enableGroupToggle === true && !isLeaf && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 ml-1", children: allLeavesHidden ? "\u25B6" : "\u25BC" })
92
+ ] })
93
+ },
94
+ header.id
95
+ );
96
+ }) }, headerGroup.id);
97
+ })
98
+ ] });
99
+ }
100
+ function GroupedHeaderGrid({
101
+ data,
102
+ columns,
103
+ pagination,
104
+ onRowClick,
105
+ loading = false,
106
+ emptyText = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
107
+ className = "",
108
+ enableGroupToggle
109
+ }) {
110
+ const [sorting, setSorting] = react.useState([]);
111
+ const [pageIndex, setPageIndex] = react.useState(0);
112
+ const [pageSize] = react.useState(pagination?.pageSize ?? 20);
113
+ const table = reactTable.useReactTable({
114
+ data,
115
+ columns,
116
+ state: {
117
+ sorting,
118
+ pagination: { pageIndex, pageSize }
119
+ },
120
+ onSortingChange: setSorting,
121
+ onPaginationChange: (updater) => {
122
+ const next = typeof updater === "function" ? updater({ pageIndex, pageSize }) : updater;
123
+ setPageIndex(next.pageIndex);
124
+ },
125
+ getCoreRowModel: reactTable.getCoreRowModel(),
126
+ getSortedRowModel: reactTable.getSortedRowModel(),
127
+ // C-29: exactOptionalPropertyTypes — conditional spread avoids assigning undefined
128
+ // to a non-optional property when pagination is absent.
129
+ ...pagination !== void 0 ? { getPaginationRowModel: reactTable.getPaginationRowModel() } : {},
130
+ manualPagination: false
131
+ });
132
+ const pageCount = table.getPageCount();
133
+ if (loading) {
134
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex flex-col ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-40 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-blue-500" }) }) });
135
+ }
136
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col ${className}`, children: [
137
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-lg border border-gray-200", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full text-sm border-collapse", children: [
138
+ /* @__PURE__ */ jsxRuntime.jsx(
139
+ MultiRowHeader,
140
+ {
141
+ table,
142
+ ...enableGroupToggle === true ? { enableGroupToggle: true } : {}
143
+ }
144
+ ),
145
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white divide-y divide-gray-100", children: table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
146
+ "td",
147
+ {
148
+ colSpan: table.getAllLeafColumns().length,
149
+ className: "px-4 py-10 text-center text-gray-400",
150
+ children: emptyText
151
+ }
152
+ ) }) : table.getRowModel().rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(
153
+ "tr",
154
+ {
155
+ className: `hover:bg-gray-50 ${onRowClick ? "cursor-pointer" : ""}`,
156
+ onClick: (e) => onRowClick?.(row.original, e),
157
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsxRuntime.jsx(
158
+ "td",
159
+ {
160
+ className: "px-4 py-3 whitespace-nowrap text-gray-700 border-r border-gray-100 last:border-r-0",
161
+ children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext())
162
+ },
163
+ cell.id
164
+ ))
165
+ },
166
+ row.id
167
+ )) })
168
+ ] }) }),
169
+ pagination !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-2 py-3 text-sm text-gray-600", children: [
170
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
171
+ "\uC804\uCCB4 ",
172
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: table.getFilteredRowModel().rows.length }),
173
+ "\uAC74"
174
+ ] }),
175
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
176
+ /* @__PURE__ */ jsxRuntime.jsx(
177
+ "button",
178
+ {
179
+ onClick: () => table.setPageIndex(0),
180
+ disabled: !table.getCanPreviousPage(),
181
+ className: "px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100",
182
+ children: "\xAB"
183
+ }
184
+ ),
185
+ /* @__PURE__ */ jsxRuntime.jsx(
186
+ "button",
187
+ {
188
+ onClick: () => table.previousPage(),
189
+ disabled: !table.getCanPreviousPage(),
190
+ className: "px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100",
191
+ children: "\u2039"
192
+ }
193
+ ),
194
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-3", children: [
195
+ pageIndex + 1,
196
+ " / ",
197
+ pageCount || 1
198
+ ] }),
199
+ /* @__PURE__ */ jsxRuntime.jsx(
200
+ "button",
201
+ {
202
+ onClick: () => table.nextPage(),
203
+ disabled: !table.getCanNextPage(),
204
+ className: "px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100",
205
+ children: "\u203A"
206
+ }
207
+ ),
208
+ /* @__PURE__ */ jsxRuntime.jsx(
209
+ "button",
210
+ {
211
+ onClick: () => table.setPageIndex(pageCount - 1),
212
+ disabled: !table.getCanNextPage(),
213
+ className: "px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100",
214
+ children: "\xBB"
215
+ }
216
+ )
217
+ ] })
218
+ ] })
219
+ ] });
220
+ }
221
+
222
+ // src/index.ts
223
+ gridLicense.checkLicense();
224
+
225
+ exports.GroupedHeaderGrid = GroupedHeaderGrid;
226
+ exports.MultiRowHeader = MultiRowHeader;
227
+ exports.createColumnGroup = createColumnGroup;
228
+ //# sourceMappingURL=index.cjs.map
229
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/createColumnGroup.ts","../src/MultiRowHeader.tsx","../src/legacy/GroupedHeaderGrid.tsx","../src/index.ts"],"names":["useLicenseStatus","jsxs","jsx","Watermark","flexRender","useState","useReactTable","getCoreRowModel","getSortedRowModel","getPaginationRowModel","checkLicense"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * createColumnGroup — thin wrapper to create a TanStack `GroupColumnDef<TData>`.\r\n *\r\n * Provides TypeScript generic type-safety for the standard TanStack column grouping pattern:\r\n * `{ header: string; columns: ColumnDef<TData>[] }`.\r\n *\r\n * @example\r\n * ```typescript\r\n * const infoGroup = createColumnGroup({\r\n * header: '기본 정보',\r\n * columns: [nameCol, deptCol],\r\n * });\r\n * ```\r\n *\r\n * @see AC-001 in G-001-spec.md — createColumnGroup signature\r\n * @see Section 5.1 in G-001-spec.md — API design\r\n */\r\n\r\nimport type { ColumnDef, GroupColumnDef } from '@tanstack/react-table';\r\n\r\n/**\r\n * Config object for `createColumnGroup`.\r\n *\r\n * @typeParam TData - The row data type of the table.\r\n */\r\nexport interface ColumnGroupConfig<TData> {\r\n /** The display label for the column group header. */\r\n header: string;\r\n /** Leaf (or nested group) column definitions belonging to this group. */\r\n columns: ColumnDef<TData>[];\r\n}\r\n\r\n/**\r\n * Creates a TanStack `GroupColumnDef<TData>` from a typed config object.\r\n *\r\n * This is a thin wrapper — no logic beyond type narrowing. The returned\r\n * object is identical to writing `{ header, columns }` inline, but provides\r\n * generic type-checking at the call site.\r\n *\r\n * @typeParam TData - The row data type of the table.\r\n * @param config - `ColumnGroupConfig<TData>` with `header` and `columns`.\r\n * @returns A `GroupColumnDef<TData>` suitable for passing to `useReactTable`.\r\n */\r\nexport function createColumnGroup<TData>(\r\n config: ColumnGroupConfig<TData>,\r\n): GroupColumnDef<TData> {\r\n return {\r\n header: config.header,\r\n columns: config.columns,\r\n };\r\n}\r\n","/**\r\n * MultiRowHeader — renders a multi-row `<thead>` section from TanStack\r\n * `table.getHeaderGroups()`.\r\n *\r\n * Extracts the header rendering logic from GroupedHeaderGrid.tsx (L75-117)\r\n * into a reusable Pro-package component. Uses only TanStack v8 standard APIs\r\n * (C-2): `getHeaderGroups`, `header.isPlaceholder`, `header.colSpan`,\r\n * `header.subHeaders`, `flexRender`.\r\n *\r\n * G-002 additions: `enableStickyHeader` prop for multi-row sticky (AC-001),\r\n * `frozenColumns` prop as on/off switch for column pinning left-offset (AC-002),\r\n * CSS variable `--grid-header-row-height` based top offset (AC-003).\r\n *\r\n * G-003 additions: `enableGroupToggle` prop for group header click to toggle\r\n * child column visibility (AC-001). Group cells get collapse icon ▼/▶ and\r\n * click handler; leaf cells retain sort handler (AC-002, D2 decision).\r\n *\r\n * Flat columns mixed with group columns are handled automatically by TanStack's\r\n * placeholder mechanism — do NOT add custom rowSpan calculation (spec §11.2).\r\n *\r\n * @see AC-001, AC-002, AC-003 in G-002-spec.md\r\n * @see Section 5.1/5.2 in G-002-spec.md — API design\r\n * @see Section 11.2/11.4 in G-002-spec.md — implementation guidelines\r\n * @see Section 6.1, 11.1 in G-003-spec.md — enableGroupToggle implementation\r\n */\r\n\r\nimport { type CSSProperties } from 'react';\r\nimport { flexRender, type Header, type Table } from '@tanstack/react-table';\r\nimport { useLicenseStatus, Watermark } from '@topgrid/grid-license';\r\n\r\n/**\r\n * Props for `MultiRowHeader`.\r\n *\r\n * @typeParam TData - The row data type of the table.\r\n */\r\nexport interface MultiRowHeaderProps<TData = unknown> {\r\n /**\r\n * The TanStack table instance. Provides `getHeaderGroups()` used for\r\n * multi-row header rendering.\r\n */\r\n table: Table<TData>;\r\n /**\r\n * When true, applies sticky positioning to each header row so the multi-row\r\n * header remains fixed at the viewport top during vertical scroll (AC-001).\r\n * Default: false (G-001 behaviour preserved — breaking: false).\r\n */\r\n enableStickyHeader?: boolean;\r\n /**\r\n * Number of columns pinned on the left that should receive `sticky left`\r\n * positioning. Acts as an on/off switch; the actual frozen column identities\r\n * are determined from TanStack's `columnPinning.left` state via\r\n * `column.getIsPinned() === 'left'` (AC-002, D2 decision).\r\n * 0 or omitted: frozen positioning inactive.\r\n */\r\n frozenColumns?: number;\r\n /**\r\n * When true, group header cells (non-leaf) become clickable toggles that\r\n * show/hide all child (leaf) columns at once (G-003, AC-001).\r\n * Clicking a group header that has all leaves hidden will show them all;\r\n * clicking one with any visible leaf will hide them all.\r\n * Leaf columns retain their sort click handler regardless.\r\n * Default: false (G-001/G-002 behaviour preserved — breaking: false).\r\n */\r\n enableGroupToggle?: boolean;\r\n}\r\n\r\n/**\r\n * Returns the left pixel offset for a frozen header cell (AC-002, EC-05).\r\n *\r\n * TanStack's `column.getStart('left')` returns the correct offset for leaf\r\n * columns. For group header cells it may return `undefined`; in that case the\r\n * first leaf child's offset is used as a fallback (spec §11.4 EC-05).\r\n *\r\n * @typeParam TData - Row data type (matches the parent table's TData).\r\n * @see G-002-spec.md Section 11.4\r\n */\r\nfunction getHeaderLeftOffset<TData>(header: Header<TData, unknown>): number {\r\n const direct = header.column.getStart('left');\r\n if (direct !== undefined) return direct;\r\n // EC-05 fallback: group header cell — use first leaf child's offset.\r\n const firstLeaf = header.subHeaders[0]?.column;\r\n return firstLeaf?.getStart('left') ?? 0;\r\n}\r\n\r\n/**\r\n * Renders a multi-row `<thead>` element from a TanStack table instance.\r\n *\r\n * Iterates `table.getHeaderGroups()` to produce one `<tr>` per header row.\r\n * Group header cells use `header.colSpan` (computed by TanStack automatically).\r\n * Placeholder cells (`header.isPlaceholder`) are rendered as empty `<th>` elements.\r\n * Sorting is enabled only on leaf columns (`!header.subHeaders.length`).\r\n *\r\n * @typeParam TData - The row data type of the table.\r\n * @param props - `MultiRowHeaderProps<TData>`.\r\n * @returns A `<thead>` JSX element with all header rows.\r\n */\r\nexport function MultiRowHeader<TData>({\r\n table,\r\n enableStickyHeader,\r\n frozenColumns,\r\n enableGroupToggle,\r\n}: MultiRowHeaderProps<TData>): JSX.Element {\r\n // ADR-MOD-GRID-REFACTOR-2026-05-17-001 — license watermark wiring (H-D pattern)\r\n // sub-spec §8 Step 4: extra <tr><th colSpan> watermark row inside <thead>.\r\n // §9.3 D-3 = (a): sticky top-0 when enableStickyHeader is true.\r\n const _lic = useLicenseStatus();\r\n const headerGroups = table.getHeaderGroups();\r\n const visibleLeafCount = table.getVisibleLeafColumns().length;\r\n\r\n return (\r\n <thead className=\"bg-gray-50\">\r\n {_lic.watermarkRequired && visibleLeafCount > 0 ? (\r\n <tr\r\n {...(enableStickyHeader === true\r\n ? { className: 'sticky top-0 z-20' }\r\n : {})}\r\n >\r\n <th\r\n colSpan={visibleLeafCount}\r\n className=\"relative bg-yellow-50 px-4 py-1 text-center text-xs text-gray-500\"\r\n >\r\n <Watermark required />\r\n </th>\r\n </tr>\r\n ) : null}\r\n {headerGroups.map((headerGroup, rowIndex) => {\r\n // AC-001: sticky row props — C-29 conditional spread pattern.\r\n // Row 0: sticky top-0 z-10 (Tailwind only, no inline style needed).\r\n // Row N≥1: sticky z-10 + inline style top: calc(var(--grid-header-row-height, 40px) * N).\r\n const trProps = {\r\n ...(enableStickyHeader === true && rowIndex === 0 && {\r\n className: 'sticky top-0 z-10',\r\n }),\r\n ...(enableStickyHeader === true && rowIndex > 0 && {\r\n className: 'sticky z-10',\r\n style: {\r\n top: `calc(var(--grid-header-row-height, 40px) * ${rowIndex})`,\r\n } as CSSProperties,\r\n }),\r\n };\r\n\r\n return (\r\n <tr key={headerGroup.id} {...trProps}>\r\n {headerGroup.headers.map((header) => {\r\n // AC-002: frozen column detection via TanStack native API (D2 decision).\r\n // frozenColumns > 0 acts as the feature on/off switch;\r\n // actual pinned identity comes from TanStack columnPinning state.\r\n const isFrozen =\r\n (frozenColumns ?? 0) > 0 &&\r\n header.column.getIsPinned() === 'left';\r\n\r\n // D4: z-index layers.\r\n // frozen + sticky intersection → z-30.\r\n // frozen only (sticky off) → z-20.\r\n // Neither → no extra z-class.\r\n const frozenZClass =\r\n isFrozen && enableStickyHeader === true\r\n ? 'sticky z-30'\r\n : isFrozen\r\n ? 'sticky z-20'\r\n : '';\r\n\r\n // AC-002: left offset in px (inline style — dynamic runtime value, C-5 exception).\r\n // EC-05 fallback: group cell getStart('left') may be undefined → subHeaders[0] fallback.\r\n const thStyle: CSSProperties = isFrozen\r\n ? { left: `${getHeaderLeftOffset(header as Header<unknown, unknown>)}px` }\r\n : {};\r\n\r\n // Leaf columns: sorting enabled. Group columns: group toggle (if enabled).\r\n const isLeaf = header.subHeaders.length === 0;\r\n\r\n // G-003 AC-001: pre-compute allLeavesHidden once per non-leaf header.\r\n // Used for (a) click handler, (b) effectiveColSpan, (c) collapse icon.\r\n const allLeavesHidden =\r\n !isLeaf &&\r\n header.column.getLeafColumns().every((c) => !c.getIsVisible());\r\n\r\n // G-003 AC-001: group click handler — toggle all leaf column visibility.\r\n // allLeavesHidden → show all (true); any visible leaf → hide all (false).\r\n const groupClickHandler =\r\n enableGroupToggle === true && !isLeaf\r\n ? () => {\r\n const leafCols = header.column.getLeafColumns();\r\n leafCols.forEach((c) => c.toggleVisibility(allLeavesHidden));\r\n }\r\n : undefined;\r\n\r\n // G-003: effectiveColSpan — collapsed group occupies 1 column (spec §6.1).\r\n const effectiveColSpan =\r\n enableGroupToggle === true && allLeavesHidden\r\n ? 1\r\n : header.colSpan;\r\n\r\n // isPlaceholder: filler cell for multi-row headers (TanStack placeholder mechanism).\r\n // Flat columns in the group row appear as placeholder cells — rendered empty.\r\n if (header.isPlaceholder) {\r\n return (\r\n <th\r\n key={header.id}\r\n colSpan={effectiveColSpan}\r\n className={`px-4 py-3 border border-gray-200${frozenZClass ? ` ${frozenZClass}` : ''}`}\r\n {...(isFrozen ? { style: thStyle } : {})}\r\n />\r\n );\r\n }\r\n\r\n return (\r\n <th\r\n key={header.id}\r\n colSpan={effectiveColSpan}\r\n className={`px-4 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider border border-gray-200 whitespace-nowrap select-none${\r\n header.column.getCanSort() && isLeaf\r\n ? ' cursor-pointer hover:bg-gray-100'\r\n : ''\r\n }${\r\n enableGroupToggle === true && !isLeaf\r\n ? ' cursor-pointer hover:bg-gray-100'\r\n : ''\r\n }${frozenZClass ? ` ${frozenZClass}` : ''}`}\r\n {...(isFrozen ? { style: thStyle } : {})}\r\n onClick={\r\n isLeaf ? header.column.getToggleSortingHandler() : groupClickHandler\r\n }\r\n >\r\n <div className=\"flex items-center justify-center gap-1\">\r\n {flexRender(header.column.columnDef.header, header.getContext())}\r\n {header.column.getCanSort() && isLeaf && (\r\n <span className=\"text-gray-400\">\r\n {({ asc: '▲', desc: '▼' } as Record<string, string>)[\r\n header.column.getIsSorted() as string\r\n ] ?? '⇅'}\r\n </span>\r\n )}\r\n {enableGroupToggle === true && !isLeaf && (\r\n <span className=\"text-gray-400 ml-1\">\r\n {allLeavesHidden ? '▶' : '▼'}\r\n </span>\r\n )}\r\n </div>\r\n </th>\r\n );\r\n })}\r\n </tr>\r\n );\r\n })}\r\n </thead>\r\n );\r\n}\r\n","/**\r\n * GroupedHeaderGrid — legacy alias component (G-003, C-6 deprecation alias).\r\n *\r\n * Wraps `useReactTable` + `MultiRowHeader` + tbody + pagination into a single\r\n * self-contained component, preserving the AS-IS GroupedHeaderGrid API surface\r\n * from tw-framework-front/src/components/tomis/Grid/GroupedHeaderGrid.tsx (L0).\r\n *\r\n * Behaviour and classNames are ported verbatim from L0 (C-17 visual preservation).\r\n * `verifyOrWarn` is intentionally absent here — it runs via index.ts side-effect.\r\n *\r\n * D3 decision: inline type aliases for GridPaginationOptions / GridRowSelectionOptions\r\n * to avoid reverse dependency on tw-framework-front.\r\n *\r\n * @see G-003-spec.md Section 6.2 — legacy/GroupedHeaderGrid structure\r\n * @see C-6 — 1 minor version deprecation alias (breaking: false)\r\n * @see C-17 — AS-IS L0 className is authoritative\r\n */\r\n\r\nimport { useState } from 'react';\r\nimport type { MouseEvent } from 'react';\r\nimport {\r\n useReactTable,\r\n getCoreRowModel,\r\n getSortedRowModel,\r\n getPaginationRowModel,\r\n flexRender,\r\n type SortingState,\r\n type ColumnDef,\r\n} from '@tanstack/react-table';\r\nimport type { GridPaginationOptions, GridRowSelectionOptions } from '@topgrid/grid-core';\r\nimport { MultiRowHeader } from '../MultiRowHeader';\r\n\r\n/**\r\n * Props for the legacy `GroupedHeaderGrid` wrapper component.\r\n *\r\n * @typeParam TData - The row data type.\r\n * @deprecated Migrate to composing `useReactTable` + `MultiRowHeader` directly.\r\n */\r\nexport interface GroupedHeaderGridProps<TData = unknown> {\r\n data: TData[];\r\n /**\r\n * Pass grouped column definitions using TanStack Table's native column grouping.\r\n * Use `{ header: 'Group', columns: [...leafColumns] }` structure for grouping.\r\n */\r\n columns: ColumnDef<TData>[];\r\n pagination?: GridPaginationOptions;\r\n rowSelection?: GridRowSelectionOptions<TData>;\r\n onRowClick?: (row: TData, event: MouseEvent<HTMLTableRowElement>) => void;\r\n loading?: boolean;\r\n emptyText?: string;\r\n className?: string;\r\n /** G-003 AC-001: enable group header click to toggle child column visibility. */\r\n enableGroupToggle?: boolean;\r\n}\r\n\r\n/**\r\n * Legacy self-contained grid component with grouped multi-row headers.\r\n *\r\n * Delegates header rendering to `MultiRowHeader` from `@topgrid/grid-pro-header`.\r\n * tbody and pagination are ported verbatim from AS-IS L0 (C-17).\r\n *\r\n * @typeParam TData - The row data type (must extend `object`).\r\n * @deprecated Prefer composing `useReactTable` + `MultiRowHeader` directly.\r\n */\r\nexport function GroupedHeaderGrid<TData extends object>({\r\n data,\r\n columns,\r\n pagination,\r\n onRowClick,\r\n loading = false,\r\n emptyText = '데이터가 없습니다.',\r\n className = '',\r\n enableGroupToggle,\r\n}: GroupedHeaderGridProps<TData>): JSX.Element {\r\n const [sorting, setSorting] = useState<SortingState>([]);\r\n const [pageIndex, setPageIndex] = useState(0);\r\n const [pageSize] = useState(pagination?.pageSize ?? 20);\r\n\r\n const table = useReactTable({\r\n data,\r\n columns,\r\n state: {\r\n sorting,\r\n pagination: { pageIndex, pageSize },\r\n },\r\n onSortingChange: setSorting,\r\n onPaginationChange: (updater) => {\r\n const next =\r\n typeof updater === 'function' ? updater({ pageIndex, pageSize }) : updater;\r\n setPageIndex(next.pageIndex);\r\n },\r\n getCoreRowModel: getCoreRowModel(),\r\n getSortedRowModel: getSortedRowModel(),\r\n // C-29: exactOptionalPropertyTypes — conditional spread avoids assigning undefined\r\n // to a non-optional property when pagination is absent.\r\n ...(pagination !== undefined\r\n ? { getPaginationRowModel: getPaginationRowModel() }\r\n : {}),\r\n manualPagination: false,\r\n });\r\n\r\n const pageCount = table.getPageCount();\r\n\r\n if (loading) {\r\n return (\r\n <div className={`flex flex-col ${className}`}>\r\n <div className=\"h-40 flex items-center justify-center\">\r\n <div className=\"animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-blue-500\" />\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={`flex flex-col ${className}`}>\r\n <div className=\"overflow-x-auto rounded-lg border border-gray-200\">\r\n <table className=\"min-w-full text-sm border-collapse\">\r\n <MultiRowHeader\r\n table={table}\r\n {...(enableGroupToggle === true ? { enableGroupToggle: true } : {})}\r\n />\r\n <tbody className=\"bg-white divide-y divide-gray-100\">\r\n {table.getRowModel().rows.length === 0 ? (\r\n <tr>\r\n <td\r\n colSpan={table.getAllLeafColumns().length}\r\n className=\"px-4 py-10 text-center text-gray-400\"\r\n >\r\n {emptyText}\r\n </td>\r\n </tr>\r\n ) : (\r\n table.getRowModel().rows.map((row) => (\r\n <tr\r\n key={row.id}\r\n className={`hover:bg-gray-50 ${onRowClick ? 'cursor-pointer' : ''}`}\r\n onClick={(e) => onRowClick?.(row.original, e)}\r\n >\r\n {row.getVisibleCells().map((cell) => (\r\n <td\r\n key={cell.id}\r\n className=\"px-4 py-3 whitespace-nowrap text-gray-700 border-r border-gray-100 last:border-r-0\"\r\n >\r\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\r\n </td>\r\n ))}\r\n </tr>\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n {pagination !== undefined && (\r\n <div className=\"flex items-center justify-between px-2 py-3 text-sm text-gray-600\">\r\n <span>\r\n 전체 <strong>{table.getFilteredRowModel().rows.length}</strong>건\r\n </span>\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => table.setPageIndex(0)}\r\n disabled={!table.getCanPreviousPage()}\r\n className=\"px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100\"\r\n >\r\n {'«'}\r\n </button>\r\n <button\r\n onClick={() => table.previousPage()}\r\n disabled={!table.getCanPreviousPage()}\r\n className=\"px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100\"\r\n >\r\n {'‹'}\r\n </button>\r\n <span className=\"px-3\">\r\n {pageIndex + 1} / {pageCount || 1}\r\n </span>\r\n <button\r\n onClick={() => table.nextPage()}\r\n disabled={!table.getCanNextPage()}\r\n className=\"px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100\"\r\n >\r\n {'›'}\r\n </button>\r\n <button\r\n onClick={() => table.setPageIndex(pageCount - 1)}\r\n disabled={!table.getCanNextPage()}\r\n className=\"px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100\"\r\n >\r\n {'»'}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { checkLicense } from '@topgrid/grid-license';\r\n\r\ncheckLicense();\r\n\r\n// createColumnGroup helper (AC-001)\r\nexport { createColumnGroup } from './createColumnGroup';\r\nexport type { ColumnGroupConfig } from './types';\r\n\r\n// MultiRowHeader component (AC-002, AC-003, AC-004)\r\nexport { MultiRowHeader } from './MultiRowHeader';\r\nexport type { MultiRowHeaderProps } from './types';\r\n\r\n// GroupedHeaderGrid legacy alias (G-003, C-6 deprecation alias)\r\nexport { GroupedHeaderGrid } from './legacy/GroupedHeaderGrid';\r\nexport type { GroupedHeaderGridProps } from './legacy/GroupedHeaderGrid';\r\n"]}
@@ -0,0 +1,173 @@
1
+ import { ColumnDef, GroupColumnDef, Table } from '@tanstack/react-table';
2
+ import { MouseEvent } from 'react';
3
+ import { GridPaginationOptions, GridRowSelectionOptions } from '@topgrid/grid-core';
4
+
5
+ /**
6
+ * createColumnGroup — thin wrapper to create a TanStack `GroupColumnDef<TData>`.
7
+ *
8
+ * Provides TypeScript generic type-safety for the standard TanStack column grouping pattern:
9
+ * `{ header: string; columns: ColumnDef<TData>[] }`.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const infoGroup = createColumnGroup({
14
+ * header: '기본 정보',
15
+ * columns: [nameCol, deptCol],
16
+ * });
17
+ * ```
18
+ *
19
+ * @see AC-001 in G-001-spec.md — createColumnGroup signature
20
+ * @see Section 5.1 in G-001-spec.md — API design
21
+ */
22
+
23
+ /**
24
+ * Config object for `createColumnGroup`.
25
+ *
26
+ * @typeParam TData - The row data type of the table.
27
+ */
28
+ interface ColumnGroupConfig<TData> {
29
+ /** The display label for the column group header. */
30
+ header: string;
31
+ /** Leaf (or nested group) column definitions belonging to this group. */
32
+ columns: ColumnDef<TData>[];
33
+ }
34
+ /**
35
+ * Creates a TanStack `GroupColumnDef<TData>` from a typed config object.
36
+ *
37
+ * This is a thin wrapper — no logic beyond type narrowing. The returned
38
+ * object is identical to writing `{ header, columns }` inline, but provides
39
+ * generic type-checking at the call site.
40
+ *
41
+ * @typeParam TData - The row data type of the table.
42
+ * @param config - `ColumnGroupConfig<TData>` with `header` and `columns`.
43
+ * @returns A `GroupColumnDef<TData>` suitable for passing to `useReactTable`.
44
+ */
45
+ declare function createColumnGroup<TData>(config: ColumnGroupConfig<TData>): GroupColumnDef<TData>;
46
+
47
+ /**
48
+ * MultiRowHeader — renders a multi-row `<thead>` section from TanStack
49
+ * `table.getHeaderGroups()`.
50
+ *
51
+ * Extracts the header rendering logic from GroupedHeaderGrid.tsx (L75-117)
52
+ * into a reusable Pro-package component. Uses only TanStack v8 standard APIs
53
+ * (C-2): `getHeaderGroups`, `header.isPlaceholder`, `header.colSpan`,
54
+ * `header.subHeaders`, `flexRender`.
55
+ *
56
+ * G-002 additions: `enableStickyHeader` prop for multi-row sticky (AC-001),
57
+ * `frozenColumns` prop as on/off switch for column pinning left-offset (AC-002),
58
+ * CSS variable `--grid-header-row-height` based top offset (AC-003).
59
+ *
60
+ * G-003 additions: `enableGroupToggle` prop for group header click to toggle
61
+ * child column visibility (AC-001). Group cells get collapse icon ▼/▶ and
62
+ * click handler; leaf cells retain sort handler (AC-002, D2 decision).
63
+ *
64
+ * Flat columns mixed with group columns are handled automatically by TanStack's
65
+ * placeholder mechanism — do NOT add custom rowSpan calculation (spec §11.2).
66
+ *
67
+ * @see AC-001, AC-002, AC-003 in G-002-spec.md
68
+ * @see Section 5.1/5.2 in G-002-spec.md — API design
69
+ * @see Section 11.2/11.4 in G-002-spec.md — implementation guidelines
70
+ * @see Section 6.1, 11.1 in G-003-spec.md — enableGroupToggle implementation
71
+ */
72
+
73
+ /**
74
+ * Props for `MultiRowHeader`.
75
+ *
76
+ * @typeParam TData - The row data type of the table.
77
+ */
78
+ interface MultiRowHeaderProps<TData = unknown> {
79
+ /**
80
+ * The TanStack table instance. Provides `getHeaderGroups()` used for
81
+ * multi-row header rendering.
82
+ */
83
+ table: Table<TData>;
84
+ /**
85
+ * When true, applies sticky positioning to each header row so the multi-row
86
+ * header remains fixed at the viewport top during vertical scroll (AC-001).
87
+ * Default: false (G-001 behaviour preserved — breaking: false).
88
+ */
89
+ enableStickyHeader?: boolean;
90
+ /**
91
+ * Number of columns pinned on the left that should receive `sticky left`
92
+ * positioning. Acts as an on/off switch; the actual frozen column identities
93
+ * are determined from TanStack's `columnPinning.left` state via
94
+ * `column.getIsPinned() === 'left'` (AC-002, D2 decision).
95
+ * 0 or omitted: frozen positioning inactive.
96
+ */
97
+ frozenColumns?: number;
98
+ /**
99
+ * When true, group header cells (non-leaf) become clickable toggles that
100
+ * show/hide all child (leaf) columns at once (G-003, AC-001).
101
+ * Clicking a group header that has all leaves hidden will show them all;
102
+ * clicking one with any visible leaf will hide them all.
103
+ * Leaf columns retain their sort click handler regardless.
104
+ * Default: false (G-001/G-002 behaviour preserved — breaking: false).
105
+ */
106
+ enableGroupToggle?: boolean;
107
+ }
108
+ /**
109
+ * Renders a multi-row `<thead>` element from a TanStack table instance.
110
+ *
111
+ * Iterates `table.getHeaderGroups()` to produce one `<tr>` per header row.
112
+ * Group header cells use `header.colSpan` (computed by TanStack automatically).
113
+ * Placeholder cells (`header.isPlaceholder`) are rendered as empty `<th>` elements.
114
+ * Sorting is enabled only on leaf columns (`!header.subHeaders.length`).
115
+ *
116
+ * @typeParam TData - The row data type of the table.
117
+ * @param props - `MultiRowHeaderProps<TData>`.
118
+ * @returns A `<thead>` JSX element with all header rows.
119
+ */
120
+ declare function MultiRowHeader<TData>({ table, enableStickyHeader, frozenColumns, enableGroupToggle, }: MultiRowHeaderProps<TData>): JSX.Element;
121
+
122
+ /**
123
+ * GroupedHeaderGrid — legacy alias component (G-003, C-6 deprecation alias).
124
+ *
125
+ * Wraps `useReactTable` + `MultiRowHeader` + tbody + pagination into a single
126
+ * self-contained component, preserving the AS-IS GroupedHeaderGrid API surface
127
+ * from tw-framework-front/src/components/tomis/Grid/GroupedHeaderGrid.tsx (L0).
128
+ *
129
+ * Behaviour and classNames are ported verbatim from L0 (C-17 visual preservation).
130
+ * `verifyOrWarn` is intentionally absent here — it runs via index.ts side-effect.
131
+ *
132
+ * D3 decision: inline type aliases for GridPaginationOptions / GridRowSelectionOptions
133
+ * to avoid reverse dependency on tw-framework-front.
134
+ *
135
+ * @see G-003-spec.md Section 6.2 — legacy/GroupedHeaderGrid structure
136
+ * @see C-6 — 1 minor version deprecation alias (breaking: false)
137
+ * @see C-17 — AS-IS L0 className is authoritative
138
+ */
139
+
140
+ /**
141
+ * Props for the legacy `GroupedHeaderGrid` wrapper component.
142
+ *
143
+ * @typeParam TData - The row data type.
144
+ * @deprecated Migrate to composing `useReactTable` + `MultiRowHeader` directly.
145
+ */
146
+ interface GroupedHeaderGridProps<TData = unknown> {
147
+ data: TData[];
148
+ /**
149
+ * Pass grouped column definitions using TanStack Table's native column grouping.
150
+ * Use `{ header: 'Group', columns: [...leafColumns] }` structure for grouping.
151
+ */
152
+ columns: ColumnDef<TData>[];
153
+ pagination?: GridPaginationOptions;
154
+ rowSelection?: GridRowSelectionOptions<TData>;
155
+ onRowClick?: (row: TData, event: MouseEvent<HTMLTableRowElement>) => void;
156
+ loading?: boolean;
157
+ emptyText?: string;
158
+ className?: string;
159
+ /** G-003 AC-001: enable group header click to toggle child column visibility. */
160
+ enableGroupToggle?: boolean;
161
+ }
162
+ /**
163
+ * Legacy self-contained grid component with grouped multi-row headers.
164
+ *
165
+ * Delegates header rendering to `MultiRowHeader` from `@topgrid/grid-pro-header`.
166
+ * tbody and pagination are ported verbatim from AS-IS L0 (C-17).
167
+ *
168
+ * @typeParam TData - The row data type (must extend `object`).
169
+ * @deprecated Prefer composing `useReactTable` + `MultiRowHeader` directly.
170
+ */
171
+ declare function GroupedHeaderGrid<TData extends object>({ data, columns, pagination, onRowClick, loading, emptyText, className, enableGroupToggle, }: GroupedHeaderGridProps<TData>): JSX.Element;
172
+
173
+ export { type ColumnGroupConfig, GroupedHeaderGrid, type GroupedHeaderGridProps, MultiRowHeader, type MultiRowHeaderProps, createColumnGroup };
@@ -0,0 +1,173 @@
1
+ import { ColumnDef, GroupColumnDef, Table } from '@tanstack/react-table';
2
+ import { MouseEvent } from 'react';
3
+ import { GridPaginationOptions, GridRowSelectionOptions } from '@topgrid/grid-core';
4
+
5
+ /**
6
+ * createColumnGroup — thin wrapper to create a TanStack `GroupColumnDef<TData>`.
7
+ *
8
+ * Provides TypeScript generic type-safety for the standard TanStack column grouping pattern:
9
+ * `{ header: string; columns: ColumnDef<TData>[] }`.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const infoGroup = createColumnGroup({
14
+ * header: '기본 정보',
15
+ * columns: [nameCol, deptCol],
16
+ * });
17
+ * ```
18
+ *
19
+ * @see AC-001 in G-001-spec.md — createColumnGroup signature
20
+ * @see Section 5.1 in G-001-spec.md — API design
21
+ */
22
+
23
+ /**
24
+ * Config object for `createColumnGroup`.
25
+ *
26
+ * @typeParam TData - The row data type of the table.
27
+ */
28
+ interface ColumnGroupConfig<TData> {
29
+ /** The display label for the column group header. */
30
+ header: string;
31
+ /** Leaf (or nested group) column definitions belonging to this group. */
32
+ columns: ColumnDef<TData>[];
33
+ }
34
+ /**
35
+ * Creates a TanStack `GroupColumnDef<TData>` from a typed config object.
36
+ *
37
+ * This is a thin wrapper — no logic beyond type narrowing. The returned
38
+ * object is identical to writing `{ header, columns }` inline, but provides
39
+ * generic type-checking at the call site.
40
+ *
41
+ * @typeParam TData - The row data type of the table.
42
+ * @param config - `ColumnGroupConfig<TData>` with `header` and `columns`.
43
+ * @returns A `GroupColumnDef<TData>` suitable for passing to `useReactTable`.
44
+ */
45
+ declare function createColumnGroup<TData>(config: ColumnGroupConfig<TData>): GroupColumnDef<TData>;
46
+
47
+ /**
48
+ * MultiRowHeader — renders a multi-row `<thead>` section from TanStack
49
+ * `table.getHeaderGroups()`.
50
+ *
51
+ * Extracts the header rendering logic from GroupedHeaderGrid.tsx (L75-117)
52
+ * into a reusable Pro-package component. Uses only TanStack v8 standard APIs
53
+ * (C-2): `getHeaderGroups`, `header.isPlaceholder`, `header.colSpan`,
54
+ * `header.subHeaders`, `flexRender`.
55
+ *
56
+ * G-002 additions: `enableStickyHeader` prop for multi-row sticky (AC-001),
57
+ * `frozenColumns` prop as on/off switch for column pinning left-offset (AC-002),
58
+ * CSS variable `--grid-header-row-height` based top offset (AC-003).
59
+ *
60
+ * G-003 additions: `enableGroupToggle` prop for group header click to toggle
61
+ * child column visibility (AC-001). Group cells get collapse icon ▼/▶ and
62
+ * click handler; leaf cells retain sort handler (AC-002, D2 decision).
63
+ *
64
+ * Flat columns mixed with group columns are handled automatically by TanStack's
65
+ * placeholder mechanism — do NOT add custom rowSpan calculation (spec §11.2).
66
+ *
67
+ * @see AC-001, AC-002, AC-003 in G-002-spec.md
68
+ * @see Section 5.1/5.2 in G-002-spec.md — API design
69
+ * @see Section 11.2/11.4 in G-002-spec.md — implementation guidelines
70
+ * @see Section 6.1, 11.1 in G-003-spec.md — enableGroupToggle implementation
71
+ */
72
+
73
+ /**
74
+ * Props for `MultiRowHeader`.
75
+ *
76
+ * @typeParam TData - The row data type of the table.
77
+ */
78
+ interface MultiRowHeaderProps<TData = unknown> {
79
+ /**
80
+ * The TanStack table instance. Provides `getHeaderGroups()` used for
81
+ * multi-row header rendering.
82
+ */
83
+ table: Table<TData>;
84
+ /**
85
+ * When true, applies sticky positioning to each header row so the multi-row
86
+ * header remains fixed at the viewport top during vertical scroll (AC-001).
87
+ * Default: false (G-001 behaviour preserved — breaking: false).
88
+ */
89
+ enableStickyHeader?: boolean;
90
+ /**
91
+ * Number of columns pinned on the left that should receive `sticky left`
92
+ * positioning. Acts as an on/off switch; the actual frozen column identities
93
+ * are determined from TanStack's `columnPinning.left` state via
94
+ * `column.getIsPinned() === 'left'` (AC-002, D2 decision).
95
+ * 0 or omitted: frozen positioning inactive.
96
+ */
97
+ frozenColumns?: number;
98
+ /**
99
+ * When true, group header cells (non-leaf) become clickable toggles that
100
+ * show/hide all child (leaf) columns at once (G-003, AC-001).
101
+ * Clicking a group header that has all leaves hidden will show them all;
102
+ * clicking one with any visible leaf will hide them all.
103
+ * Leaf columns retain their sort click handler regardless.
104
+ * Default: false (G-001/G-002 behaviour preserved — breaking: false).
105
+ */
106
+ enableGroupToggle?: boolean;
107
+ }
108
+ /**
109
+ * Renders a multi-row `<thead>` element from a TanStack table instance.
110
+ *
111
+ * Iterates `table.getHeaderGroups()` to produce one `<tr>` per header row.
112
+ * Group header cells use `header.colSpan` (computed by TanStack automatically).
113
+ * Placeholder cells (`header.isPlaceholder`) are rendered as empty `<th>` elements.
114
+ * Sorting is enabled only on leaf columns (`!header.subHeaders.length`).
115
+ *
116
+ * @typeParam TData - The row data type of the table.
117
+ * @param props - `MultiRowHeaderProps<TData>`.
118
+ * @returns A `<thead>` JSX element with all header rows.
119
+ */
120
+ declare function MultiRowHeader<TData>({ table, enableStickyHeader, frozenColumns, enableGroupToggle, }: MultiRowHeaderProps<TData>): JSX.Element;
121
+
122
+ /**
123
+ * GroupedHeaderGrid — legacy alias component (G-003, C-6 deprecation alias).
124
+ *
125
+ * Wraps `useReactTable` + `MultiRowHeader` + tbody + pagination into a single
126
+ * self-contained component, preserving the AS-IS GroupedHeaderGrid API surface
127
+ * from tw-framework-front/src/components/tomis/Grid/GroupedHeaderGrid.tsx (L0).
128
+ *
129
+ * Behaviour and classNames are ported verbatim from L0 (C-17 visual preservation).
130
+ * `verifyOrWarn` is intentionally absent here — it runs via index.ts side-effect.
131
+ *
132
+ * D3 decision: inline type aliases for GridPaginationOptions / GridRowSelectionOptions
133
+ * to avoid reverse dependency on tw-framework-front.
134
+ *
135
+ * @see G-003-spec.md Section 6.2 — legacy/GroupedHeaderGrid structure
136
+ * @see C-6 — 1 minor version deprecation alias (breaking: false)
137
+ * @see C-17 — AS-IS L0 className is authoritative
138
+ */
139
+
140
+ /**
141
+ * Props for the legacy `GroupedHeaderGrid` wrapper component.
142
+ *
143
+ * @typeParam TData - The row data type.
144
+ * @deprecated Migrate to composing `useReactTable` + `MultiRowHeader` directly.
145
+ */
146
+ interface GroupedHeaderGridProps<TData = unknown> {
147
+ data: TData[];
148
+ /**
149
+ * Pass grouped column definitions using TanStack Table's native column grouping.
150
+ * Use `{ header: 'Group', columns: [...leafColumns] }` structure for grouping.
151
+ */
152
+ columns: ColumnDef<TData>[];
153
+ pagination?: GridPaginationOptions;
154
+ rowSelection?: GridRowSelectionOptions<TData>;
155
+ onRowClick?: (row: TData, event: MouseEvent<HTMLTableRowElement>) => void;
156
+ loading?: boolean;
157
+ emptyText?: string;
158
+ className?: string;
159
+ /** G-003 AC-001: enable group header click to toggle child column visibility. */
160
+ enableGroupToggle?: boolean;
161
+ }
162
+ /**
163
+ * Legacy self-contained grid component with grouped multi-row headers.
164
+ *
165
+ * Delegates header rendering to `MultiRowHeader` from `@topgrid/grid-pro-header`.
166
+ * tbody and pagination are ported verbatim from AS-IS L0 (C-17).
167
+ *
168
+ * @typeParam TData - The row data type (must extend `object`).
169
+ * @deprecated Prefer composing `useReactTable` + `MultiRowHeader` directly.
170
+ */
171
+ declare function GroupedHeaderGrid<TData extends object>({ data, columns, pagination, onRowClick, loading, emptyText, className, enableGroupToggle, }: GroupedHeaderGridProps<TData>): JSX.Element;
172
+
173
+ export { type ColumnGroupConfig, GroupedHeaderGrid, type GroupedHeaderGridProps, MultiRowHeader, type MultiRowHeaderProps, createColumnGroup };
package/dist/index.mjs ADDED
@@ -0,0 +1,225 @@
1
+ import { checkLicense, useLicenseStatus, Watermark } from '@topgrid/grid-license';
2
+ import { useState } from 'react';
3
+ import { flexRender, useReactTable, getPaginationRowModel, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ // src/index.ts
7
+
8
+ // src/createColumnGroup.ts
9
+ function createColumnGroup(config) {
10
+ return {
11
+ header: config.header,
12
+ columns: config.columns
13
+ };
14
+ }
15
+ function getHeaderLeftOffset(header) {
16
+ const direct = header.column.getStart("left");
17
+ if (direct !== void 0) return direct;
18
+ const firstLeaf = header.subHeaders[0]?.column;
19
+ return firstLeaf?.getStart("left") ?? 0;
20
+ }
21
+ function MultiRowHeader({
22
+ table,
23
+ enableStickyHeader,
24
+ frozenColumns,
25
+ enableGroupToggle
26
+ }) {
27
+ const _lic = useLicenseStatus();
28
+ const headerGroups = table.getHeaderGroups();
29
+ const visibleLeafCount = table.getVisibleLeafColumns().length;
30
+ return /* @__PURE__ */ jsxs("thead", { className: "bg-gray-50", children: [
31
+ _lic.watermarkRequired && visibleLeafCount > 0 ? /* @__PURE__ */ jsx(
32
+ "tr",
33
+ {
34
+ ...enableStickyHeader === true ? { className: "sticky top-0 z-20" } : {},
35
+ children: /* @__PURE__ */ jsx(
36
+ "th",
37
+ {
38
+ colSpan: visibleLeafCount,
39
+ className: "relative bg-yellow-50 px-4 py-1 text-center text-xs text-gray-500",
40
+ children: /* @__PURE__ */ jsx(Watermark, { required: true })
41
+ }
42
+ )
43
+ }
44
+ ) : null,
45
+ headerGroups.map((headerGroup, rowIndex) => {
46
+ const trProps = {
47
+ ...enableStickyHeader === true && rowIndex === 0 && {
48
+ className: "sticky top-0 z-10"
49
+ },
50
+ ...enableStickyHeader === true && rowIndex > 0 && {
51
+ className: "sticky z-10",
52
+ style: {
53
+ top: `calc(var(--grid-header-row-height, 40px) * ${rowIndex})`
54
+ }
55
+ }
56
+ };
57
+ return /* @__PURE__ */ jsx("tr", { ...trProps, children: headerGroup.headers.map((header) => {
58
+ const isFrozen = (frozenColumns ?? 0) > 0 && header.column.getIsPinned() === "left";
59
+ const frozenZClass = isFrozen && enableStickyHeader === true ? "sticky z-30" : isFrozen ? "sticky z-20" : "";
60
+ const thStyle = isFrozen ? { left: `${getHeaderLeftOffset(header)}px` } : {};
61
+ const isLeaf = header.subHeaders.length === 0;
62
+ const allLeavesHidden = !isLeaf && header.column.getLeafColumns().every((c) => !c.getIsVisible());
63
+ const groupClickHandler = enableGroupToggle === true && !isLeaf ? () => {
64
+ const leafCols = header.column.getLeafColumns();
65
+ leafCols.forEach((c) => c.toggleVisibility(allLeavesHidden));
66
+ } : void 0;
67
+ const effectiveColSpan = enableGroupToggle === true && allLeavesHidden ? 1 : header.colSpan;
68
+ if (header.isPlaceholder) {
69
+ return /* @__PURE__ */ jsx(
70
+ "th",
71
+ {
72
+ colSpan: effectiveColSpan,
73
+ className: `px-4 py-3 border border-gray-200${frozenZClass ? ` ${frozenZClass}` : ""}`,
74
+ ...isFrozen ? { style: thStyle } : {}
75
+ },
76
+ header.id
77
+ );
78
+ }
79
+ return /* @__PURE__ */ jsx(
80
+ "th",
81
+ {
82
+ colSpan: effectiveColSpan,
83
+ className: `px-4 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider border border-gray-200 whitespace-nowrap select-none${header.column.getCanSort() && isLeaf ? " cursor-pointer hover:bg-gray-100" : ""}${enableGroupToggle === true && !isLeaf ? " cursor-pointer hover:bg-gray-100" : ""}${frozenZClass ? ` ${frozenZClass}` : ""}`,
84
+ ...isFrozen ? { style: thStyle } : {},
85
+ onClick: isLeaf ? header.column.getToggleSortingHandler() : groupClickHandler,
86
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1", children: [
87
+ flexRender(header.column.columnDef.header, header.getContext()),
88
+ header.column.getCanSort() && isLeaf && /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: { asc: "\u25B2", desc: "\u25BC" }[header.column.getIsSorted()] ?? "\u21C5" }),
89
+ enableGroupToggle === true && !isLeaf && /* @__PURE__ */ jsx("span", { className: "text-gray-400 ml-1", children: allLeavesHidden ? "\u25B6" : "\u25BC" })
90
+ ] })
91
+ },
92
+ header.id
93
+ );
94
+ }) }, headerGroup.id);
95
+ })
96
+ ] });
97
+ }
98
+ function GroupedHeaderGrid({
99
+ data,
100
+ columns,
101
+ pagination,
102
+ onRowClick,
103
+ loading = false,
104
+ emptyText = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
105
+ className = "",
106
+ enableGroupToggle
107
+ }) {
108
+ const [sorting, setSorting] = useState([]);
109
+ const [pageIndex, setPageIndex] = useState(0);
110
+ const [pageSize] = useState(pagination?.pageSize ?? 20);
111
+ const table = useReactTable({
112
+ data,
113
+ columns,
114
+ state: {
115
+ sorting,
116
+ pagination: { pageIndex, pageSize }
117
+ },
118
+ onSortingChange: setSorting,
119
+ onPaginationChange: (updater) => {
120
+ const next = typeof updater === "function" ? updater({ pageIndex, pageSize }) : updater;
121
+ setPageIndex(next.pageIndex);
122
+ },
123
+ getCoreRowModel: getCoreRowModel(),
124
+ getSortedRowModel: getSortedRowModel(),
125
+ // C-29: exactOptionalPropertyTypes — conditional spread avoids assigning undefined
126
+ // to a non-optional property when pagination is absent.
127
+ ...pagination !== void 0 ? { getPaginationRowModel: getPaginationRowModel() } : {},
128
+ manualPagination: false
129
+ });
130
+ const pageCount = table.getPageCount();
131
+ if (loading) {
132
+ return /* @__PURE__ */ jsx("div", { className: `flex flex-col ${className}`, children: /* @__PURE__ */ jsx("div", { className: "h-40 flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-blue-500" }) }) });
133
+ }
134
+ return /* @__PURE__ */ jsxs("div", { className: `flex flex-col ${className}`, children: [
135
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-lg border border-gray-200", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full text-sm border-collapse", children: [
136
+ /* @__PURE__ */ jsx(
137
+ MultiRowHeader,
138
+ {
139
+ table,
140
+ ...enableGroupToggle === true ? { enableGroupToggle: true } : {}
141
+ }
142
+ ),
143
+ /* @__PURE__ */ jsx("tbody", { className: "bg-white divide-y divide-gray-100", children: table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
144
+ "td",
145
+ {
146
+ colSpan: table.getAllLeafColumns().length,
147
+ className: "px-4 py-10 text-center text-gray-400",
148
+ children: emptyText
149
+ }
150
+ ) }) : table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
151
+ "tr",
152
+ {
153
+ className: `hover:bg-gray-50 ${onRowClick ? "cursor-pointer" : ""}`,
154
+ onClick: (e) => onRowClick?.(row.original, e),
155
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(
156
+ "td",
157
+ {
158
+ className: "px-4 py-3 whitespace-nowrap text-gray-700 border-r border-gray-100 last:border-r-0",
159
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
160
+ },
161
+ cell.id
162
+ ))
163
+ },
164
+ row.id
165
+ )) })
166
+ ] }) }),
167
+ pagination !== void 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-2 py-3 text-sm text-gray-600", children: [
168
+ /* @__PURE__ */ jsxs("span", { children: [
169
+ "\uC804\uCCB4 ",
170
+ /* @__PURE__ */ jsx("strong", { children: table.getFilteredRowModel().rows.length }),
171
+ "\uAC74"
172
+ ] }),
173
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
174
+ /* @__PURE__ */ jsx(
175
+ "button",
176
+ {
177
+ onClick: () => table.setPageIndex(0),
178
+ disabled: !table.getCanPreviousPage(),
179
+ className: "px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100",
180
+ children: "\xAB"
181
+ }
182
+ ),
183
+ /* @__PURE__ */ jsx(
184
+ "button",
185
+ {
186
+ onClick: () => table.previousPage(),
187
+ disabled: !table.getCanPreviousPage(),
188
+ className: "px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100",
189
+ children: "\u2039"
190
+ }
191
+ ),
192
+ /* @__PURE__ */ jsxs("span", { className: "px-3", children: [
193
+ pageIndex + 1,
194
+ " / ",
195
+ pageCount || 1
196
+ ] }),
197
+ /* @__PURE__ */ jsx(
198
+ "button",
199
+ {
200
+ onClick: () => table.nextPage(),
201
+ disabled: !table.getCanNextPage(),
202
+ className: "px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100",
203
+ children: "\u203A"
204
+ }
205
+ ),
206
+ /* @__PURE__ */ jsx(
207
+ "button",
208
+ {
209
+ onClick: () => table.setPageIndex(pageCount - 1),
210
+ disabled: !table.getCanNextPage(),
211
+ className: "px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100",
212
+ children: "\xBB"
213
+ }
214
+ )
215
+ ] })
216
+ ] })
217
+ ] });
218
+ }
219
+
220
+ // src/index.ts
221
+ checkLicense();
222
+
223
+ export { GroupedHeaderGrid, MultiRowHeader, createColumnGroup };
224
+ //# sourceMappingURL=index.mjs.map
225
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/createColumnGroup.ts","../src/MultiRowHeader.tsx","../src/legacy/GroupedHeaderGrid.tsx","../src/index.ts"],"names":["jsx","jsxs","flexRender"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * createColumnGroup — thin wrapper to create a TanStack `GroupColumnDef<TData>`.\r\n *\r\n * Provides TypeScript generic type-safety for the standard TanStack column grouping pattern:\r\n * `{ header: string; columns: ColumnDef<TData>[] }`.\r\n *\r\n * @example\r\n * ```typescript\r\n * const infoGroup = createColumnGroup({\r\n * header: '기본 정보',\r\n * columns: [nameCol, deptCol],\r\n * });\r\n * ```\r\n *\r\n * @see AC-001 in G-001-spec.md — createColumnGroup signature\r\n * @see Section 5.1 in G-001-spec.md — API design\r\n */\r\n\r\nimport type { ColumnDef, GroupColumnDef } from '@tanstack/react-table';\r\n\r\n/**\r\n * Config object for `createColumnGroup`.\r\n *\r\n * @typeParam TData - The row data type of the table.\r\n */\r\nexport interface ColumnGroupConfig<TData> {\r\n /** The display label for the column group header. */\r\n header: string;\r\n /** Leaf (or nested group) column definitions belonging to this group. */\r\n columns: ColumnDef<TData>[];\r\n}\r\n\r\n/**\r\n * Creates a TanStack `GroupColumnDef<TData>` from a typed config object.\r\n *\r\n * This is a thin wrapper — no logic beyond type narrowing. The returned\r\n * object is identical to writing `{ header, columns }` inline, but provides\r\n * generic type-checking at the call site.\r\n *\r\n * @typeParam TData - The row data type of the table.\r\n * @param config - `ColumnGroupConfig<TData>` with `header` and `columns`.\r\n * @returns A `GroupColumnDef<TData>` suitable for passing to `useReactTable`.\r\n */\r\nexport function createColumnGroup<TData>(\r\n config: ColumnGroupConfig<TData>,\r\n): GroupColumnDef<TData> {\r\n return {\r\n header: config.header,\r\n columns: config.columns,\r\n };\r\n}\r\n","/**\r\n * MultiRowHeader — renders a multi-row `<thead>` section from TanStack\r\n * `table.getHeaderGroups()`.\r\n *\r\n * Extracts the header rendering logic from GroupedHeaderGrid.tsx (L75-117)\r\n * into a reusable Pro-package component. Uses only TanStack v8 standard APIs\r\n * (C-2): `getHeaderGroups`, `header.isPlaceholder`, `header.colSpan`,\r\n * `header.subHeaders`, `flexRender`.\r\n *\r\n * G-002 additions: `enableStickyHeader` prop for multi-row sticky (AC-001),\r\n * `frozenColumns` prop as on/off switch for column pinning left-offset (AC-002),\r\n * CSS variable `--grid-header-row-height` based top offset (AC-003).\r\n *\r\n * G-003 additions: `enableGroupToggle` prop for group header click to toggle\r\n * child column visibility (AC-001). Group cells get collapse icon ▼/▶ and\r\n * click handler; leaf cells retain sort handler (AC-002, D2 decision).\r\n *\r\n * Flat columns mixed with group columns are handled automatically by TanStack's\r\n * placeholder mechanism — do NOT add custom rowSpan calculation (spec §11.2).\r\n *\r\n * @see AC-001, AC-002, AC-003 in G-002-spec.md\r\n * @see Section 5.1/5.2 in G-002-spec.md — API design\r\n * @see Section 11.2/11.4 in G-002-spec.md — implementation guidelines\r\n * @see Section 6.1, 11.1 in G-003-spec.md — enableGroupToggle implementation\r\n */\r\n\r\nimport { type CSSProperties } from 'react';\r\nimport { flexRender, type Header, type Table } from '@tanstack/react-table';\r\nimport { useLicenseStatus, Watermark } from '@topgrid/grid-license';\r\n\r\n/**\r\n * Props for `MultiRowHeader`.\r\n *\r\n * @typeParam TData - The row data type of the table.\r\n */\r\nexport interface MultiRowHeaderProps<TData = unknown> {\r\n /**\r\n * The TanStack table instance. Provides `getHeaderGroups()` used for\r\n * multi-row header rendering.\r\n */\r\n table: Table<TData>;\r\n /**\r\n * When true, applies sticky positioning to each header row so the multi-row\r\n * header remains fixed at the viewport top during vertical scroll (AC-001).\r\n * Default: false (G-001 behaviour preserved — breaking: false).\r\n */\r\n enableStickyHeader?: boolean;\r\n /**\r\n * Number of columns pinned on the left that should receive `sticky left`\r\n * positioning. Acts as an on/off switch; the actual frozen column identities\r\n * are determined from TanStack's `columnPinning.left` state via\r\n * `column.getIsPinned() === 'left'` (AC-002, D2 decision).\r\n * 0 or omitted: frozen positioning inactive.\r\n */\r\n frozenColumns?: number;\r\n /**\r\n * When true, group header cells (non-leaf) become clickable toggles that\r\n * show/hide all child (leaf) columns at once (G-003, AC-001).\r\n * Clicking a group header that has all leaves hidden will show them all;\r\n * clicking one with any visible leaf will hide them all.\r\n * Leaf columns retain their sort click handler regardless.\r\n * Default: false (G-001/G-002 behaviour preserved — breaking: false).\r\n */\r\n enableGroupToggle?: boolean;\r\n}\r\n\r\n/**\r\n * Returns the left pixel offset for a frozen header cell (AC-002, EC-05).\r\n *\r\n * TanStack's `column.getStart('left')` returns the correct offset for leaf\r\n * columns. For group header cells it may return `undefined`; in that case the\r\n * first leaf child's offset is used as a fallback (spec §11.4 EC-05).\r\n *\r\n * @typeParam TData - Row data type (matches the parent table's TData).\r\n * @see G-002-spec.md Section 11.4\r\n */\r\nfunction getHeaderLeftOffset<TData>(header: Header<TData, unknown>): number {\r\n const direct = header.column.getStart('left');\r\n if (direct !== undefined) return direct;\r\n // EC-05 fallback: group header cell — use first leaf child's offset.\r\n const firstLeaf = header.subHeaders[0]?.column;\r\n return firstLeaf?.getStart('left') ?? 0;\r\n}\r\n\r\n/**\r\n * Renders a multi-row `<thead>` element from a TanStack table instance.\r\n *\r\n * Iterates `table.getHeaderGroups()` to produce one `<tr>` per header row.\r\n * Group header cells use `header.colSpan` (computed by TanStack automatically).\r\n * Placeholder cells (`header.isPlaceholder`) are rendered as empty `<th>` elements.\r\n * Sorting is enabled only on leaf columns (`!header.subHeaders.length`).\r\n *\r\n * @typeParam TData - The row data type of the table.\r\n * @param props - `MultiRowHeaderProps<TData>`.\r\n * @returns A `<thead>` JSX element with all header rows.\r\n */\r\nexport function MultiRowHeader<TData>({\r\n table,\r\n enableStickyHeader,\r\n frozenColumns,\r\n enableGroupToggle,\r\n}: MultiRowHeaderProps<TData>): JSX.Element {\r\n // ADR-MOD-GRID-REFACTOR-2026-05-17-001 — license watermark wiring (H-D pattern)\r\n // sub-spec §8 Step 4: extra <tr><th colSpan> watermark row inside <thead>.\r\n // §9.3 D-3 = (a): sticky top-0 when enableStickyHeader is true.\r\n const _lic = useLicenseStatus();\r\n const headerGroups = table.getHeaderGroups();\r\n const visibleLeafCount = table.getVisibleLeafColumns().length;\r\n\r\n return (\r\n <thead className=\"bg-gray-50\">\r\n {_lic.watermarkRequired && visibleLeafCount > 0 ? (\r\n <tr\r\n {...(enableStickyHeader === true\r\n ? { className: 'sticky top-0 z-20' }\r\n : {})}\r\n >\r\n <th\r\n colSpan={visibleLeafCount}\r\n className=\"relative bg-yellow-50 px-4 py-1 text-center text-xs text-gray-500\"\r\n >\r\n <Watermark required />\r\n </th>\r\n </tr>\r\n ) : null}\r\n {headerGroups.map((headerGroup, rowIndex) => {\r\n // AC-001: sticky row props — C-29 conditional spread pattern.\r\n // Row 0: sticky top-0 z-10 (Tailwind only, no inline style needed).\r\n // Row N≥1: sticky z-10 + inline style top: calc(var(--grid-header-row-height, 40px) * N).\r\n const trProps = {\r\n ...(enableStickyHeader === true && rowIndex === 0 && {\r\n className: 'sticky top-0 z-10',\r\n }),\r\n ...(enableStickyHeader === true && rowIndex > 0 && {\r\n className: 'sticky z-10',\r\n style: {\r\n top: `calc(var(--grid-header-row-height, 40px) * ${rowIndex})`,\r\n } as CSSProperties,\r\n }),\r\n };\r\n\r\n return (\r\n <tr key={headerGroup.id} {...trProps}>\r\n {headerGroup.headers.map((header) => {\r\n // AC-002: frozen column detection via TanStack native API (D2 decision).\r\n // frozenColumns > 0 acts as the feature on/off switch;\r\n // actual pinned identity comes from TanStack columnPinning state.\r\n const isFrozen =\r\n (frozenColumns ?? 0) > 0 &&\r\n header.column.getIsPinned() === 'left';\r\n\r\n // D4: z-index layers.\r\n // frozen + sticky intersection → z-30.\r\n // frozen only (sticky off) → z-20.\r\n // Neither → no extra z-class.\r\n const frozenZClass =\r\n isFrozen && enableStickyHeader === true\r\n ? 'sticky z-30'\r\n : isFrozen\r\n ? 'sticky z-20'\r\n : '';\r\n\r\n // AC-002: left offset in px (inline style — dynamic runtime value, C-5 exception).\r\n // EC-05 fallback: group cell getStart('left') may be undefined → subHeaders[0] fallback.\r\n const thStyle: CSSProperties = isFrozen\r\n ? { left: `${getHeaderLeftOffset(header as Header<unknown, unknown>)}px` }\r\n : {};\r\n\r\n // Leaf columns: sorting enabled. Group columns: group toggle (if enabled).\r\n const isLeaf = header.subHeaders.length === 0;\r\n\r\n // G-003 AC-001: pre-compute allLeavesHidden once per non-leaf header.\r\n // Used for (a) click handler, (b) effectiveColSpan, (c) collapse icon.\r\n const allLeavesHidden =\r\n !isLeaf &&\r\n header.column.getLeafColumns().every((c) => !c.getIsVisible());\r\n\r\n // G-003 AC-001: group click handler — toggle all leaf column visibility.\r\n // allLeavesHidden → show all (true); any visible leaf → hide all (false).\r\n const groupClickHandler =\r\n enableGroupToggle === true && !isLeaf\r\n ? () => {\r\n const leafCols = header.column.getLeafColumns();\r\n leafCols.forEach((c) => c.toggleVisibility(allLeavesHidden));\r\n }\r\n : undefined;\r\n\r\n // G-003: effectiveColSpan — collapsed group occupies 1 column (spec §6.1).\r\n const effectiveColSpan =\r\n enableGroupToggle === true && allLeavesHidden\r\n ? 1\r\n : header.colSpan;\r\n\r\n // isPlaceholder: filler cell for multi-row headers (TanStack placeholder mechanism).\r\n // Flat columns in the group row appear as placeholder cells — rendered empty.\r\n if (header.isPlaceholder) {\r\n return (\r\n <th\r\n key={header.id}\r\n colSpan={effectiveColSpan}\r\n className={`px-4 py-3 border border-gray-200${frozenZClass ? ` ${frozenZClass}` : ''}`}\r\n {...(isFrozen ? { style: thStyle } : {})}\r\n />\r\n );\r\n }\r\n\r\n return (\r\n <th\r\n key={header.id}\r\n colSpan={effectiveColSpan}\r\n className={`px-4 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider border border-gray-200 whitespace-nowrap select-none${\r\n header.column.getCanSort() && isLeaf\r\n ? ' cursor-pointer hover:bg-gray-100'\r\n : ''\r\n }${\r\n enableGroupToggle === true && !isLeaf\r\n ? ' cursor-pointer hover:bg-gray-100'\r\n : ''\r\n }${frozenZClass ? ` ${frozenZClass}` : ''}`}\r\n {...(isFrozen ? { style: thStyle } : {})}\r\n onClick={\r\n isLeaf ? header.column.getToggleSortingHandler() : groupClickHandler\r\n }\r\n >\r\n <div className=\"flex items-center justify-center gap-1\">\r\n {flexRender(header.column.columnDef.header, header.getContext())}\r\n {header.column.getCanSort() && isLeaf && (\r\n <span className=\"text-gray-400\">\r\n {({ asc: '▲', desc: '▼' } as Record<string, string>)[\r\n header.column.getIsSorted() as string\r\n ] ?? '⇅'}\r\n </span>\r\n )}\r\n {enableGroupToggle === true && !isLeaf && (\r\n <span className=\"text-gray-400 ml-1\">\r\n {allLeavesHidden ? '▶' : '▼'}\r\n </span>\r\n )}\r\n </div>\r\n </th>\r\n );\r\n })}\r\n </tr>\r\n );\r\n })}\r\n </thead>\r\n );\r\n}\r\n","/**\r\n * GroupedHeaderGrid — legacy alias component (G-003, C-6 deprecation alias).\r\n *\r\n * Wraps `useReactTable` + `MultiRowHeader` + tbody + pagination into a single\r\n * self-contained component, preserving the AS-IS GroupedHeaderGrid API surface\r\n * from tw-framework-front/src/components/tomis/Grid/GroupedHeaderGrid.tsx (L0).\r\n *\r\n * Behaviour and classNames are ported verbatim from L0 (C-17 visual preservation).\r\n * `verifyOrWarn` is intentionally absent here — it runs via index.ts side-effect.\r\n *\r\n * D3 decision: inline type aliases for GridPaginationOptions / GridRowSelectionOptions\r\n * to avoid reverse dependency on tw-framework-front.\r\n *\r\n * @see G-003-spec.md Section 6.2 — legacy/GroupedHeaderGrid structure\r\n * @see C-6 — 1 minor version deprecation alias (breaking: false)\r\n * @see C-17 — AS-IS L0 className is authoritative\r\n */\r\n\r\nimport { useState } from 'react';\r\nimport type { MouseEvent } from 'react';\r\nimport {\r\n useReactTable,\r\n getCoreRowModel,\r\n getSortedRowModel,\r\n getPaginationRowModel,\r\n flexRender,\r\n type SortingState,\r\n type ColumnDef,\r\n} from '@tanstack/react-table';\r\nimport type { GridPaginationOptions, GridRowSelectionOptions } from '@topgrid/grid-core';\r\nimport { MultiRowHeader } from '../MultiRowHeader';\r\n\r\n/**\r\n * Props for the legacy `GroupedHeaderGrid` wrapper component.\r\n *\r\n * @typeParam TData - The row data type.\r\n * @deprecated Migrate to composing `useReactTable` + `MultiRowHeader` directly.\r\n */\r\nexport interface GroupedHeaderGridProps<TData = unknown> {\r\n data: TData[];\r\n /**\r\n * Pass grouped column definitions using TanStack Table's native column grouping.\r\n * Use `{ header: 'Group', columns: [...leafColumns] }` structure for grouping.\r\n */\r\n columns: ColumnDef<TData>[];\r\n pagination?: GridPaginationOptions;\r\n rowSelection?: GridRowSelectionOptions<TData>;\r\n onRowClick?: (row: TData, event: MouseEvent<HTMLTableRowElement>) => void;\r\n loading?: boolean;\r\n emptyText?: string;\r\n className?: string;\r\n /** G-003 AC-001: enable group header click to toggle child column visibility. */\r\n enableGroupToggle?: boolean;\r\n}\r\n\r\n/**\r\n * Legacy self-contained grid component with grouped multi-row headers.\r\n *\r\n * Delegates header rendering to `MultiRowHeader` from `@topgrid/grid-pro-header`.\r\n * tbody and pagination are ported verbatim from AS-IS L0 (C-17).\r\n *\r\n * @typeParam TData - The row data type (must extend `object`).\r\n * @deprecated Prefer composing `useReactTable` + `MultiRowHeader` directly.\r\n */\r\nexport function GroupedHeaderGrid<TData extends object>({\r\n data,\r\n columns,\r\n pagination,\r\n onRowClick,\r\n loading = false,\r\n emptyText = '데이터가 없습니다.',\r\n className = '',\r\n enableGroupToggle,\r\n}: GroupedHeaderGridProps<TData>): JSX.Element {\r\n const [sorting, setSorting] = useState<SortingState>([]);\r\n const [pageIndex, setPageIndex] = useState(0);\r\n const [pageSize] = useState(pagination?.pageSize ?? 20);\r\n\r\n const table = useReactTable({\r\n data,\r\n columns,\r\n state: {\r\n sorting,\r\n pagination: { pageIndex, pageSize },\r\n },\r\n onSortingChange: setSorting,\r\n onPaginationChange: (updater) => {\r\n const next =\r\n typeof updater === 'function' ? updater({ pageIndex, pageSize }) : updater;\r\n setPageIndex(next.pageIndex);\r\n },\r\n getCoreRowModel: getCoreRowModel(),\r\n getSortedRowModel: getSortedRowModel(),\r\n // C-29: exactOptionalPropertyTypes — conditional spread avoids assigning undefined\r\n // to a non-optional property when pagination is absent.\r\n ...(pagination !== undefined\r\n ? { getPaginationRowModel: getPaginationRowModel() }\r\n : {}),\r\n manualPagination: false,\r\n });\r\n\r\n const pageCount = table.getPageCount();\r\n\r\n if (loading) {\r\n return (\r\n <div className={`flex flex-col ${className}`}>\r\n <div className=\"h-40 flex items-center justify-center\">\r\n <div className=\"animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-blue-500\" />\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={`flex flex-col ${className}`}>\r\n <div className=\"overflow-x-auto rounded-lg border border-gray-200\">\r\n <table className=\"min-w-full text-sm border-collapse\">\r\n <MultiRowHeader\r\n table={table}\r\n {...(enableGroupToggle === true ? { enableGroupToggle: true } : {})}\r\n />\r\n <tbody className=\"bg-white divide-y divide-gray-100\">\r\n {table.getRowModel().rows.length === 0 ? (\r\n <tr>\r\n <td\r\n colSpan={table.getAllLeafColumns().length}\r\n className=\"px-4 py-10 text-center text-gray-400\"\r\n >\r\n {emptyText}\r\n </td>\r\n </tr>\r\n ) : (\r\n table.getRowModel().rows.map((row) => (\r\n <tr\r\n key={row.id}\r\n className={`hover:bg-gray-50 ${onRowClick ? 'cursor-pointer' : ''}`}\r\n onClick={(e) => onRowClick?.(row.original, e)}\r\n >\r\n {row.getVisibleCells().map((cell) => (\r\n <td\r\n key={cell.id}\r\n className=\"px-4 py-3 whitespace-nowrap text-gray-700 border-r border-gray-100 last:border-r-0\"\r\n >\r\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\r\n </td>\r\n ))}\r\n </tr>\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n {pagination !== undefined && (\r\n <div className=\"flex items-center justify-between px-2 py-3 text-sm text-gray-600\">\r\n <span>\r\n 전체 <strong>{table.getFilteredRowModel().rows.length}</strong>건\r\n </span>\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => table.setPageIndex(0)}\r\n disabled={!table.getCanPreviousPage()}\r\n className=\"px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100\"\r\n >\r\n {'«'}\r\n </button>\r\n <button\r\n onClick={() => table.previousPage()}\r\n disabled={!table.getCanPreviousPage()}\r\n className=\"px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100\"\r\n >\r\n {'‹'}\r\n </button>\r\n <span className=\"px-3\">\r\n {pageIndex + 1} / {pageCount || 1}\r\n </span>\r\n <button\r\n onClick={() => table.nextPage()}\r\n disabled={!table.getCanNextPage()}\r\n className=\"px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100\"\r\n >\r\n {'›'}\r\n </button>\r\n <button\r\n onClick={() => table.setPageIndex(pageCount - 1)}\r\n disabled={!table.getCanNextPage()}\r\n className=\"px-2 py-1 rounded border border-gray-300 disabled:opacity-40 hover:bg-gray-100\"\r\n >\r\n {'»'}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { checkLicense } from '@topgrid/grid-license';\r\n\r\ncheckLicense();\r\n\r\n// createColumnGroup helper (AC-001)\r\nexport { createColumnGroup } from './createColumnGroup';\r\nexport type { ColumnGroupConfig } from './types';\r\n\r\n// MultiRowHeader component (AC-002, AC-003, AC-004)\r\nexport { MultiRowHeader } from './MultiRowHeader';\r\nexport type { MultiRowHeaderProps } from './types';\r\n\r\n// GroupedHeaderGrid legacy alias (G-003, C-6 deprecation alias)\r\nexport { GroupedHeaderGrid } from './legacy/GroupedHeaderGrid';\r\nexport type { GroupedHeaderGridProps } from './legacy/GroupedHeaderGrid';\r\n"]}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@topgrid/grid-pro-header",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "license": "SEE LICENSE IN EULA",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "description": "Pro: Multi-row Header (Column Groups)",
10
+ "main": "./dist/index.cjs",
11
+ "module": "./dist/index.mjs",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.mjs",
17
+ "require": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md"
23
+ ],
24
+ "sideEffects": [
25
+ "./src/index.ts"
26
+ ],
27
+ "dependencies": {
28
+ "@topgrid/grid-core": "0.1.0",
29
+ "@topgrid/grid-license": "0.1.0"
30
+ },
31
+ "peerDependencies": {
32
+ "@tanstack/react-table": "^8.0.0",
33
+ "react": "^18.0.0 || ^19.0.0",
34
+ "react-dom": "^18.0.0 || ^19.0.0"
35
+ },
36
+ "scripts": {
37
+ "build": "tsup",
38
+ "typecheck": "tsc --noEmit",
39
+ "test": "echo TODO"
40
+ }
41
+ }