@ncds/ui-admin 1.8.0 → 1.8.1

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.
@@ -147,6 +147,7 @@ const ComboBox = exports.ComboBox = /*#__PURE__*/(0, _react.forwardRef)((_ref, r
147
147
  (0, _react.useImperativeHandle)(ref, () => internalRef.current, []);
148
148
  const trailingElement = {
149
149
  type: 'custom',
150
+ placement: 'inside',
150
151
  children: (0, _jsxRuntime.jsx)("div", {
151
152
  className: "ncua-input__icon-wrap ncua-input__right-icon",
152
153
  onClick: showAllItem,
@@ -10,6 +10,11 @@ var _classnames = _interopRequireDefault(require("classnames"));
10
10
  var _react = require("react");
11
11
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
12
  // ──────────────────────────────────────────────
13
+ // $table-header-height 와 동기화 — sticky thead가 차지하는 높이를 maxHeight에 보상
14
+ const TABLE_HEADER_HEIGHT = 40;
15
+ // 스크롤바 트랙 상하 여백 합계 (top 8px + bottom 8px) — SCSS &--fixed-header &__scrollbar 오프셋과 동기화
16
+ const SCROLLBAR_TRACK_OFFSET = 16;
17
+ const SCROLLBAR_THUMB_MIN_HEIGHT = 40;
13
18
  // Sort Icons (@ncds/ui-admin-icon)
14
19
  // ──────────────────────────────────────────────
15
20
  const SORT_ICONS = {
@@ -111,8 +116,18 @@ const Cell = /*#__PURE__*/(0, _react.forwardRef)((_ref5, ref) => {
111
116
  let {
112
117
  children,
113
118
  className,
119
+ isHeader,
114
120
  ...rest
115
121
  } = _ref5;
122
+ if (isHeader) {
123
+ return (0, _jsxRuntime.jsx)("th", {
124
+ ref: ref,
125
+ scope: "row",
126
+ className: (0, _classnames.default)('ncua-table__cell', className),
127
+ ...rest,
128
+ children: children
129
+ });
130
+ }
116
131
  return (0, _jsxRuntime.jsx)("td", {
117
132
  ref: ref,
118
133
  className: (0, _classnames.default)('ncua-table__cell', className),
@@ -153,14 +168,13 @@ const ColGroup = _ref8 => {
153
168
  return width;
154
169
  };
155
170
  return (0, _jsxRuntime.jsx)("colgroup", {
156
- children: widths.map((width, index) => {
157
- const duplicateCount = widths.slice(0, index).filter(v => v === width).length;
158
- return (0, _jsxRuntime.jsx)("col", {
159
- style: {
160
- width: resolveColWidth(width)
161
- }
162
- }, `col-${width}-${duplicateCount}`);
163
- })
171
+ children: widths.map((width, index) =>
172
+ // biome-ignore lint/suspicious/noArrayIndexKey: colgroup columns never reorder or change
173
+ (0, _jsxRuntime.jsx)("col", {
174
+ style: {
175
+ width: resolveColWidth(width)
176
+ }
177
+ }, index))
164
178
  });
165
179
  };
166
180
  ColGroup.displayName = 'Table.ColGroup';
@@ -189,12 +203,18 @@ const categorizeChild = (child, result) => {
189
203
  result.footerContent.push(child);
190
204
  } else if (child.type === Pagination) {
191
205
  result.paginationContent.push(child);
206
+ } else if (child.type === Header) {
207
+ result.headerContent.push(child);
208
+ } else if (child.type === ColGroup) {
209
+ result.colGroupContent.push(child);
192
210
  } else {
193
211
  result.tableContent.push(child);
194
212
  }
195
213
  };
196
214
  const sortChildren = children => {
197
215
  const result = {
216
+ headerContent: [],
217
+ colGroupContent: [],
198
218
  tableContent: [],
199
219
  footerContent: [],
200
220
  paginationContent: []
@@ -226,17 +246,113 @@ const TableComponent = /*#__PURE__*/(0, _react.forwardRef)((_ref0, ref) => {
226
246
  'ncua-table--selectable': selectable
227
247
  });
228
248
  const {
249
+ headerContent,
250
+ colGroupContent,
229
251
  tableContent,
230
252
  footerContent,
231
253
  paginationContent
232
254
  } = sortChildren(children);
233
255
  const scrollStyle = fixedHeader && maxHeight ? {
234
- maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight
256
+ maxHeight: typeof maxHeight === 'number' ? `${maxHeight + TABLE_HEADER_HEIGHT}px` : `calc(${maxHeight} + ${TABLE_HEADER_HEIGHT}px)`
235
257
  } : undefined;
236
- const tableElement = (0, _jsxRuntime.jsx)("table", {
258
+ // Custom scrollbar refs (used only in fixed-header mode)
259
+ const scrollContainerRef = (0, _react.useRef)(null);
260
+ const scrollAreaRef = (0, _react.useRef)(null);
261
+ const thumbRef = (0, _react.useRef)(null);
262
+ (0, _react.useEffect)(() => {
263
+ if (!fixedHeader || !maxHeight) return;
264
+ const scrollEl = scrollContainerRef.current;
265
+ const thumbEl = thumbRef.current;
266
+ if (!scrollEl || !thumbEl) return;
267
+ const update = () => {
268
+ const {
269
+ scrollTop,
270
+ scrollHeight,
271
+ clientHeight
272
+ } = scrollEl;
273
+ if (scrollHeight <= clientHeight) {
274
+ thumbEl.style.height = '0';
275
+ return;
276
+ }
277
+ const trackHeight = (scrollAreaRef.current?.clientHeight ?? clientHeight) - TABLE_HEADER_HEIGHT - SCROLLBAR_TRACK_OFFSET;
278
+ const thumbHeight = Math.max(SCROLLBAR_THUMB_MIN_HEIGHT, clientHeight / scrollHeight * trackHeight);
279
+ const thumbTop = scrollTop / (scrollHeight - clientHeight) * (trackHeight - thumbHeight);
280
+ thumbEl.style.height = `${thumbHeight}px`;
281
+ thumbEl.style.transform = `translateY(${thumbTop}px)`;
282
+ };
283
+ scrollEl.addEventListener('scroll', update, {
284
+ passive: true
285
+ });
286
+ const observer = new ResizeObserver(update);
287
+ observer.observe(scrollEl);
288
+ update();
289
+ return () => {
290
+ scrollEl.removeEventListener('scroll', update);
291
+ observer.disconnect();
292
+ };
293
+ }, [fixedHeader, maxHeight]);
294
+ const handleThumbMouseDown = e => {
295
+ e.preventDefault();
296
+ const scrollEl = scrollContainerRef.current;
297
+ const thumbEl = thumbRef.current;
298
+ const areaEl = scrollAreaRef.current;
299
+ if (!scrollEl || !thumbEl) return;
300
+ areaEl?.setAttribute('data-dragging', '');
301
+ const startY = e.clientY;
302
+ const startScrollTop = scrollEl.scrollTop;
303
+ const {
304
+ scrollHeight,
305
+ clientHeight
306
+ } = scrollEl;
307
+ const thumbHeight = thumbEl.offsetHeight;
308
+ const scrollRatio = (scrollHeight - clientHeight) / (clientHeight - thumbHeight);
309
+ const onMove = ev => {
310
+ scrollEl.scrollTop = startScrollTop + (ev.clientY - startY) * scrollRatio;
311
+ };
312
+ const onUp = () => {
313
+ areaEl?.removeAttribute('data-dragging');
314
+ document.removeEventListener('mousemove', onMove);
315
+ document.removeEventListener('mouseup', onUp);
316
+ };
317
+ document.addEventListener('mousemove', onMove);
318
+ document.addEventListener('mouseup', onUp);
319
+ };
320
+ if (fixedHeader && maxHeight) {
321
+ return (0, _jsxRuntime.jsxs)("div", {
322
+ ref: ref,
323
+ className: "ncua-table-wrapper",
324
+ children: [(0, _jsxRuntime.jsxs)("div", {
325
+ className: tableClasses,
326
+ ...rest,
327
+ children: [(0, _jsxRuntime.jsxs)("div", {
328
+ ref: scrollAreaRef,
329
+ className: "ncua-table__scroll-area",
330
+ children: [(0, _jsxRuntime.jsx)("div", {
331
+ ref: scrollContainerRef,
332
+ className: "ncua-table__scroll-container",
333
+ style: scrollStyle,
334
+ children: (0, _jsxRuntime.jsxs)("table", {
335
+ className: "ncua-table__table",
336
+ role: "table",
337
+ children: [colGroupContent, headerContent, tableContent]
338
+ })
339
+ }), (0, _jsxRuntime.jsx)("div", {
340
+ className: "ncua-table__scrollbar",
341
+ "aria-hidden": "true",
342
+ children: (0, _jsxRuntime.jsx)("div", {
343
+ ref: thumbRef,
344
+ className: "ncua-table__scrollbar-thumb",
345
+ onMouseDown: handleThumbMouseDown
346
+ })
347
+ })]
348
+ }), footerContent]
349
+ }), paginationContent]
350
+ });
351
+ }
352
+ const tableElement = (0, _jsxRuntime.jsxs)("table", {
237
353
  className: "ncua-table__table",
238
354
  role: "table",
239
- children: tableContent
355
+ children: [colGroupContent, headerContent, tableContent]
240
356
  });
241
357
  return (0, _jsxRuntime.jsxs)("div", {
242
358
  ref: ref,
@@ -244,11 +360,7 @@ const TableComponent = /*#__PURE__*/(0, _react.forwardRef)((_ref0, ref) => {
244
360
  children: [(0, _jsxRuntime.jsxs)("div", {
245
361
  className: tableClasses,
246
362
  ...rest,
247
- children: [fixedHeader && maxHeight ? (0, _jsxRuntime.jsx)("div", {
248
- className: "ncua-table__scroll-container",
249
- style: scrollStyle,
250
- children: tableElement
251
- }) : tableElement, footerContent]
363
+ children: [tableElement, footerContent]
252
364
  }), paginationContent]
253
365
  });
254
366
  });
@@ -140,6 +140,7 @@ const ComboBox = /*#__PURE__*/forwardRef((_ref, ref) => {
140
140
  useImperativeHandle(ref, () => internalRef.current, []);
141
141
  const trailingElement = {
142
142
  type: 'custom',
143
+ placement: 'inside',
143
144
  children: _jsx("div", {
144
145
  className: "ncua-input__icon-wrap ncua-input__right-icon",
145
146
  onClick: showAllItem,
@@ -1,8 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ChevronDown, ChevronSelectorVertical, ChevronUp } from '@ncds/ui-admin-icon';
3
3
  import classNames from 'classnames';
4
- import { Children, forwardRef } from 'react';
4
+ import { Children, forwardRef, useEffect, useRef } from 'react';
5
5
  // ──────────────────────────────────────────────
6
+ // $table-header-height 와 동기화 — sticky thead가 차지하는 높이를 maxHeight에 보상
7
+ const TABLE_HEADER_HEIGHT = 40;
8
+ // 스크롤바 트랙 상하 여백 합계 (top 8px + bottom 8px) — SCSS &--fixed-header &__scrollbar 오프셋과 동기화
9
+ const SCROLLBAR_TRACK_OFFSET = 16;
10
+ const SCROLLBAR_THUMB_MIN_HEIGHT = 40;
6
11
  // Sort Icons (@ncds/ui-admin-icon)
7
12
  // ──────────────────────────────────────────────
8
13
  const SORT_ICONS = {
@@ -104,8 +109,18 @@ const Cell = /*#__PURE__*/forwardRef((_ref5, ref) => {
104
109
  let {
105
110
  children,
106
111
  className,
112
+ isHeader,
107
113
  ...rest
108
114
  } = _ref5;
115
+ if (isHeader) {
116
+ return _jsx("th", {
117
+ ref: ref,
118
+ scope: "row",
119
+ className: classNames('ncua-table__cell', className),
120
+ ...rest,
121
+ children: children
122
+ });
123
+ }
109
124
  return _jsx("td", {
110
125
  ref: ref,
111
126
  className: classNames('ncua-table__cell', className),
@@ -146,14 +161,13 @@ const ColGroup = _ref8 => {
146
161
  return width;
147
162
  };
148
163
  return _jsx("colgroup", {
149
- children: widths.map((width, index) => {
150
- const duplicateCount = widths.slice(0, index).filter(v => v === width).length;
151
- return _jsx("col", {
152
- style: {
153
- width: resolveColWidth(width)
154
- }
155
- }, `col-${width}-${duplicateCount}`);
156
- })
164
+ children: widths.map((width, index) =>
165
+ // biome-ignore lint/suspicious/noArrayIndexKey: colgroup columns never reorder or change
166
+ _jsx("col", {
167
+ style: {
168
+ width: resolveColWidth(width)
169
+ }
170
+ }, index))
157
171
  });
158
172
  };
159
173
  ColGroup.displayName = 'Table.ColGroup';
@@ -182,12 +196,18 @@ const categorizeChild = (child, result) => {
182
196
  result.footerContent.push(child);
183
197
  } else if (child.type === Pagination) {
184
198
  result.paginationContent.push(child);
199
+ } else if (child.type === Header) {
200
+ result.headerContent.push(child);
201
+ } else if (child.type === ColGroup) {
202
+ result.colGroupContent.push(child);
185
203
  } else {
186
204
  result.tableContent.push(child);
187
205
  }
188
206
  };
189
207
  const sortChildren = children => {
190
208
  const result = {
209
+ headerContent: [],
210
+ colGroupContent: [],
191
211
  tableContent: [],
192
212
  footerContent: [],
193
213
  paginationContent: []
@@ -219,17 +239,113 @@ const TableComponent = /*#__PURE__*/forwardRef((_ref0, ref) => {
219
239
  'ncua-table--selectable': selectable
220
240
  });
221
241
  const {
242
+ headerContent,
243
+ colGroupContent,
222
244
  tableContent,
223
245
  footerContent,
224
246
  paginationContent
225
247
  } = sortChildren(children);
226
248
  const scrollStyle = fixedHeader && maxHeight ? {
227
- maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight
249
+ maxHeight: typeof maxHeight === 'number' ? `${maxHeight + TABLE_HEADER_HEIGHT}px` : `calc(${maxHeight} + ${TABLE_HEADER_HEIGHT}px)`
228
250
  } : undefined;
229
- const tableElement = _jsx("table", {
251
+ // Custom scrollbar refs (used only in fixed-header mode)
252
+ const scrollContainerRef = useRef(null);
253
+ const scrollAreaRef = useRef(null);
254
+ const thumbRef = useRef(null);
255
+ useEffect(() => {
256
+ if (!fixedHeader || !maxHeight) return;
257
+ const scrollEl = scrollContainerRef.current;
258
+ const thumbEl = thumbRef.current;
259
+ if (!scrollEl || !thumbEl) return;
260
+ const update = () => {
261
+ const {
262
+ scrollTop,
263
+ scrollHeight,
264
+ clientHeight
265
+ } = scrollEl;
266
+ if (scrollHeight <= clientHeight) {
267
+ thumbEl.style.height = '0';
268
+ return;
269
+ }
270
+ const trackHeight = (scrollAreaRef.current?.clientHeight ?? clientHeight) - TABLE_HEADER_HEIGHT - SCROLLBAR_TRACK_OFFSET;
271
+ const thumbHeight = Math.max(SCROLLBAR_THUMB_MIN_HEIGHT, clientHeight / scrollHeight * trackHeight);
272
+ const thumbTop = scrollTop / (scrollHeight - clientHeight) * (trackHeight - thumbHeight);
273
+ thumbEl.style.height = `${thumbHeight}px`;
274
+ thumbEl.style.transform = `translateY(${thumbTop}px)`;
275
+ };
276
+ scrollEl.addEventListener('scroll', update, {
277
+ passive: true
278
+ });
279
+ const observer = new ResizeObserver(update);
280
+ observer.observe(scrollEl);
281
+ update();
282
+ return () => {
283
+ scrollEl.removeEventListener('scroll', update);
284
+ observer.disconnect();
285
+ };
286
+ }, [fixedHeader, maxHeight]);
287
+ const handleThumbMouseDown = e => {
288
+ e.preventDefault();
289
+ const scrollEl = scrollContainerRef.current;
290
+ const thumbEl = thumbRef.current;
291
+ const areaEl = scrollAreaRef.current;
292
+ if (!scrollEl || !thumbEl) return;
293
+ areaEl?.setAttribute('data-dragging', '');
294
+ const startY = e.clientY;
295
+ const startScrollTop = scrollEl.scrollTop;
296
+ const {
297
+ scrollHeight,
298
+ clientHeight
299
+ } = scrollEl;
300
+ const thumbHeight = thumbEl.offsetHeight;
301
+ const scrollRatio = (scrollHeight - clientHeight) / (clientHeight - thumbHeight);
302
+ const onMove = ev => {
303
+ scrollEl.scrollTop = startScrollTop + (ev.clientY - startY) * scrollRatio;
304
+ };
305
+ const onUp = () => {
306
+ areaEl?.removeAttribute('data-dragging');
307
+ document.removeEventListener('mousemove', onMove);
308
+ document.removeEventListener('mouseup', onUp);
309
+ };
310
+ document.addEventListener('mousemove', onMove);
311
+ document.addEventListener('mouseup', onUp);
312
+ };
313
+ if (fixedHeader && maxHeight) {
314
+ return _jsxs("div", {
315
+ ref: ref,
316
+ className: "ncua-table-wrapper",
317
+ children: [_jsxs("div", {
318
+ className: tableClasses,
319
+ ...rest,
320
+ children: [_jsxs("div", {
321
+ ref: scrollAreaRef,
322
+ className: "ncua-table__scroll-area",
323
+ children: [_jsx("div", {
324
+ ref: scrollContainerRef,
325
+ className: "ncua-table__scroll-container",
326
+ style: scrollStyle,
327
+ children: _jsxs("table", {
328
+ className: "ncua-table__table",
329
+ role: "table",
330
+ children: [colGroupContent, headerContent, tableContent]
331
+ })
332
+ }), _jsx("div", {
333
+ className: "ncua-table__scrollbar",
334
+ "aria-hidden": "true",
335
+ children: _jsx("div", {
336
+ ref: thumbRef,
337
+ className: "ncua-table__scrollbar-thumb",
338
+ onMouseDown: handleThumbMouseDown
339
+ })
340
+ })]
341
+ }), footerContent]
342
+ }), paginationContent]
343
+ });
344
+ }
345
+ const tableElement = _jsxs("table", {
230
346
  className: "ncua-table__table",
231
347
  role: "table",
232
- children: tableContent
348
+ children: [colGroupContent, headerContent, tableContent]
233
349
  });
234
350
  return _jsxs("div", {
235
351
  ref: ref,
@@ -237,11 +353,7 @@ const TableComponent = /*#__PURE__*/forwardRef((_ref0, ref) => {
237
353
  children: [_jsxs("div", {
238
354
  className: tableClasses,
239
355
  ...rest,
240
- children: [fixedHeader && maxHeight ? _jsx("div", {
241
- className: "ncua-table__scroll-container",
242
- style: scrollStyle,
243
- children: tableElement
244
- }) : tableElement, footerContent]
356
+ children: [tableElement, footerContent]
245
357
  }), paginationContent]
246
358
  });
247
359
  });
@@ -106,6 +106,7 @@ const ComboBox = forwardRef(({ placeholder = '검색하세요', id, className, h
106
106
  useImperativeHandle(ref, () => internalRef.current, []);
107
107
  const trailingElement = {
108
108
  type: 'custom',
109
+ placement: 'inside',
109
110
  children: (_jsx("div", { className: "ncua-input__icon-wrap ncua-input__right-icon", onClick: showAllItem, children: _jsx(Button, { label: "\uC804\uCCB4", hierarchy: "text", size: "xxs", leadingIcon: { type: 'icon', icon: ChevronSelectorVertical } }) })),
110
111
  };
111
112
  const leadingElement = {
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from 'react';
2
- import type { SortDirection, TableBodyProps, TableCellProps, TableColGroupProps, TableEmptyProps, TableFooterProps, TableHeaderProps, TablePaginationProps } from './types';
2
+ import type { SortDirection, TableBodyProps, TableColGroupProps, TableEmptyProps, TableFooterProps, TableHeaderProps, TablePaginationProps } from './types';
3
3
  export declare const Table: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
4
4
  type?: import("./types").TableType | undefined;
5
5
  fixedHeader?: boolean | undefined;
@@ -25,7 +25,9 @@ export declare const Table: import("react").ForwardRefExoticComponent<Omit<impor
25
25
  onSort?: (() => void) | undefined;
26
26
  width?: string | number | undefined;
27
27
  } & import("react").RefAttributes<HTMLTableCellElement>>;
28
- Cell: import("react").ForwardRefExoticComponent<TableCellProps & import("react").RefAttributes<HTMLTableCellElement>>;
28
+ Cell: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").TdHTMLAttributes<HTMLTableDataCellElement>, HTMLTableDataCellElement>, "ref"> & {
29
+ isHeader?: boolean | undefined;
30
+ } & import("react").RefAttributes<HTMLTableCellElement>>;
29
31
  Footer: {
30
32
  ({ children, className }: TableFooterProps): import("react/jsx-runtime").JSX.Element;
31
33
  displayName: string;
@@ -1,8 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ChevronDown, ChevronSelectorVertical, ChevronUp } from '@ncds/ui-admin-icon';
3
3
  import classNames from 'classnames';
4
- import { Children, forwardRef } from 'react';
4
+ import { Children, forwardRef, useEffect, useRef, } from 'react';
5
5
  // ──────────────────────────────────────────────
6
+ // $table-header-height 와 동기화 — sticky thead가 차지하는 높이를 maxHeight에 보상
7
+ const TABLE_HEADER_HEIGHT = 40;
8
+ // 스크롤바 트랙 상하 여백 합계 (top 8px + bottom 8px) — SCSS &--fixed-header &__scrollbar 오프셋과 동기화
9
+ const SCROLLBAR_TRACK_OFFSET = 16;
10
+ const SCROLLBAR_THUMB_MIN_HEIGHT = 40;
6
11
  // Sort Icons (@ncds/ui-admin-icon)
7
12
  // ──────────────────────────────────────────────
8
13
  const SORT_ICONS = {
@@ -36,7 +41,12 @@ const HeaderCell = forwardRef(({ children, className, sortDirection, onSort, wid
36
41
  }), style: { ...style, width }, "aria-sort": isSortable ? ARIA_SORT_MAP[sortDirection] : undefined, onClick: isSortable ? onSort : undefined, ...rest, children: isSortable && SortIcon ? (_jsxs("span", { className: "ncua-table__header-cell-inner", children: [_jsx("span", { className: "ncua-table__header-cell-text", children: children }), _jsx("span", { className: "ncua-table__sort-icon", children: _jsx(SortIcon, { width: 16, height: 16 }) })] })) : (children) }));
37
42
  });
38
43
  HeaderCell.displayName = 'Table.HeaderCell';
39
- const Cell = forwardRef(({ children, className, ...rest }, ref) => (_jsx("td", { ref: ref, className: classNames('ncua-table__cell', className), ...rest, children: children })));
44
+ const Cell = forwardRef(({ children, className, isHeader, ...rest }, ref) => {
45
+ if (isHeader) {
46
+ return (_jsx("th", { ref: ref, scope: "row", className: classNames('ncua-table__cell', className), ...rest, children: children }));
47
+ }
48
+ return (_jsx("td", { ref: ref, className: classNames('ncua-table__cell', className), ...rest, children: children }));
49
+ });
40
50
  Cell.displayName = 'Table.Cell';
41
51
  const Footer = ({ children, className }) => (_jsx("div", { className: classNames('ncua-table__footer', className), children: children }));
42
52
  Footer.displayName = 'Table.Footer';
@@ -50,10 +60,9 @@ const ColGroup = ({ widths }) => {
50
60
  return `${width}px`;
51
61
  return width;
52
62
  };
53
- return (_jsx("colgroup", { children: widths.map((width, index) => {
54
- const duplicateCount = widths.slice(0, index).filter((v) => v === width).length;
55
- return _jsx("col", { style: { width: resolveColWidth(width) } }, `col-${width}-${duplicateCount}`);
56
- }) }));
63
+ return (_jsx("colgroup", { children: widths.map((width, index) => (
64
+ // biome-ignore lint/suspicious/noArrayIndexKey: colgroup columns never reorder or change
65
+ _jsx("col", { style: { width: resolveColWidth(width) } }, index))) }));
57
66
  };
58
67
  ColGroup.displayName = 'Table.ColGroup';
59
68
  const Empty = ({ colSpan, children }) => (_jsx("tr", { children: _jsx("td", { colSpan: colSpan, className: "ncua-table__empty", role: "status", "aria-live": "polite", children: children || '등록된 게시물이 없습니다.' }) }));
@@ -69,12 +78,24 @@ const categorizeChild = (child, result) => {
69
78
  else if (child.type === Pagination) {
70
79
  result.paginationContent.push(child);
71
80
  }
81
+ else if (child.type === Header) {
82
+ result.headerContent.push(child);
83
+ }
84
+ else if (child.type === ColGroup) {
85
+ result.colGroupContent.push(child);
86
+ }
72
87
  else {
73
88
  result.tableContent.push(child);
74
89
  }
75
90
  };
76
91
  const sortChildren = (children) => {
77
- const result = { tableContent: [], footerContent: [], paginationContent: [] };
92
+ const result = {
93
+ headerContent: [],
94
+ colGroupContent: [],
95
+ tableContent: [],
96
+ footerContent: [],
97
+ paginationContent: [],
98
+ };
78
99
  Children.forEach(children, (child) => {
79
100
  categorizeChild(child, result);
80
101
  });
@@ -91,12 +112,75 @@ const TableComponent = forwardRef(({ type = 'horizontal', fixedHeader = false, m
91
112
  'ncua-table--hoverable': hoverable && type === 'horizontal',
92
113
  'ncua-table--selectable': selectable,
93
114
  });
94
- const { tableContent, footerContent, paginationContent } = sortChildren(children);
115
+ const { headerContent, colGroupContent, tableContent, footerContent, paginationContent } = sortChildren(children);
95
116
  const scrollStyle = fixedHeader && maxHeight
96
- ? { maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight }
117
+ ? {
118
+ maxHeight: typeof maxHeight === 'number'
119
+ ? `${maxHeight + TABLE_HEADER_HEIGHT}px`
120
+ : `calc(${maxHeight} + ${TABLE_HEADER_HEIGHT}px)`,
121
+ }
97
122
  : undefined;
98
- const tableElement = (_jsx("table", { className: "ncua-table__table", role: "table", children: tableContent }));
99
- return (_jsxs("div", { ref: ref, className: "ncua-table-wrapper", children: [_jsxs("div", { className: tableClasses, ...rest, children: [fixedHeader && maxHeight ? (_jsx("div", { className: "ncua-table__scroll-container", style: scrollStyle, children: tableElement })) : (tableElement), footerContent] }), paginationContent] }));
123
+ // Custom scrollbar refs (used only in fixed-header mode)
124
+ const scrollContainerRef = useRef(null);
125
+ const scrollAreaRef = useRef(null);
126
+ const thumbRef = useRef(null);
127
+ useEffect(() => {
128
+ if (!fixedHeader || !maxHeight)
129
+ return;
130
+ const scrollEl = scrollContainerRef.current;
131
+ const thumbEl = thumbRef.current;
132
+ if (!scrollEl || !thumbEl)
133
+ return;
134
+ const update = () => {
135
+ const { scrollTop, scrollHeight, clientHeight } = scrollEl;
136
+ if (scrollHeight <= clientHeight) {
137
+ thumbEl.style.height = '0';
138
+ return;
139
+ }
140
+ const trackHeight = (scrollAreaRef.current?.clientHeight ?? clientHeight) - TABLE_HEADER_HEIGHT - SCROLLBAR_TRACK_OFFSET;
141
+ const thumbHeight = Math.max(SCROLLBAR_THUMB_MIN_HEIGHT, (clientHeight / scrollHeight) * trackHeight);
142
+ const thumbTop = (scrollTop / (scrollHeight - clientHeight)) * (trackHeight - thumbHeight);
143
+ thumbEl.style.height = `${thumbHeight}px`;
144
+ thumbEl.style.transform = `translateY(${thumbTop}px)`;
145
+ };
146
+ scrollEl.addEventListener('scroll', update, { passive: true });
147
+ const observer = new ResizeObserver(update);
148
+ observer.observe(scrollEl);
149
+ update();
150
+ return () => {
151
+ scrollEl.removeEventListener('scroll', update);
152
+ observer.disconnect();
153
+ };
154
+ }, [fixedHeader, maxHeight]);
155
+ const handleThumbMouseDown = (e) => {
156
+ e.preventDefault();
157
+ const scrollEl = scrollContainerRef.current;
158
+ const thumbEl = thumbRef.current;
159
+ const areaEl = scrollAreaRef.current;
160
+ if (!scrollEl || !thumbEl)
161
+ return;
162
+ areaEl?.setAttribute('data-dragging', '');
163
+ const startY = e.clientY;
164
+ const startScrollTop = scrollEl.scrollTop;
165
+ const { scrollHeight, clientHeight } = scrollEl;
166
+ const thumbHeight = thumbEl.offsetHeight;
167
+ const scrollRatio = (scrollHeight - clientHeight) / (clientHeight - thumbHeight);
168
+ const onMove = (ev) => {
169
+ scrollEl.scrollTop = startScrollTop + (ev.clientY - startY) * scrollRatio;
170
+ };
171
+ const onUp = () => {
172
+ areaEl?.removeAttribute('data-dragging');
173
+ document.removeEventListener('mousemove', onMove);
174
+ document.removeEventListener('mouseup', onUp);
175
+ };
176
+ document.addEventListener('mousemove', onMove);
177
+ document.addEventListener('mouseup', onUp);
178
+ };
179
+ if (fixedHeader && maxHeight) {
180
+ return (_jsxs("div", { ref: ref, className: "ncua-table-wrapper", children: [_jsxs("div", { className: tableClasses, ...rest, children: [_jsxs("div", { ref: scrollAreaRef, className: "ncua-table__scroll-area", children: [_jsx("div", { ref: scrollContainerRef, className: "ncua-table__scroll-container", style: scrollStyle, children: _jsxs("table", { className: "ncua-table__table", role: "table", children: [colGroupContent, headerContent, tableContent] }) }), _jsx("div", { className: "ncua-table__scrollbar", "aria-hidden": "true", children: _jsx("div", { ref: thumbRef, className: "ncua-table__scrollbar-thumb", onMouseDown: handleThumbMouseDown }) })] }), footerContent] }), paginationContent] }));
181
+ }
182
+ const tableElement = (_jsxs("table", { className: "ncua-table__table", role: "table", children: [colGroupContent, headerContent, tableContent] }));
183
+ return (_jsxs("div", { ref: ref, className: "ncua-table-wrapper", children: [_jsxs("div", { className: tableClasses, ...rest, children: [tableElement, footerContent] }), paginationContent] }));
100
184
  });
101
185
  TableComponent.displayName = 'Table';
102
186
  // ──────────────────────────────────────────────
@@ -27,7 +27,9 @@ export type TableHeaderCellProps = Omit<ComponentProps<'th'>, 'ref'> & {
27
27
  onSort?: () => void;
28
28
  width?: string | number;
29
29
  };
30
- export type TableCellProps = Omit<ComponentProps<'td'>, 'ref'>;
30
+ export type TableCellProps = Omit<ComponentProps<'td'>, 'ref'> & {
31
+ isHeader?: boolean;
32
+ };
31
33
  export type TableFooterProps = {
32
34
  children: ReactNode;
33
35
  className?: string;
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from 'react';
2
- import type { SortDirection, TableBodyProps, TableCellProps, TableColGroupProps, TableEmptyProps, TableFooterProps, TableHeaderProps, TablePaginationProps } from './types';
2
+ import type { SortDirection, TableBodyProps, TableColGroupProps, TableEmptyProps, TableFooterProps, TableHeaderProps, TablePaginationProps } from './types';
3
3
  export declare const Table: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
4
4
  type?: import("./types").TableType | undefined;
5
5
  fixedHeader?: boolean | undefined;
@@ -25,7 +25,9 @@ export declare const Table: import("react").ForwardRefExoticComponent<Omit<impor
25
25
  onSort?: (() => void) | undefined;
26
26
  width?: string | number | undefined;
27
27
  } & import("react").RefAttributes<HTMLTableCellElement>>;
28
- Cell: import("react").ForwardRefExoticComponent<TableCellProps & import("react").RefAttributes<HTMLTableCellElement>>;
28
+ Cell: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").TdHTMLAttributes<HTMLTableDataCellElement>, HTMLTableDataCellElement>, "ref"> & {
29
+ isHeader?: boolean | undefined;
30
+ } & import("react").RefAttributes<HTMLTableCellElement>>;
29
31
  Footer: {
30
32
  ({ children, className }: TableFooterProps): import("react/jsx-runtime").JSX.Element;
31
33
  displayName: string;
@@ -27,7 +27,9 @@ export type TableHeaderCellProps = Omit<ComponentProps<'th'>, 'ref'> & {
27
27
  onSort?: () => void;
28
28
  width?: string | number;
29
29
  };
30
- export type TableCellProps = Omit<ComponentProps<'td'>, 'ref'>;
30
+ export type TableCellProps = Omit<ComponentProps<'td'>, 'ref'> & {
31
+ isHeader?: boolean;
32
+ };
31
33
  export type TableFooterProps = {
32
34
  children: ReactNode;
33
35
  className?: string;
@@ -960,6 +960,10 @@ button {
960
960
  .ncua-checkbox-input:has(input:disabled:checked)::before {
961
961
  background-image: var(--check-icon-disabled);
962
962
  }
963
+ .ncua-checkbox-input.has-indeterminate :where(input) {
964
+ border-color: var(--gray-700);
965
+ background-color: var(--gray-50);
966
+ }
963
967
  .ncua-checkbox-input.has-indeterminate::before {
964
968
  background-image: var(--indeterminate-icon);
965
969
  }
@@ -3523,8 +3527,17 @@ button {
3523
3527
  .ncua-pagination__before {
3524
3528
  margin-inline: 4px 8px;
3525
3529
  }
3530
+ .ncua-pagination__item {
3531
+ display: flex;
3532
+ align-items: center;
3533
+ height: 32px;
3534
+ margin: 0;
3535
+ padding: 0;
3536
+ list-style: none;
3537
+ }
3526
3538
  .ncua-pagination__item + .ncua-pagination__item {
3527
3539
  margin-inline-start: 4px;
3540
+ margin-top: 0;
3528
3541
  }
3529
3542
  .ncua-pagination__page-num {
3530
3543
  font-size: 14px;
@@ -5584,29 +5597,53 @@ button {
5584
5597
  box-shadow: var(--shadow-xs);
5585
5598
  overflow: hidden;
5586
5599
  }
5600
+ .ncua-table__scroll-area {
5601
+ position: relative;
5602
+ }
5603
+ .ncua-table__scroll-area:hover .ncua-table__scrollbar, .ncua-table__scroll-area[data-dragging] .ncua-table__scrollbar {
5604
+ opacity: 1;
5605
+ }
5587
5606
  .ncua-table__scroll-container {
5588
5607
  width: 100%;
5589
5608
  overflow-y: auto;
5609
+ scrollbar-width: none;
5590
5610
  }
5591
5611
  .ncua-table__scroll-container::-webkit-scrollbar {
5592
- width: 16px;
5612
+ display: none;
5593
5613
  }
5594
- .ncua-table__scroll-container::-webkit-scrollbar-track {
5595
- background: transparent;
5596
- padding: 4px;
5597
- margin-top: 40px;
5614
+ .ncua-table__scrollbar {
5615
+ position: absolute;
5616
+ top: 2px;
5617
+ right: 2px;
5618
+ bottom: 2px;
5619
+ width: 6px;
5620
+ opacity: 0;
5621
+ transition: opacity 0.2s ease;
5622
+ pointer-events: none;
5623
+ border-radius: 8px;
5598
5624
  }
5599
- .ncua-table__scroll-container::-webkit-scrollbar-thumb {
5600
- background: var(--gray-200);
5625
+ .ncua-table__scrollbar-thumb {
5626
+ position: absolute;
5627
+ top: 0;
5628
+ left: 0;
5629
+ right: 0;
5630
+ height: 40px;
5631
+ background: var(--gray-100);
5601
5632
  border-radius: 8px;
5602
- border: 5px solid transparent;
5603
- background-clip: padding-box;
5604
- min-height: 40px;
5633
+ cursor: pointer;
5634
+ pointer-events: auto;
5635
+ }
5636
+ .ncua-table__scrollbar-thumb:hover {
5637
+ background: var(--gray-200);
5638
+ }
5639
+ .ncua-table__scrollbar-thumb:active {
5640
+ background: var(--gray-300);
5641
+ cursor: grabbing;
5605
5642
  }
5606
5643
  .ncua-table__table {
5607
5644
  display: table;
5608
5645
  width: 100%;
5609
- border-collapse: collapse;
5646
+ border-collapse: separate;
5610
5647
  border-spacing: 0;
5611
5648
  table-layout: fixed;
5612
5649
  margin-bottom: 0;
@@ -5617,6 +5654,7 @@ button {
5617
5654
  }
5618
5655
  .ncua-table__header tr {
5619
5656
  border-bottom: none;
5657
+ height: 40px;
5620
5658
  }
5621
5659
  .ncua-table__header-cell {
5622
5660
  padding: 0 16px;
@@ -5651,9 +5689,16 @@ button {
5651
5689
  .ncua-table__header-cell-text {
5652
5690
  white-space: nowrap;
5653
5691
  }
5692
+ .ncua-table .ncua-checkbox-input,
5693
+ .ncua-table .ncua-radio-input {
5694
+ vertical-align: middle;
5695
+ }
5654
5696
  .ncua-table .ncua-checkbox-input::before {
5655
5697
  pointer-events: none;
5656
5698
  }
5699
+ .ncua-table__header-cell:has(> .ncua-checkbox-input), .ncua-table__header-cell:has(> .ncua-radio-input), .ncua-table__cell:has(> .ncua-checkbox-input), .ncua-table__cell:has(> .ncua-radio-input) {
5700
+ line-height: 0;
5701
+ }
5657
5702
  .ncua-table__sort-icon {
5658
5703
  display: inline-flex;
5659
5704
  align-items: center;
@@ -5676,20 +5721,21 @@ button {
5676
5721
  background: var(--base-white);
5677
5722
  }
5678
5723
  .ncua-table__row {
5679
- min-height: 48px;
5724
+ height: 48px;
5680
5725
  background: var(--base-white);
5681
5726
  transition: background-color 0.15s ease;
5682
5727
  }
5683
5728
  .ncua-table__row:nth-child(2n), .ncua-table__row:nth-child(2n+1) {
5684
5729
  background-color: var(--base-white);
5685
5730
  }
5686
- .ncua-table__row td {
5731
+ .ncua-table__row td,
5732
+ .ncua-table__row th.ncua-table__cell {
5687
5733
  border-bottom: 1px solid var(--gray-100);
5688
5734
  }
5689
- .ncua-table__row:last-child td {
5735
+ .ncua-table__row:last-child td, .ncua-table__row:last-child th.ncua-table__cell {
5690
5736
  border-bottom: none;
5691
5737
  }
5692
- .ncua-table__row--selected {
5738
+ .ncua-table__row--selected:nth-child(n) {
5693
5739
  background: var(--gray-50);
5694
5740
  }
5695
5741
  .ncua-table__row--selected td:first-child {
@@ -5705,23 +5751,39 @@ button {
5705
5751
  background: var(--base-black);
5706
5752
  z-index: 1;
5707
5753
  }
5708
- .ncua-table__row--warning {
5709
- background: var(--warning-50, #fffaeb);
5754
+ .ncua-table__row--warning.ncua-table__row--selected:nth-child(n) {
5755
+ background: var(--orange-50);
5710
5756
  }
5711
- .ncua-table__row--warning td {
5712
- border-bottom-color: var(--warning-200, #fedf89);
5757
+ .ncua-table__row--warning.ncua-table__row--selected td,
5758
+ .ncua-table__row--warning.ncua-table__row--selected th {
5759
+ background: var(--orange-50);
5713
5760
  }
5714
- .ncua-table__row--error {
5715
- background: var(--error-50, #fef3f2);
5761
+ .ncua-table__row--error.ncua-table__row--selected:nth-child(n) {
5762
+ background: var(--primary-red-50);
5716
5763
  }
5717
- .ncua-table__row--error td {
5718
- border-bottom-color: var(--error-200, #fecdca);
5764
+ .ncua-table__row--error.ncua-table__row--selected td,
5765
+ .ncua-table__row--error.ncua-table__row--selected th {
5766
+ background: var(--primary-red-50);
5719
5767
  }
5720
- .ncua-table--hoverable .ncua-table__row:not(.ncua-table__row--selected):not(.ncua-table__row--warning):not(.ncua-table__row--error):hover {
5721
- background: var(--gray-50);
5768
+ .ncua-table--hoverable .ncua-table__row:not(.ncua-table__row--selected):hover {
5769
+ background: color-mix(in srgb, var(--gray-50) 40%, transparent);
5722
5770
  }
5723
- .ncua-table--hoverable .ncua-table__row--selected:hover {
5724
- background: var(--gray-100);
5771
+ .ncua-table--hoverable .ncua-table__row--selected:not(.ncua-table__row--warning):not(.ncua-table__row--error):hover {
5772
+ background: color-mix(in srgb, var(--gray-200) 10%, transparent);
5773
+ }
5774
+ .ncua-table--hoverable .ncua-table__row--selected.ncua-table__row--warning:hover {
5775
+ background: var(--base-white);
5776
+ }
5777
+ .ncua-table--hoverable .ncua-table__row--selected.ncua-table__row--warning:hover td,
5778
+ .ncua-table--hoverable .ncua-table__row--selected.ncua-table__row--warning:hover th {
5779
+ background: color-mix(in srgb, var(--orange-200) 10%, transparent);
5780
+ }
5781
+ .ncua-table--hoverable .ncua-table__row--selected.ncua-table__row--error:hover {
5782
+ background: var(--base-white);
5783
+ }
5784
+ .ncua-table--hoverable .ncua-table__row--selected.ncua-table__row--error:hover td,
5785
+ .ncua-table--hoverable .ncua-table__row--selected.ncua-table__row--error:hover th {
5786
+ background: color-mix(in srgb, var(--primary-red-200) 10%, transparent);
5725
5787
  }
5726
5788
  .ncua-table__cell {
5727
5789
  padding: 10px 8px;
@@ -5732,13 +5794,13 @@ button {
5732
5794
  text-align: center;
5733
5795
  vertical-align: middle;
5734
5796
  border-right: 1px solid var(--gray-100);
5735
- min-height: 48px;
5797
+ height: 48px;
5736
5798
  word-break: break-word;
5737
5799
  }
5738
5800
  .ncua-table__cell:last-child {
5739
5801
  border-right: none;
5740
5802
  }
5741
- .ncua-table__checkbox-cell {
5803
+ .ncua-table__checkbox-cell, .ncua-table__radio-cell {
5742
5804
  width: 56px;
5743
5805
  min-width: 56px;
5744
5806
  max-width: 56px;
@@ -5746,13 +5808,13 @@ button {
5746
5808
  vertical-align: middle;
5747
5809
  border-right: 1px solid var(--gray-100);
5748
5810
  }
5749
- .ncua-table__checkbox-cell--header {
5811
+ .ncua-table__checkbox-cell--header, .ncua-table__radio-cell--header {
5750
5812
  padding: 0 16px;
5751
5813
  background: var(--gray-100);
5752
5814
  border-right-color: var(--gray-200);
5753
5815
  border-bottom: 1px solid var(--gray-200);
5754
5816
  }
5755
- .ncua-table__checkbox-cell--body {
5817
+ .ncua-table__checkbox-cell--body, .ncua-table__radio-cell--body {
5756
5818
  padding: 12px 16px;
5757
5819
  height: 48px;
5758
5820
  }
@@ -5803,16 +5865,18 @@ button {
5803
5865
  .ncua-table--selectable .ncua-table__table {
5804
5866
  background: var(--base-white);
5805
5867
  }
5868
+ .ncua-table--selectable .ncua-table__scroll-area,
5806
5869
  .ncua-table--selectable .ncua-table__scroll-container,
5807
- .ncua-table--selectable > .ncua-table__table {
5870
+ .ncua-table--selectable > .ncua-table__table:not(.ncua-table__table--head) {
5808
5871
  box-shadow: 0 1px 0 0 var(--gray-200);
5809
5872
  }
5810
5873
  .ncua-table--selectable:has(.ncua-table__footer) {
5811
5874
  padding-bottom: 0;
5812
5875
  background: var(--base-white);
5813
5876
  }
5877
+ .ncua-table--selectable:has(.ncua-table__footer) .ncua-table__scroll-area,
5814
5878
  .ncua-table--selectable:has(.ncua-table__footer) .ncua-table__scroll-container,
5815
- .ncua-table--selectable:has(.ncua-table__footer) > .ncua-table__table {
5879
+ .ncua-table--selectable:has(.ncua-table__footer) > .ncua-table__table:not(.ncua-table__table--head) {
5816
5880
  box-shadow: none;
5817
5881
  }
5818
5882
  .ncua-table--in-data-grid.ncua-table--selectable .ncua-table__header-cell:first-child,
@@ -5821,40 +5885,64 @@ button {
5821
5885
  border-left: none;
5822
5886
  }
5823
5887
  .ncua-table--in-data-grid.ncua-table--selectable.ncua-table--fixed-header .ncua-table__header-cell:first-child {
5824
- box-shadow: inset 0 -1px 0 0 var(--gray-200), inset -1px 0 0 0 var(--gray-200);
5888
+ border-left: none;
5825
5889
  }
5826
5890
  .ncua-table--fixed-header {
5827
5891
  position: relative;
5828
- }
5829
- .ncua-table--fixed-header::after {
5830
- content: "";
5831
- position: absolute;
5832
- top: 0;
5833
- right: 0;
5834
- width: 16px;
5835
- height: 40px;
5836
- background: var(--gray-100);
5837
- border-bottom: 1px solid var(--gray-200);
5838
- z-index: 11;
5839
- pointer-events: none;
5892
+ overflow: clip;
5840
5893
  }
5841
5894
  .ncua-table--fixed-header .ncua-table__header-cell {
5842
5895
  position: sticky;
5843
5896
  top: 0;
5844
5897
  z-index: 10;
5845
- border-bottom: none;
5846
- border-right: none;
5847
- box-shadow: inset 0 -1px 0 0 var(--gray-200), inset -1px 0 0 0 var(--gray-200);
5898
+ padding: 0 16px;
5899
+ height: 40px;
5848
5900
  }
5849
- .ncua-table--fixed-header .ncua-table__header-cell:last-child {
5850
- border-right: none;
5851
- box-shadow: inset 0 -1px 0 0 var(--gray-200);
5901
+ .ncua-table--fixed-header .ncua-table__scrollbar {
5902
+ top: calc(40px + 8px);
5903
+ right: 4px;
5904
+ bottom: 8px;
5905
+ }
5906
+ .ncua-table--horizontal .ncua-table__header-cell {
5907
+ height: 40px;
5908
+ min-height: 40px;
5909
+ }
5910
+ .ncua-table--vertical {
5911
+ overflow: visible;
5912
+ }
5913
+ .ncua-table--vertical .ncua-table__scroll-container {
5914
+ overflow: visible;
5915
+ }
5916
+ .ncua-table--vertical .ncua-table__body > .ncua-table__row:first-child > .ncua-table__cell:first-child {
5917
+ border-top-left-radius: var(--border-radius-md);
5918
+ }
5919
+ .ncua-table--vertical .ncua-table__body > .ncua-table__row:first-child > .ncua-table__cell:last-child {
5920
+ border-top-right-radius: var(--border-radius-md);
5852
5921
  }
5853
- .ncua-table--fixed-header.ncua-table--selectable .ncua-table__header-cell:first-child {
5854
- box-shadow: inset 0 -1px 0 0 var(--gray-200), inset -1px 0 0 0 var(--gray-200), inset 1px 0 0 0 var(--gray-100);
5922
+ .ncua-table--vertical .ncua-table__body > .ncua-table__row:last-child > .ncua-table__cell:first-child {
5923
+ border-bottom-left-radius: var(--border-radius-md);
5855
5924
  }
5856
- .ncua-table--vertical .ncua-table__row td:first-child,
5857
- .ncua-table--vertical .ncua-table__row th:first-child {
5925
+ .ncua-table--vertical .ncua-table__body > .ncua-table__row:last-child > .ncua-table__cell:last-child {
5926
+ border-bottom-right-radius: var(--border-radius-md);
5927
+ }
5928
+ .ncua-table--vertical .ncua-table .ncua-table__body > .ncua-table__row:first-child > .ncua-table__cell:first-child {
5929
+ border-top-left-radius: 0;
5930
+ }
5931
+ .ncua-table--vertical .ncua-table .ncua-table__body > .ncua-table__row:first-child > .ncua-table__cell:last-child {
5932
+ border-top-right-radius: 0;
5933
+ }
5934
+ .ncua-table--vertical .ncua-table .ncua-table__body > .ncua-table__row:last-child > .ncua-table__cell:first-child {
5935
+ border-bottom-left-radius: 0;
5936
+ }
5937
+ .ncua-table--vertical .ncua-table .ncua-table__body > .ncua-table__row:last-child > .ncua-table__cell:last-child {
5938
+ border-bottom-right-radius: 0;
5939
+ }
5940
+ .ncua-table--vertical .ncua-table__body > .ncua-table__row td,
5941
+ .ncua-table--vertical .ncua-table__body > .ncua-table__row th {
5942
+ height: 48px;
5943
+ }
5944
+ .ncua-table--vertical .ncua-table__body > .ncua-table__row td:first-child,
5945
+ .ncua-table--vertical .ncua-table__body > .ncua-table__row th:first-child {
5858
5946
  width: 240px;
5859
5947
  min-width: 240px;
5860
5948
  max-width: 240px;
@@ -5867,12 +5955,31 @@ button {
5867
5955
  background: var(--gray-50);
5868
5956
  border-right: 1px solid var(--gray-100);
5869
5957
  }
5870
- .ncua-table--vertical .ncua-table__row td:last-child,
5871
- .ncua-table--vertical .ncua-table__row th:last-child {
5958
+ .ncua-table--vertical .ncua-table__body > .ncua-table__row td:last-child,
5959
+ .ncua-table--vertical .ncua-table__body > .ncua-table__row th:last-child {
5872
5960
  padding: 10px 16px;
5873
5961
  text-align: left;
5874
5962
  font-weight: var(--font-weights-commerce-sans-4);
5875
5963
  }
5964
+ .ncua-table--vertical .ncua-table .ncua-table__body > .ncua-table__row td:first-child,
5965
+ .ncua-table--vertical .ncua-table .ncua-table__body > .ncua-table__row th:first-child {
5966
+ width: auto;
5967
+ min-width: 0;
5968
+ max-width: none;
5969
+ padding: 10px 8px;
5970
+ font-size: var(--font-size-xs);
5971
+ font-weight: var(--font-weights-commerce-sans-4);
5972
+ line-height: var(--line-heights-xs);
5973
+ text-align: center;
5974
+ background: var(--base-white);
5975
+ border-right: 1px solid var(--gray-100);
5976
+ }
5977
+ .ncua-table--vertical .ncua-table .ncua-table__body > .ncua-table__row td:last-child,
5978
+ .ncua-table--vertical .ncua-table .ncua-table__body > .ncua-table__row th:last-child {
5979
+ padding: 10px 8px;
5980
+ text-align: center;
5981
+ font-weight: var(--font-weights-commerce-sans-4);
5982
+ }
5876
5983
  .ncua-table--vertical .ncua-table__required {
5877
5984
  color: var(--primary-red-500, #ec1d31);
5878
5985
  font-size: var(--font-size-sm);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ncds/ui-admin",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "nhn-commerce의 어드민 디자인 시스템입니다.",
5
5
  "scripts": {
6
6
  "barrel": "node barrel.js",