@ncds/ui-admin 1.8.11 → 1.8.12
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/dist/cjs/src/components/data-display/data-grid/DataGrid.js +3 -1
- package/dist/cjs/src/components/data-display/table/Table.js +326 -75
- package/dist/cjs/src/components/data-display/table/dnd-context.js +15 -0
- package/dist/cjs/src/components/data-display/table/dnd-preview.js +127 -0
- package/dist/esm/src/components/data-display/data-grid/DataGrid.js +3 -1
- package/dist/esm/src/components/data-display/table/Table.js +328 -77
- package/dist/esm/src/components/data-display/table/dnd-context.js +10 -0
- package/dist/esm/src/components/data-display/table/dnd-preview.js +121 -0
- package/dist/temp/src/components/data-display/data-grid/DataGrid.js +1 -1
- package/dist/temp/src/components/data-display/data-grid/DataGrid.types.d.ts +5 -0
- package/dist/temp/src/components/data-display/table/Table.d.ts +14 -4
- package/dist/temp/src/components/data-display/table/Table.js +172 -14
- package/dist/temp/src/components/data-display/table/dnd-context.d.ts +12 -0
- package/dist/temp/src/components/data-display/table/dnd-context.js +10 -0
- package/dist/temp/src/components/data-display/table/dnd-preview.d.ts +6 -0
- package/dist/temp/src/components/data-display/table/dnd-preview.js +120 -0
- package/dist/temp/src/components/data-display/table/types.d.ts +24 -1
- package/dist/types/src/components/data-display/data-grid/DataGrid.types.d.ts +5 -0
- package/dist/types/src/components/data-display/table/Table.d.ts +14 -4
- package/dist/types/src/components/data-display/table/dnd-context.d.ts +12 -0
- package/dist/types/src/components/data-display/table/dnd-preview.d.ts +6 -0
- package/dist/types/src/components/data-display/table/types.d.ts +24 -1
- package/dist/ui-admin/assets/styles/style.css +166 -2
- package/package.json +2 -2
|
@@ -19,7 +19,7 @@ const ActionBar = ({ children, className, position = 'top', align = 'space-betwe
|
|
|
19
19
|
'ncua-data-grid__action-bar--space-between': align === 'space-between',
|
|
20
20
|
}), ...rest, children: children }));
|
|
21
21
|
ActionBar.displayName = 'DataGrid.ActionBar';
|
|
22
|
-
const DataGridTable = forwardRef(({ children, className, type = 'horizontal', fixedHeader, maxHeight, hoverable, selectable, horizontalScroll, minWidth, }, ref) => (_jsx("div", { ref: ref, className: classNames('ncua-data-grid__table', className), children: _jsx(NcuaTable, { className: "ncua-table--in-data-grid", type: type, fixedHeader: fixedHeader, maxHeight: maxHeight, hoverable: hoverable, selectable: selectable, horizontalScroll: horizontalScroll, minWidth: minWidth, children: children }) })));
|
|
22
|
+
const DataGridTable = forwardRef(({ children, className, type = 'horizontal', fixedHeader, maxHeight, hoverable, selectable, horizontalScroll, minWidth, draggable, }, ref) => (_jsx("div", { ref: ref, className: classNames('ncua-data-grid__table', className), children: _jsx(NcuaTable, { className: "ncua-table--in-data-grid", type: type, fixedHeader: fixedHeader, maxHeight: maxHeight, hoverable: hoverable, selectable: selectable, horizontalScroll: horizontalScroll, minWidth: minWidth, draggable: draggable, children: children }) })));
|
|
23
23
|
DataGridTable.displayName = 'DataGrid.Table';
|
|
24
24
|
const Pagination = ({ children, className, ...rest }) => (_jsx("div", { className: classNames('ncua-data-grid__pagination', className), ...rest, children: children }));
|
|
25
25
|
Pagination.displayName = 'DataGrid.Pagination';
|
|
@@ -36,6 +36,11 @@ export type DataGridTableProps = {
|
|
|
36
36
|
horizontalScroll?: boolean;
|
|
37
37
|
/** 가로 스크롤 트리거 임계 너비. horizontalScroll=true 일 때만 의미가 있다. */
|
|
38
38
|
minWidth?: string | number;
|
|
39
|
+
/**
|
|
40
|
+
* 행 드래그앤드롭 활성화. Table.Row에 dragId, Table.Body에 onRowDrop,
|
|
41
|
+
* 헤더에 Table.DragHeaderCell, 각 행에 Table.DragCell을 함께 사용한다.
|
|
42
|
+
*/
|
|
43
|
+
draggable?: boolean;
|
|
39
44
|
};
|
|
40
45
|
export type DataGridPaginationProps = ComponentProps<'div'> & {
|
|
41
46
|
children: ReactNode;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
-
import type { SortDirection, TableBodyProps, TableColGroupProps, TableEmptyProps, TableFooterProps, TableHeaderProps, TablePaginationProps } from './types';
|
|
3
|
-
export declare const Table: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
|
2
|
+
import type { SortDirection, TableBodyProps, TableColGroupProps, TableDragCellProps, TableDragHeaderCellProps, TableEmptyProps, TableFooterProps, TableHeaderProps, TablePaginationProps } from './types';
|
|
3
|
+
export declare const Table: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "draggable" | "ref"> & {
|
|
4
4
|
type?: import("./types").TableType | undefined;
|
|
5
5
|
fixedHeader?: boolean | undefined;
|
|
6
6
|
maxHeight?: string | number | undefined;
|
|
@@ -8,6 +8,7 @@ export declare const Table: import("react").ForwardRefExoticComponent<Omit<impor
|
|
|
8
8
|
selectable?: boolean | undefined;
|
|
9
9
|
horizontalScroll?: boolean | undefined;
|
|
10
10
|
minWidth?: string | number | undefined;
|
|
11
|
+
draggable?: boolean | undefined;
|
|
11
12
|
children: ReactNode;
|
|
12
13
|
} & import("react").RefAttributes<HTMLDivElement>> & {
|
|
13
14
|
Header: {
|
|
@@ -15,13 +16,22 @@ export declare const Table: import("react").ForwardRefExoticComponent<Omit<impor
|
|
|
15
16
|
displayName: string;
|
|
16
17
|
};
|
|
17
18
|
Body: {
|
|
18
|
-
({ children, className }: TableBodyProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
({ children, className, onRowDrop }: TableBodyProps): import("react/jsx-runtime").JSX.Element;
|
|
19
20
|
displayName: string;
|
|
20
21
|
};
|
|
21
22
|
Row: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLTableRowElement>, HTMLTableRowElement>, "ref"> & {
|
|
22
23
|
selected?: boolean | undefined;
|
|
23
24
|
status?: import("./types").RowStatus | undefined;
|
|
25
|
+
dragId?: string | undefined;
|
|
24
26
|
} & import("react").RefAttributes<HTMLTableRowElement>>;
|
|
27
|
+
DragHeaderCell: {
|
|
28
|
+
({ className, children }: TableDragHeaderCellProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
displayName: string;
|
|
30
|
+
};
|
|
31
|
+
DragCell: {
|
|
32
|
+
({ disabled, className, children }: TableDragCellProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
displayName: string;
|
|
34
|
+
};
|
|
25
35
|
HeaderCell: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ThHTMLAttributes<HTMLTableHeaderCellElement>, HTMLTableHeaderCellElement>, "ref"> & {
|
|
26
36
|
sortDirection?: SortDirection | undefined;
|
|
27
37
|
onSort?: (() => void) | undefined;
|
|
@@ -48,4 +58,4 @@ export declare const Table: import("react").ForwardRefExoticComponent<Omit<impor
|
|
|
48
58
|
displayName: string;
|
|
49
59
|
};
|
|
50
60
|
};
|
|
51
|
-
export type { RowStatus, SortDirection, TableBodyProps, TableCellProps, TableColGroupProps, TableEmptyProps, TableFooterProps, TableHeaderCellProps, TableHeaderProps, TablePaginationProps, TableProps, TableRowProps, TableType, } from './types';
|
|
61
|
+
export type { RowStatus, SortDirection, TableBodyProps, TableCellProps, TableColGroupProps, TableDragCellProps, TableDragHeaderCellProps, TableEmptyProps, TableFooterProps, TableHeaderCellProps, TableHeaderProps, TablePaginationProps, TableProps, TableRowProps, TableType, } from './types';
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { dropTargetForElements, draggable as makeDraggable, monitorForElements, } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
3
|
+
import { disableNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/disable-native-drag-preview';
|
|
4
|
+
import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';
|
|
5
|
+
import { attachClosestEdge, extractClosestEdge, } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
6
|
+
import { ChevronDown, ChevronSelectorVertical, ChevronUp, DotsGrid02 } from '@ncds/ui-admin-icon';
|
|
3
7
|
import classNames from 'classnames';
|
|
4
|
-
import { Children, forwardRef, useRef, } from 'react';
|
|
8
|
+
import { Children, forwardRef, useCallback, useContext, useEffect, useRef, useState, } from 'react';
|
|
5
9
|
import { FloatingProvider } from '../../../contexts/FloatingContext';
|
|
10
|
+
import { RowDndContext, TableDndContext } from './dnd-context';
|
|
11
|
+
import { buildDragPreview, PREVIEW_BADGE_SIZE, TABLE_DND_ID_RADIX, TABLE_DND_ID_SLICE_END, TABLE_DND_ID_SLICE_START, } from './dnd-preview';
|
|
6
12
|
import { TABLE_HEADER_HEIGHT, useTableHorizontalScrollbar, useTableVerticalScrollbar } from './useTableScrollbars';
|
|
7
13
|
// 가로 스크롤 디자인 기준 폭 — 14인치 모니터 + LNB 고려한 디자인 권장 너비
|
|
8
14
|
const DEFAULT_HORIZONTAL_SCROLL_MIN_WIDTH = 1140;
|
|
@@ -29,14 +35,145 @@ const ARIA_SORT_MAP = {
|
|
|
29
35
|
// ──────────────────────────────────────────────
|
|
30
36
|
const Header = ({ children, className }) => (_jsx("thead", { className: classNames('ncua-table__header', className), children: children }));
|
|
31
37
|
Header.displayName = 'Table.Header';
|
|
32
|
-
const Body = ({ children, className }) =>
|
|
38
|
+
const Body = ({ children, className, onRowDrop }) => {
|
|
39
|
+
const { tableId } = useContext(TableDndContext);
|
|
40
|
+
// onRowDrop 참조를 ref로 유지 — 콜백이 매 렌더마다 재생성되어도 effect가 재구독하지 않도록
|
|
41
|
+
const onRowDropRef = useRef(onRowDrop);
|
|
42
|
+
onRowDropRef.current = onRowDrop;
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
return monitorForElements({
|
|
45
|
+
canMonitor: ({ source }) => source.data.tableId === tableId,
|
|
46
|
+
onDrop: ({ source, location }) => {
|
|
47
|
+
if (!onRowDropRef.current)
|
|
48
|
+
return;
|
|
49
|
+
const target = location.current.dropTargets[0];
|
|
50
|
+
if (!target)
|
|
51
|
+
return;
|
|
52
|
+
const fromId = source.data.id;
|
|
53
|
+
const toId = target.data.id;
|
|
54
|
+
if (typeof fromId !== 'string' || typeof toId !== 'string' || fromId === toId)
|
|
55
|
+
return;
|
|
56
|
+
const edge = extractClosestEdge(target.data);
|
|
57
|
+
onRowDropRef.current(fromId, toId, edge === 'bottom' ? 'bottom' : 'top');
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}, [tableId]);
|
|
61
|
+
return _jsx("tbody", { className: classNames('ncua-table__body', className), children: children });
|
|
62
|
+
};
|
|
33
63
|
Body.displayName = 'Table.Body';
|
|
34
|
-
const Row = forwardRef(({ children, className, selected, status, ...rest },
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
64
|
+
const Row = forwardRef(({ children, className, selected, status, dragId, ...rest }, forwardedRef) => {
|
|
65
|
+
const { isDraggable, tableId } = useContext(TableDndContext);
|
|
66
|
+
const internalRef = useRef(null);
|
|
67
|
+
const [closestEdge, setClosestEdge] = useState(null);
|
|
68
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
69
|
+
const setRef = useCallback((el) => {
|
|
70
|
+
internalRef.current = el;
|
|
71
|
+
if (typeof forwardedRef === 'function') {
|
|
72
|
+
forwardedRef(el);
|
|
73
|
+
}
|
|
74
|
+
else if (forwardedRef) {
|
|
75
|
+
forwardedRef.current = el;
|
|
76
|
+
}
|
|
77
|
+
}, [forwardedRef]);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (!isDraggable || !dragId || !internalRef.current)
|
|
80
|
+
return;
|
|
81
|
+
return dropTargetForElements({
|
|
82
|
+
element: internalRef.current,
|
|
83
|
+
getData: ({ input, element }) => attachClosestEdge({ id: dragId, tableId }, { input, element, allowedEdges: ['top', 'bottom'] }),
|
|
84
|
+
onDragEnter: ({ self, source }) => {
|
|
85
|
+
if (source.data.id === dragId)
|
|
86
|
+
return;
|
|
87
|
+
const edge = extractClosestEdge(self.data);
|
|
88
|
+
setClosestEdge(edge === 'bottom' && internalRef.current?.nextElementSibling ? null : edge);
|
|
89
|
+
},
|
|
90
|
+
onDrag: ({ self, source }) => {
|
|
91
|
+
if (source.data.id === dragId)
|
|
92
|
+
return;
|
|
93
|
+
const edge = extractClosestEdge(self.data);
|
|
94
|
+
setClosestEdge(edge === 'bottom' && internalRef.current?.nextElementSibling ? null : edge);
|
|
95
|
+
},
|
|
96
|
+
onDragLeave: () => setClosestEdge(null),
|
|
97
|
+
onDrop: () => setClosestEdge(null),
|
|
98
|
+
});
|
|
99
|
+
}, [isDraggable, dragId, tableId]);
|
|
100
|
+
return (_jsx(RowDndContext.Provider, { value: { dragId, setIsDragging }, children: _jsx("tr", { ref: setRef, "data-draggable-id": dragId, className: classNames('ncua-table__row', className, {
|
|
101
|
+
'ncua-table__row--selected': selected,
|
|
102
|
+
'ncua-table__row--warning': status === 'warning',
|
|
103
|
+
'ncua-table__row--error': status === 'error',
|
|
104
|
+
'ncua-table__row--drag-over-top': closestEdge === 'top',
|
|
105
|
+
'ncua-table__row--drag-over-bottom': closestEdge === 'bottom',
|
|
106
|
+
'is-dragging': isDragging,
|
|
107
|
+
}), ...rest, children: children }) }));
|
|
108
|
+
});
|
|
39
109
|
Row.displayName = 'Table.Row';
|
|
110
|
+
const DragHeaderCell = ({ className, children }) => (_jsx("th", { className: classNames('ncua-table__header-cell', 'ncua-table__drag-header-cell', className), children: _jsxs("span", { className: "ncua-table__drag-cell-inner", children: [_jsx("span", { className: "ncua-table__drag-header-icon", "aria-hidden": "true", children: _jsx(DotsGrid02, { width: 16, height: 16 }) }), children] }) }));
|
|
111
|
+
DragHeaderCell.displayName = 'Table.DragHeaderCell';
|
|
112
|
+
const DragCell = ({ disabled, className, children }) => {
|
|
113
|
+
const { isDraggable, tableId } = useContext(TableDndContext);
|
|
114
|
+
const { dragId, setIsDragging } = useContext(RowDndContext);
|
|
115
|
+
const handleRef = useRef(null);
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (!isDraggable || !dragId || !handleRef.current || disabled)
|
|
118
|
+
return;
|
|
119
|
+
let overlay = null;
|
|
120
|
+
let removePointerMove = null;
|
|
121
|
+
let pendingPreview = null;
|
|
122
|
+
return makeDraggable({
|
|
123
|
+
element: handleRef.current,
|
|
124
|
+
getInitialData: () => ({ id: dragId, tableId }),
|
|
125
|
+
onGenerateDragPreview: ({ nativeSetDragImage, location }) => {
|
|
126
|
+
if (!handleRef.current)
|
|
127
|
+
return;
|
|
128
|
+
const rowEl = handleRef.current.closest('tr');
|
|
129
|
+
if (!rowEl)
|
|
130
|
+
return;
|
|
131
|
+
disableNativeDragPreview({ nativeSetDragImage });
|
|
132
|
+
const rowRect = rowEl.getBoundingClientRect();
|
|
133
|
+
const badgeHalf = PREVIEW_BADGE_SIZE / 2;
|
|
134
|
+
const offsetX = Math.round(location.initial.input.clientX - rowRect.left) + badgeHalf;
|
|
135
|
+
const offsetY = Math.round(location.initial.input.clientY - rowRect.top) + badgeHalf;
|
|
136
|
+
const isSelected = rowEl.classList.contains('ncua-table__row--selected');
|
|
137
|
+
const bodyEl = rowEl.closest('.ncua-table__body');
|
|
138
|
+
const selectedRows = isSelected && bodyEl ? Array.from(bodyEl.querySelectorAll('.ncua-table__row--selected')) : [];
|
|
139
|
+
pendingPreview = {
|
|
140
|
+
rows: selectedRows.length > 1 ? selectedRows : [rowEl],
|
|
141
|
+
rowRect,
|
|
142
|
+
offsetX,
|
|
143
|
+
offsetY,
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
onDragStart: ({ location }) => {
|
|
147
|
+
setIsDragging(true);
|
|
148
|
+
if (!pendingPreview)
|
|
149
|
+
return;
|
|
150
|
+
const { rows, rowRect, offsetX, offsetY } = pendingPreview;
|
|
151
|
+
overlay = buildDragPreview(rows, rowRect);
|
|
152
|
+
overlay.style.left = `${Math.round(location.initial.input.clientX) - offsetX}px`;
|
|
153
|
+
overlay.style.top = `${Math.round(location.initial.input.clientY) - offsetY}px`;
|
|
154
|
+
document.body.appendChild(overlay);
|
|
155
|
+
const onDragOver = (e) => {
|
|
156
|
+
if (!overlay)
|
|
157
|
+
return;
|
|
158
|
+
overlay.style.left = `${e.clientX - offsetX}px`;
|
|
159
|
+
overlay.style.top = `${e.clientY - offsetY}px`;
|
|
160
|
+
};
|
|
161
|
+
document.addEventListener('dragover', onDragOver);
|
|
162
|
+
removePointerMove = () => document.removeEventListener('dragover', onDragOver);
|
|
163
|
+
},
|
|
164
|
+
onDrop: () => {
|
|
165
|
+
setIsDragging(false);
|
|
166
|
+
removePointerMove?.();
|
|
167
|
+
removePointerMove = null;
|
|
168
|
+
overlay?.remove();
|
|
169
|
+
overlay = null;
|
|
170
|
+
pendingPreview = null;
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
}, [isDraggable, dragId, tableId, disabled, setIsDragging]);
|
|
174
|
+
return (_jsx("td", { className: classNames('ncua-table__drag-cell', className), children: _jsxs("span", { className: "ncua-table__drag-cell-inner", children: [isDraggable && (_jsx("button", { ref: handleRef, type: "button", className: "ncua-table__drag-handle", "aria-label": "\uD589 \uC21C\uC11C \uBCC0\uACBD", disabled: disabled, children: _jsx(DotsGrid02, {}) })), children] }) }));
|
|
175
|
+
};
|
|
176
|
+
DragCell.displayName = 'Table.DragCell';
|
|
40
177
|
const HeaderCell = forwardRef(({ children, className, sortDirection, onSort, width, minWidth, style, ...rest }, ref) => {
|
|
41
178
|
const isSortable = sortDirection !== undefined && onSort !== undefined;
|
|
42
179
|
const SortIcon = isSortable ? SORT_ICONS[sortDirection] : undefined;
|
|
@@ -64,9 +201,14 @@ const ColGroup = ({ widths, minWidths }) => {
|
|
|
64
201
|
return `${width}px`;
|
|
65
202
|
return width;
|
|
66
203
|
};
|
|
67
|
-
return (_jsx("colgroup", { children: widths.map((width, index) =>
|
|
68
|
-
|
|
69
|
-
|
|
204
|
+
return (_jsx("colgroup", { children: widths.map((width, index) => {
|
|
205
|
+
const colStyle = {
|
|
206
|
+
width: resolveColWidth(width),
|
|
207
|
+
minWidth: resolveColWidth(minWidths?.[index]),
|
|
208
|
+
};
|
|
209
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: colgroup columns never reorder or change
|
|
210
|
+
return _jsx("col", { style: colStyle }, index);
|
|
211
|
+
}) }));
|
|
70
212
|
};
|
|
71
213
|
ColGroup.displayName = 'Table.ColGroup';
|
|
72
214
|
const Empty = ({ colSpan, children }) => (_jsx("tr", { children: _jsx("td", { colSpan: colSpan, className: "ncua-table__empty", role: "status", "aria-live": "polite", children: children || '등록된 게시물이 없습니다.' }) }));
|
|
@@ -108,13 +250,17 @@ const sortChildren = (children) => {
|
|
|
108
250
|
// ──────────────────────────────────────────────
|
|
109
251
|
// Main Table component
|
|
110
252
|
// ──────────────────────────────────────────────
|
|
111
|
-
const TableComponent = forwardRef(({ type = 'horizontal', fixedHeader = false, maxHeight, hoverable = true, selectable = false, horizontalScroll = false, minWidth, children, className, ...rest }, ref) => {
|
|
253
|
+
const TableComponent = forwardRef(({ type = 'horizontal', fixedHeader = false, maxHeight, hoverable = true, selectable = false, horizontalScroll = false, minWidth, draggable = false, children, className, ...rest }, ref) => {
|
|
254
|
+
const tableIdRef = useRef(`ncua-table-${Math.random().toString(TABLE_DND_ID_RADIX).slice(TABLE_DND_ID_SLICE_START, TABLE_DND_ID_SLICE_END)}`);
|
|
255
|
+
const tableId = tableIdRef.current;
|
|
256
|
+
const effectiveDraggable = draggable && type === 'horizontal';
|
|
112
257
|
const tableClasses = classNames('ncua-table', className, {
|
|
113
258
|
'ncua-table--horizontal': type === 'horizontal',
|
|
114
259
|
'ncua-table--vertical': type === 'vertical',
|
|
115
260
|
'ncua-table--fixed-header': fixedHeader,
|
|
116
261
|
'ncua-table--hoverable': hoverable && type === 'horizontal',
|
|
117
262
|
'ncua-table--selectable': selectable,
|
|
263
|
+
'ncua-table--draggable': effectiveDraggable,
|
|
118
264
|
});
|
|
119
265
|
const { headerContent, colGroupContent, tableContent, footerContent, paginationContent } = sortChildren(children);
|
|
120
266
|
const scrollStyle = fixedHeader && maxHeight
|
|
@@ -148,12 +294,22 @@ const TableComponent = forwardRef(({ type = 'horizontal', fixedHeader = false, m
|
|
|
148
294
|
hScrollbarRef,
|
|
149
295
|
hThumbRef,
|
|
150
296
|
});
|
|
297
|
+
// fixedHeader 모드에서 드래그 시 자동 스크롤
|
|
298
|
+
useEffect(() => {
|
|
299
|
+
if (!effectiveDraggable || !fixedScrollEnabled || !scrollContainerRef.current)
|
|
300
|
+
return;
|
|
301
|
+
return autoScrollForElements({ element: scrollContainerRef.current });
|
|
302
|
+
}, [effectiveDraggable, fixedScrollEnabled]);
|
|
151
303
|
// <colgroup> + <thead> + <tbody> 묶음 — fixed-header 분기와 horizontalScroll 분기 모두에서 재사용
|
|
152
304
|
const renderTable = () => (_jsxs("table", { className: "ncua-table__table", role: "table", children: [colGroupContent, headerContent, tableContent] }));
|
|
153
305
|
// fixed-header 시 scroll-area + scrollbar 래핑, 아니면 <table> 그대로.
|
|
154
306
|
// withScrollbar=false 이면 scrollbar를 제외 — horizontalScroll 분기에서 scrollbar를
|
|
155
307
|
// h-scroll-container 형제 위치에 별도 렌더해 가로 스크롤 시 viewport 우측에 자연 고정.
|
|
156
308
|
const renderScrollableArea = (includeVerticalScrollbar = true) => fixedScrollEnabled ? (_jsxs("div", { ref: scrollAreaRef, className: "ncua-table__scroll-area", children: [_jsx("div", { ref: scrollContainerRef, className: "ncua-table__scroll-container", style: scrollStyle, children: renderTable() }), includeVerticalScrollbar && (_jsx("div", { ref: scrollbarRef, className: "ncua-table__scrollbar", "aria-hidden": "true", children: _jsx("div", { ref: thumbRef, className: "ncua-table__scrollbar-thumb", onMouseDown: handleThumbMouseDown }) }))] })) : (renderTable());
|
|
309
|
+
const dndContextValue = {
|
|
310
|
+
isDraggable: effectiveDraggable,
|
|
311
|
+
tableId,
|
|
312
|
+
};
|
|
157
313
|
// horizontalScroll=true 시 외곽 wrapper + FloatingProvider 부착.
|
|
158
314
|
// 핵심 — __h-scroll-container 는 <table>(또는 scroll-area) 만 감싸고, footer/pagination 은
|
|
159
315
|
// 그 바깥에서 항상 고정 위치. 세로 스크롤바는 h-scroll-container 형제로 배치되어
|
|
@@ -165,9 +321,9 @@ const TableComponent = forwardRef(({ type = 'horizontal', fixedHeader = false, m
|
|
|
165
321
|
const innerStyle = {
|
|
166
322
|
'--ncua-table-min-width': typeof resolvedMinWidth === 'number' ? `${resolvedMinWidth}px` : resolvedMinWidth,
|
|
167
323
|
};
|
|
168
|
-
return (_jsx(FloatingProvider, { value: FLOATING_PORTAL_VALUE, children: _jsxs("div", { ref: ref, className: "ncua-table-wrapper", style: WRAPPER_STYLE, children: [_jsxs("div", { className: tableClasses, ...rest, children: [_jsxs("div", { ref: hScrollContainerRef, className: "ncua-table__h-scroll-container", children: [_jsx("div", { className: "ncua-table__h-scroll-inner", style: innerStyle, children: renderScrollableArea(false) }), _jsx("div", { ref: hScrollbarRef, className: "ncua-table__h-scrollbar", "aria-hidden": "true", children: _jsx("div", { ref: hThumbRef, className: "ncua-table__h-scrollbar-thumb", onMouseDown: handleHThumbMouseDown }) })] }), fixedScrollEnabled && (_jsx("div", { ref: scrollbarRef, className: "ncua-table__scrollbar", "aria-hidden": "true", children: _jsx("div", { ref: thumbRef, className: "ncua-table__scrollbar-thumb", onMouseDown: handleThumbMouseDown }) })), footerContent] }), paginationContent] }) }));
|
|
324
|
+
return (_jsx(TableDndContext.Provider, { value: dndContextValue, children: _jsx(FloatingProvider, { value: FLOATING_PORTAL_VALUE, children: _jsxs("div", { ref: ref, className: "ncua-table-wrapper", style: WRAPPER_STYLE, children: [_jsxs("div", { className: tableClasses, ...rest, children: [_jsxs("div", { ref: hScrollContainerRef, className: "ncua-table__h-scroll-container", children: [_jsx("div", { className: "ncua-table__h-scroll-inner", style: innerStyle, children: renderScrollableArea(false) }), _jsx("div", { ref: hScrollbarRef, className: "ncua-table__h-scrollbar", "aria-hidden": "true", children: _jsx("div", { ref: hThumbRef, className: "ncua-table__h-scrollbar-thumb", onMouseDown: handleHThumbMouseDown }) })] }), fixedScrollEnabled && (_jsx("div", { ref: scrollbarRef, className: "ncua-table__scrollbar", "aria-hidden": "true", children: _jsx("div", { ref: thumbRef, className: "ncua-table__scrollbar-thumb", onMouseDown: handleThumbMouseDown }) })), footerContent] }), paginationContent] }) }) }));
|
|
169
325
|
}
|
|
170
|
-
return (_jsxs("div", { ref: ref, className: "ncua-table-wrapper", style: WRAPPER_STYLE, children: [_jsxs("div", { className: tableClasses, ...rest, children: [renderScrollableArea(), footerContent] }), paginationContent] }));
|
|
326
|
+
return (_jsx(TableDndContext.Provider, { value: dndContextValue, children: _jsxs("div", { ref: ref, className: "ncua-table-wrapper", style: WRAPPER_STYLE, children: [_jsxs("div", { className: tableClasses, ...rest, children: [renderScrollableArea(), footerContent] }), paginationContent] }) }));
|
|
171
327
|
});
|
|
172
328
|
TableComponent.displayName = 'Table';
|
|
173
329
|
// ──────────────────────────────────────────────
|
|
@@ -177,6 +333,8 @@ export const Table = Object.assign(TableComponent, {
|
|
|
177
333
|
Header,
|
|
178
334
|
Body,
|
|
179
335
|
Row,
|
|
336
|
+
DragHeaderCell,
|
|
337
|
+
DragCell,
|
|
180
338
|
HeaderCell,
|
|
181
339
|
Cell,
|
|
182
340
|
Footer,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type TableDndContextValue = {
|
|
2
|
+
isDraggable: boolean;
|
|
3
|
+
tableId: string;
|
|
4
|
+
};
|
|
5
|
+
declare const TableDndContext: import("react").Context<TableDndContextValue>;
|
|
6
|
+
type RowDndContextValue = {
|
|
7
|
+
dragId: string | undefined;
|
|
8
|
+
setIsDragging: (v: boolean) => void;
|
|
9
|
+
};
|
|
10
|
+
declare const RowDndContext: import("react").Context<RowDndContextValue>;
|
|
11
|
+
export type { TableDndContextValue, RowDndContextValue };
|
|
12
|
+
export { TableDndContext, RowDndContext };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
const TableDndContext = createContext({
|
|
3
|
+
isDraggable: false,
|
|
4
|
+
tableId: '',
|
|
5
|
+
});
|
|
6
|
+
const RowDndContext = createContext({
|
|
7
|
+
dragId: undefined,
|
|
8
|
+
setIsDragging: (_v) => undefined,
|
|
9
|
+
});
|
|
10
|
+
export { TableDndContext, RowDndContext };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const TABLE_DND_ID_RADIX = 36;
|
|
2
|
+
declare const TABLE_DND_ID_SLICE_START = 2;
|
|
3
|
+
declare const TABLE_DND_ID_SLICE_END = 9;
|
|
4
|
+
declare const PREVIEW_BADGE_SIZE = 24;
|
|
5
|
+
declare const buildDragPreview: (rows: HTMLElement[], rowRect: DOMRect) => HTMLDivElement;
|
|
6
|
+
export { TABLE_DND_ID_RADIX, TABLE_DND_ID_SLICE_START, TABLE_DND_ID_SLICE_END, PREVIEW_BADGE_SIZE, buildDragPreview };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
const TABLE_DND_ID_RADIX = 36;
|
|
2
|
+
const TABLE_DND_ID_SLICE_START = 2;
|
|
3
|
+
const TABLE_DND_ID_SLICE_END = 9;
|
|
4
|
+
const PREVIEW_MAX_ROWS = 3;
|
|
5
|
+
const PREVIEW_STACK_OFFSET = 5;
|
|
6
|
+
const PREVIEW_MAX_STACK_OFFSET = PREVIEW_STACK_OFFSET * PREVIEW_MAX_ROWS;
|
|
7
|
+
const PREVIEW_BADGE_SIZE = 24;
|
|
8
|
+
const PREVIEW_BADGE_HALF = PREVIEW_BADGE_SIZE / 2;
|
|
9
|
+
// hover의 color-mix 반투명 배경을 우회해 불투명 RGB 배경색을 클래스 기반으로 직접 결정
|
|
10
|
+
const getRowBackground = (rowEl) => {
|
|
11
|
+
const resolveCssVar = (name) => getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
12
|
+
const isSelected = rowEl.classList.contains('ncua-table__row--selected');
|
|
13
|
+
const isError = rowEl.classList.contains('ncua-table__row--error');
|
|
14
|
+
const isWarning = rowEl.classList.contains('ncua-table__row--warning');
|
|
15
|
+
if (isSelected && isError)
|
|
16
|
+
return resolveCssVar('--primary-red-50');
|
|
17
|
+
if (isSelected && isWarning)
|
|
18
|
+
return resolveCssVar('--orange-50');
|
|
19
|
+
if (isSelected)
|
|
20
|
+
return resolveCssVar('--gray-50');
|
|
21
|
+
return resolveCssVar('--base-white');
|
|
22
|
+
};
|
|
23
|
+
// cloneNode는 HTML attribute만 복사하므로 checkbox.checked를 직접 동기화
|
|
24
|
+
const cloneRowWithState = (sourceRow) => {
|
|
25
|
+
const clone = sourceRow.cloneNode(true);
|
|
26
|
+
const srcInputs = sourceRow.querySelectorAll('input[type="checkbox"]');
|
|
27
|
+
const clnInputs = clone.querySelectorAll('input[type="checkbox"]');
|
|
28
|
+
srcInputs.forEach((src, i) => {
|
|
29
|
+
const cln = clnInputs[i];
|
|
30
|
+
if (cln)
|
|
31
|
+
cln.checked = src.checked;
|
|
32
|
+
});
|
|
33
|
+
clone.style.backgroundColor = getRowBackground(sourceRow);
|
|
34
|
+
// 열 너비는 테이블 레이아웃 컨텍스트에서 결정되므로 직접 복사 — ceil로 올림해 프리뷰 셀이 실제보다 좁아지지 않게 함
|
|
35
|
+
const srcCells = Array.from(sourceRow.querySelectorAll('td, th'));
|
|
36
|
+
const clnCells = Array.from(clone.querySelectorAll('td, th'));
|
|
37
|
+
srcCells.forEach((src, i) => {
|
|
38
|
+
const cln = clnCells[i];
|
|
39
|
+
if (!cln)
|
|
40
|
+
return;
|
|
41
|
+
const w = `${Math.ceil(src.getBoundingClientRect().width)}px`;
|
|
42
|
+
cln.style.width = w;
|
|
43
|
+
cln.style.minWidth = w;
|
|
44
|
+
cln.style.maxWidth = w;
|
|
45
|
+
});
|
|
46
|
+
return clone;
|
|
47
|
+
};
|
|
48
|
+
const buildCountBadge = (count) => {
|
|
49
|
+
const badge = document.createElement('div');
|
|
50
|
+
badge.className = 'ncua-table-dnd-preview__badge';
|
|
51
|
+
badge.textContent = String(count);
|
|
52
|
+
return badge;
|
|
53
|
+
};
|
|
54
|
+
const buildSummaryCard = (rowRect) => {
|
|
55
|
+
const wrapper = document.createElement('div');
|
|
56
|
+
wrapper.className = 'ncua-table-dnd-preview__summary';
|
|
57
|
+
Object.assign(wrapper.style, {
|
|
58
|
+
top: `${Math.round(PREVIEW_BADGE_HALF + PREVIEW_MAX_STACK_OFFSET)}px`,
|
|
59
|
+
left: `${Math.round(PREVIEW_BADGE_HALF + PREVIEW_MAX_STACK_OFFSET)}px`,
|
|
60
|
+
width: `${Math.round(rowRect.width) - PREVIEW_MAX_STACK_OFFSET}px`,
|
|
61
|
+
height: `${Math.round(rowRect.height)}px`,
|
|
62
|
+
});
|
|
63
|
+
return wrapper;
|
|
64
|
+
};
|
|
65
|
+
const buildRowCard = ({ row, cardLeft, cardTop, cardWidth, rowHeight, zIndex, parentTable, }) => {
|
|
66
|
+
const wrapper = document.createElement('div');
|
|
67
|
+
wrapper.className = 'ncua-table-dnd-preview__card';
|
|
68
|
+
Object.assign(wrapper.style, {
|
|
69
|
+
zIndex: String(zIndex),
|
|
70
|
+
top: `${cardTop}px`,
|
|
71
|
+
left: `${cardLeft}px`,
|
|
72
|
+
width: `${cardWidth}px`,
|
|
73
|
+
height: `${rowHeight}px`,
|
|
74
|
+
backgroundColor: getRowBackground(row),
|
|
75
|
+
});
|
|
76
|
+
const table = document.createElement('table');
|
|
77
|
+
if (parentTable)
|
|
78
|
+
table.className = parentTable.className;
|
|
79
|
+
table.style.width = `${cardWidth}px`;
|
|
80
|
+
const tbody = document.createElement('tbody');
|
|
81
|
+
tbody.className = 'ncua-table__body';
|
|
82
|
+
tbody.appendChild(cloneRowWithState(row));
|
|
83
|
+
table.appendChild(tbody);
|
|
84
|
+
wrapper.appendChild(table);
|
|
85
|
+
return wrapper;
|
|
86
|
+
};
|
|
87
|
+
const buildDragPreview = (rows, rowRect) => {
|
|
88
|
+
const visibleCount = Math.min(rows.length, PREVIEW_MAX_ROWS);
|
|
89
|
+
const hasSummary = rows.length > visibleCount;
|
|
90
|
+
const totalCards = visibleCount + (hasSummary ? 1 : 0);
|
|
91
|
+
const isMulti = rows.length > 1;
|
|
92
|
+
const parentTable = rows[0]?.closest('table') ?? null;
|
|
93
|
+
const rowWidth = Math.round(rowRect.width);
|
|
94
|
+
const rowHeight = Math.round(rowRect.height);
|
|
95
|
+
const container = document.createElement('div');
|
|
96
|
+
container.className = 'ncua-table-dnd-preview';
|
|
97
|
+
Object.assign(container.style, {
|
|
98
|
+
width: `${PREVIEW_BADGE_HALF + rowWidth}px`,
|
|
99
|
+
height: `${PREVIEW_BADGE_HALF + rowHeight + PREVIEW_STACK_OFFSET * (totalCards - 1)}px`,
|
|
100
|
+
});
|
|
101
|
+
if (isMulti)
|
|
102
|
+
container.appendChild(buildCountBadge(rows.length));
|
|
103
|
+
if (hasSummary)
|
|
104
|
+
container.appendChild(buildSummaryCard(rowRect));
|
|
105
|
+
// 뒤쪽 행 카드부터 렌더해서 앞쪽이 위로 올라오게
|
|
106
|
+
for (let i = visibleCount - 1; i >= 0; i--) {
|
|
107
|
+
const stackShift = isMulti ? i * PREVIEW_STACK_OFFSET : 0;
|
|
108
|
+
container.appendChild(buildRowCard({
|
|
109
|
+
row: rows[i],
|
|
110
|
+
cardLeft: Math.round(PREVIEW_BADGE_HALF + stackShift),
|
|
111
|
+
cardTop: Math.round(PREVIEW_BADGE_HALF + stackShift),
|
|
112
|
+
cardWidth: rowWidth - stackShift,
|
|
113
|
+
rowHeight,
|
|
114
|
+
zIndex: visibleCount - i,
|
|
115
|
+
parentTable,
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
return container;
|
|
119
|
+
};
|
|
120
|
+
export { TABLE_DND_ID_RADIX, TABLE_DND_ID_SLICE_START, TABLE_DND_ID_SLICE_END, PREVIEW_BADGE_SIZE, buildDragPreview };
|
|
@@ -2,7 +2,7 @@ import type { ComponentProps, ReactNode } from 'react';
|
|
|
2
2
|
export type TableType = 'horizontal' | 'vertical';
|
|
3
3
|
export type SortDirection = 'asc' | 'desc' | 'none';
|
|
4
4
|
export type RowStatus = 'warning' | 'error';
|
|
5
|
-
export type TableProps = Omit<ComponentProps<'div'>, 'ref'> & {
|
|
5
|
+
export type TableProps = Omit<ComponentProps<'div'>, 'ref' | 'draggable'> & {
|
|
6
6
|
type?: TableType;
|
|
7
7
|
fixedHeader?: boolean;
|
|
8
8
|
maxHeight?: string | number;
|
|
@@ -19,6 +19,11 @@ export type TableProps = Omit<ComponentProps<'div'>, 'ref'> & {
|
|
|
19
19
|
* 기본값은 1140 (14인치 모니터 + LNB 기준 디자인 권장 너비).
|
|
20
20
|
*/
|
|
21
21
|
minWidth?: string | number;
|
|
22
|
+
/**
|
|
23
|
+
* 행 드래그앤드롭 활성화. Table.Row에 dragId, Table.Body에 onRowDrop,
|
|
24
|
+
* 헤더에 Table.DragHeaderCell, 각 행에 Table.DragCell을 함께 사용한다.
|
|
25
|
+
*/
|
|
26
|
+
draggable?: boolean;
|
|
22
27
|
children: ReactNode;
|
|
23
28
|
};
|
|
24
29
|
export type TableHeaderProps = {
|
|
@@ -28,10 +33,28 @@ export type TableHeaderProps = {
|
|
|
28
33
|
export type TableBodyProps = {
|
|
29
34
|
children: ReactNode;
|
|
30
35
|
className?: string;
|
|
36
|
+
/**
|
|
37
|
+
* draggable=true 테이블에서 행이 재정렬될 때 호출된다.
|
|
38
|
+
* fromId → toId 로 이동, edge는 toId 행의 위(top)/아래(bottom) 삽입 위치.
|
|
39
|
+
*/
|
|
40
|
+
onRowDrop?: (fromId: string, toId: string, edge: 'top' | 'bottom') => void;
|
|
31
41
|
};
|
|
32
42
|
export type TableRowProps = Omit<ComponentProps<'tr'>, 'ref'> & {
|
|
33
43
|
selected?: boolean;
|
|
34
44
|
status?: RowStatus;
|
|
45
|
+
/** 드래그앤드롭 식별자. draggable 테이블에서 필수. */
|
|
46
|
+
dragId?: string;
|
|
47
|
+
};
|
|
48
|
+
export type TableDragCellProps = {
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
className?: string;
|
|
51
|
+
/** 드래그 셀에 함께 배치할 콘텐츠 (예: CheckboxInput). 아이콘 우측 8px gap으로 배치된다. */
|
|
52
|
+
children?: ReactNode;
|
|
53
|
+
};
|
|
54
|
+
export type TableDragHeaderCellProps = {
|
|
55
|
+
className?: string;
|
|
56
|
+
/** 헤더 드래그 셀에 함께 배치할 콘텐츠 (예: 전체선택 CheckboxInput). 아이콘 우측 8px gap으로 배치된다. */
|
|
57
|
+
children?: ReactNode;
|
|
35
58
|
};
|
|
36
59
|
export type TableHeaderCellProps = Omit<ComponentProps<'th'>, 'ref'> & {
|
|
37
60
|
sortDirection?: SortDirection;
|
|
@@ -36,6 +36,11 @@ export type DataGridTableProps = {
|
|
|
36
36
|
horizontalScroll?: boolean;
|
|
37
37
|
/** 가로 스크롤 트리거 임계 너비. horizontalScroll=true 일 때만 의미가 있다. */
|
|
38
38
|
minWidth?: string | number;
|
|
39
|
+
/**
|
|
40
|
+
* 행 드래그앤드롭 활성화. Table.Row에 dragId, Table.Body에 onRowDrop,
|
|
41
|
+
* 헤더에 Table.DragHeaderCell, 각 행에 Table.DragCell을 함께 사용한다.
|
|
42
|
+
*/
|
|
43
|
+
draggable?: boolean;
|
|
39
44
|
};
|
|
40
45
|
export type DataGridPaginationProps = ComponentProps<'div'> & {
|
|
41
46
|
children: ReactNode;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
-
import type { SortDirection, TableBodyProps, TableColGroupProps, TableEmptyProps, TableFooterProps, TableHeaderProps, TablePaginationProps } from './types';
|
|
3
|
-
export declare const Table: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
|
2
|
+
import type { SortDirection, TableBodyProps, TableColGroupProps, TableDragCellProps, TableDragHeaderCellProps, TableEmptyProps, TableFooterProps, TableHeaderProps, TablePaginationProps } from './types';
|
|
3
|
+
export declare const Table: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "draggable" | "ref"> & {
|
|
4
4
|
type?: import("./types").TableType | undefined;
|
|
5
5
|
fixedHeader?: boolean | undefined;
|
|
6
6
|
maxHeight?: string | number | undefined;
|
|
@@ -8,6 +8,7 @@ export declare const Table: import("react").ForwardRefExoticComponent<Omit<impor
|
|
|
8
8
|
selectable?: boolean | undefined;
|
|
9
9
|
horizontalScroll?: boolean | undefined;
|
|
10
10
|
minWidth?: string | number | undefined;
|
|
11
|
+
draggable?: boolean | undefined;
|
|
11
12
|
children: ReactNode;
|
|
12
13
|
} & import("react").RefAttributes<HTMLDivElement>> & {
|
|
13
14
|
Header: {
|
|
@@ -15,13 +16,22 @@ export declare const Table: import("react").ForwardRefExoticComponent<Omit<impor
|
|
|
15
16
|
displayName: string;
|
|
16
17
|
};
|
|
17
18
|
Body: {
|
|
18
|
-
({ children, className }: TableBodyProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
({ children, className, onRowDrop }: TableBodyProps): import("react/jsx-runtime").JSX.Element;
|
|
19
20
|
displayName: string;
|
|
20
21
|
};
|
|
21
22
|
Row: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLTableRowElement>, HTMLTableRowElement>, "ref"> & {
|
|
22
23
|
selected?: boolean | undefined;
|
|
23
24
|
status?: import("./types").RowStatus | undefined;
|
|
25
|
+
dragId?: string | undefined;
|
|
24
26
|
} & import("react").RefAttributes<HTMLTableRowElement>>;
|
|
27
|
+
DragHeaderCell: {
|
|
28
|
+
({ className, children }: TableDragHeaderCellProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
displayName: string;
|
|
30
|
+
};
|
|
31
|
+
DragCell: {
|
|
32
|
+
({ disabled, className, children }: TableDragCellProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
displayName: string;
|
|
34
|
+
};
|
|
25
35
|
HeaderCell: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ThHTMLAttributes<HTMLTableHeaderCellElement>, HTMLTableHeaderCellElement>, "ref"> & {
|
|
26
36
|
sortDirection?: SortDirection | undefined;
|
|
27
37
|
onSort?: (() => void) | undefined;
|
|
@@ -48,4 +58,4 @@ export declare const Table: import("react").ForwardRefExoticComponent<Omit<impor
|
|
|
48
58
|
displayName: string;
|
|
49
59
|
};
|
|
50
60
|
};
|
|
51
|
-
export type { RowStatus, SortDirection, TableBodyProps, TableCellProps, TableColGroupProps, TableEmptyProps, TableFooterProps, TableHeaderCellProps, TableHeaderProps, TablePaginationProps, TableProps, TableRowProps, TableType, } from './types';
|
|
61
|
+
export type { RowStatus, SortDirection, TableBodyProps, TableCellProps, TableColGroupProps, TableDragCellProps, TableDragHeaderCellProps, TableEmptyProps, TableFooterProps, TableHeaderCellProps, TableHeaderProps, TablePaginationProps, TableProps, TableRowProps, TableType, } from './types';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type TableDndContextValue = {
|
|
2
|
+
isDraggable: boolean;
|
|
3
|
+
tableId: string;
|
|
4
|
+
};
|
|
5
|
+
declare const TableDndContext: import("react").Context<TableDndContextValue>;
|
|
6
|
+
type RowDndContextValue = {
|
|
7
|
+
dragId: string | undefined;
|
|
8
|
+
setIsDragging: (v: boolean) => void;
|
|
9
|
+
};
|
|
10
|
+
declare const RowDndContext: import("react").Context<RowDndContextValue>;
|
|
11
|
+
export type { TableDndContextValue, RowDndContextValue };
|
|
12
|
+
export { TableDndContext, RowDndContext };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const TABLE_DND_ID_RADIX = 36;
|
|
2
|
+
declare const TABLE_DND_ID_SLICE_START = 2;
|
|
3
|
+
declare const TABLE_DND_ID_SLICE_END = 9;
|
|
4
|
+
declare const PREVIEW_BADGE_SIZE = 24;
|
|
5
|
+
declare const buildDragPreview: (rows: HTMLElement[], rowRect: DOMRect) => HTMLDivElement;
|
|
6
|
+
export { TABLE_DND_ID_RADIX, TABLE_DND_ID_SLICE_START, TABLE_DND_ID_SLICE_END, PREVIEW_BADGE_SIZE, buildDragPreview };
|