@ihabdevteam/core 0.12.2 → 0.13.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.
@@ -2295,13 +2295,35 @@ export declare interface IconGridMenuProps {
2295
2295
 
2296
2296
  /** @public */
2297
2297
  export declare interface IconProps {
2298
+ /**
2299
+ * 아이콘 이름(lucide 이름 또는 파일 경로), 또는 그려 넣을 노드.
2300
+ *
2301
+ * 이름은 `icon` 이다 — `name` 이 아니다. 주지 않으면 아무것도 그리지 않는다.
2302
+ */
2298
2303
  icon?: ReactNode | string;
2299
2304
  label?: ReactNode;
2305
+ /**
2306
+ * 감싸는 `<span>` 의 클래스. 주면 기본 이름을 **갈아치운다** — 덧붙이지 않는다.
2307
+ *
2308
+ * 기본값 `iconRenderer-icon` 을 비롯한 네 `iconRenderer-*` 이름은 **패키지에
2309
+ * 제 규칙이 하나도 없다**(실측: 자기 규칙 0개). 붙잡을 이름일 뿐이고 크기는
2310
+ * `size`, 그 밖의 모양은 `wrapperStyle` 이나 소비자 CSS 로 간다. 그래서
2311
+ * `className="iconRenderer-icon"` 이라고 적어도 아무 모양도 따라오지 않는다.
2312
+ *
2313
+ * 패키지 안에서 이 이름을 붙잡는 자리는 딱 한 곳인데, 그것도 제 규칙이 없어서
2314
+ * 생긴 것이다 — `.audio-player__no-waveform .iconRenderer-icon` 이 래퍼가
2315
+ * 줄 높이만큼 커지는 것을 그 자리에서 스스로 바로잡는다.
2316
+ */
2300
2317
  className?: string;
2318
+ /** `<img>` 로 그릴 때의 클래스. 기본 `iconRenderer-icon-image` — 규칙 없음. */
2301
2319
  imgClassName?: string;
2320
+ /** 마스크로 그릴 때의 클래스. 기본 `iconRenderer-icon-mask` — 규칙 없음. */
2302
2321
  maskClassName?: string;
2322
+ /** 인라인 SVG 로 그릴 때의 클래스. 기본 `iconRenderer-icon-svg` — 규칙 없음. */
2303
2323
  svgClassName?: string;
2324
+ /** 감싸는 `<span>` 의 인라인 스타일. */
2304
2325
  wrapperStyle?: CSSProperties;
2326
+ /** 한 변 픽셀. 크기는 클래스가 아니라 이것으로 정한다. */
2305
2327
  size?: number;
2306
2328
  }
2307
2329
 
@@ -3867,7 +3889,7 @@ export declare interface ProgressBarProps {
3867
3889
  }
3868
3890
 
3869
3891
  /** @public */
3870
- export declare function ProgressIndicator({ max, index, inactiveBg, inactiveColor, transparent }: ProgressIndicatorProps): JSX.Element | null;
3892
+ export declare function ProgressIndicator({ max, index, inactiveBg, inactiveColor, transparent, variant, announce }: ProgressIndicatorProps): JSX.Element | null;
3871
3893
 
3872
3894
  /** @public */
3873
3895
  export declare interface ProgressIndicatorProps {
@@ -3883,6 +3905,24 @@ export declare interface ProgressIndicatorProps {
3883
3905
  * inactiveBg·inactiveColor 를 직접 주면 그쪽이 이긴다.
3884
3906
  */
3885
3907
  transparent?: boolean;
3908
+ /**
3909
+ * 표시 방식.
3910
+ *
3911
+ * - `numbered` — 번호를 적은 52×28 칸. 기본값이다. 훈련 팝업처럼 "지금 몇
3912
+ * 번째인지" 를 글로 읽어야 하는 자리에 쓴다.
3913
+ * - `dot` — 번호 없는 8px 점. 지금 칸만 알약으로 늘어난다. 화면에서 멀리
3914
+ * 떨어져 보는 안내처럼, 진행이 있다는 것만 알리고 본문에 자리를 내주는
3915
+ * 자리에 쓴다. 좁은 화면에서도 접지 않는다 — 점은 이미 작다.
3916
+ */
3917
+ variant?: 'numbered' | 'dot';
3918
+ /**
3919
+ * 단계가 바뀔 때 낭독기가 스스로 알리게 한다(`role="status"`).
3920
+ *
3921
+ * 기본은 알리지 않는다 — 점 모드는 그림에 가까워 `role="img"` + 이름표로
3922
+ * 두는 편이 조용하다. 사용자가 넘기는 것이 아니라 화면이 저절로 넘어가는
3923
+ * 자리(검사 안내)에서는 켜는 편이 낫다.
3924
+ */
3925
+ announce?: boolean;
3886
3926
  }
3887
3927
 
3888
3928
  /** key → 실제 배경 컴포넌트. PromoBanner 등 사용처가 이걸로 렌더한다. 각 컴포넌트는 자신의
@@ -5444,7 +5484,7 @@ export declare type TabItem = {
5444
5484
  /** @public */
5445
5485
  export declare function Table<T extends {
5446
5486
  id?: string | number;
5447
- }>({ fields, headerGroups, items, renderRow, onRowClick, onRowMouseEnter, onRowMouseLeave, onRowDragStart, onRowDragEnd, draggingId, gridTemplateColumns, resizable, resizeMode, resizeStorageKey, size, title, count, collapsed, onToggleCollapse, headerActions, empty, loading, dragOver, onDragOver, onDragLeave, onDrop, renderExpandedRow, expandedId, }: TableProps<T>): JSX.Element;
5487
+ }>({ fields, headerGroups, items, renderRow, onRowClick, onRowMouseEnter, onRowMouseLeave, onRowDragStart, onRowDragEnd, draggingId, gridTemplateColumns, resizable, resizeMode, resizeStorageKey, size, title, icon, count, collapsed, onToggleCollapse, headerActions, empty, loading, dragOver, onDragOver, onDragLeave, onDrop, renderExpandedRow, expandedId, }: TableProps<T>): JSX.Element;
5448
5488
 
5449
5489
  /**
5450
5490
  * **다음에 쓸 표를 고른다.**
@@ -5586,6 +5626,13 @@ export declare type TableProps<T extends {
5586
5626
  size?: 'small' | 'medium' | 'large';
5587
5627
  /** 테이블 상단 그룹 헤더 제목. 지정하면 .table-header 영역이 렌더됩니다. */
5588
5628
  title?: ReactNode;
5629
+ /**
5630
+ * 제목 앞에 서는 lucide 아이콘 이름. Panel 의 `icon` 과 같은 자리다.
5631
+ *
5632
+ * 이 자리가 없어서 부르는 쪽이 아이콘을 `title` 노드 안에 넣고 있었다 —
5633
+ * 표와 판넬을 나란히 놓는 화면에서 둘의 머리 모양이 미묘하게 갈린다.
5634
+ */
5635
+ icon?: string;
5589
5636
  /** 제목 옆 항목 갯수 표시 */
5590
5637
  count?: number;
5591
5638
  /** 접힘 상태 — true면 필드/행 영역을 숨김. onToggleCollapse와 함께 사용 */
@@ -1,13 +1,35 @@
1
1
  import { type ReactNode, type CSSProperties } from 'react';
2
2
  /** @public */
3
3
  export interface IconProps {
4
+ /**
5
+ * 아이콘 이름(lucide 이름 또는 파일 경로), 또는 그려 넣을 노드.
6
+ *
7
+ * 이름은 `icon` 이다 — `name` 이 아니다. 주지 않으면 아무것도 그리지 않는다.
8
+ */
4
9
  icon?: ReactNode | string;
5
10
  label?: ReactNode;
11
+ /**
12
+ * 감싸는 `<span>` 의 클래스. 주면 기본 이름을 **갈아치운다** — 덧붙이지 않는다.
13
+ *
14
+ * 기본값 `iconRenderer-icon` 을 비롯한 네 `iconRenderer-*` 이름은 **패키지에
15
+ * 제 규칙이 하나도 없다**(실측: 자기 규칙 0개). 붙잡을 이름일 뿐이고 크기는
16
+ * `size`, 그 밖의 모양은 `wrapperStyle` 이나 소비자 CSS 로 간다. 그래서
17
+ * `className="iconRenderer-icon"` 이라고 적어도 아무 모양도 따라오지 않는다.
18
+ *
19
+ * 패키지 안에서 이 이름을 붙잡는 자리는 딱 한 곳인데, 그것도 제 규칙이 없어서
20
+ * 생긴 것이다 — `.audio-player__no-waveform .iconRenderer-icon` 이 래퍼가
21
+ * 줄 높이만큼 커지는 것을 그 자리에서 스스로 바로잡는다.
22
+ */
6
23
  className?: string;
24
+ /** `<img>` 로 그릴 때의 클래스. 기본 `iconRenderer-icon-image` — 규칙 없음. */
7
25
  imgClassName?: string;
26
+ /** 마스크로 그릴 때의 클래스. 기본 `iconRenderer-icon-mask` — 규칙 없음. */
8
27
  maskClassName?: string;
28
+ /** 인라인 SVG 로 그릴 때의 클래스. 기본 `iconRenderer-icon-svg` — 규칙 없음. */
9
29
  svgClassName?: string;
30
+ /** 감싸는 `<span>` 의 인라인 스타일. */
10
31
  wrapperStyle?: CSSProperties;
32
+ /** 한 변 픽셀. 크기는 클래스가 아니라 이것으로 정한다. */
11
33
  size?: number;
12
34
  }
13
35
  /** @public */
@@ -25,7 +25,7 @@ export default function Panel({ title, icon, disc, actions, size = 'medium', min
25
25
  style.maxWidth = typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth;
26
26
  if (labelWidth !== undefined)
27
27
  style['--panel-label-width'] = typeof labelWidth === 'number' ? `${labelWidth}px` : labelWidth;
28
- return (_jsxs("div", { className: cls, style: Object.keys(style).length ? style : undefined, children: [(title != null || disc != null) && (_jsxs("div", { className: cx('panel__header', disc != null ? 'panel__header--with-disc' : ''), children: [icon && (_jsx(Icon, { icon: icon, label: typeof title === 'string' ? title : undefined, className: "panel__icon" })), _jsxs("div", { className: "panel__title-group", children: [title != null && _jsx("h2", { className: "panel__title h5b", children: title }), disc != null && _jsx("p", { className: "panel__disc caption-1", children: disc })] }), actions && _jsx("div", { className: "panel__actions", children: actions })] })), loading ? (_jsx(PanelRow, { variant: "loading" })) : empty != null && (children == null || (Array.isArray(children) && children.length === 0)) ? (_jsx(PanelRow, { variant: "empty", children: empty })) : scrollable ? (_jsx("div", { className: "panel__body--scroll", children: children })) : children] }));
28
+ return (_jsxs("div", { className: cls, style: Object.keys(style).length ? style : undefined, children: [(title != null || disc != null) && (_jsxs("div", { className: cx('panel__header', disc != null ? 'panel__header--with-disc' : ''), children: [icon && (_jsx(Icon, { icon: icon, label: typeof title === 'string' ? title : undefined, className: "panel__icon" })), _jsxs("div", { className: "panel__title-group", children: [title != null && (_jsx("h2", { className: `panel__title ${disc != null ? 'body-3b' : 'h5b'}`, children: title })), disc != null && _jsx("p", { className: "panel__disc caption-1", children: disc })] }), actions && _jsx("div", { className: "panel__actions", children: actions })] })), loading ? (_jsx(PanelRow, { variant: "loading" })) : empty != null && (children == null || (Array.isArray(children) && children.length === 0)) ? (_jsx(PanelRow, { variant: "empty", children: empty })) : scrollable ? (_jsx("div", { className: "panel__body--scroll", children: children })) : children] }));
29
29
  }
30
30
  // ── PanelGrid ──────────────────────────────────────────────────────────────
31
31
  /** @public */
@@ -39,3 +39,32 @@
39
39
  height: 28px;
40
40
  }
41
41
  }
42
+
43
+ /* ── 점 모드 ────────────────────────────────────────────────────────────
44
+ 번호 없이 자리만 알린다. 지금 칸은 폭으로 갈린다 — 색만으로 가르면 색을
45
+ 구별하기 어려운 사람에게 네 칸이 같아 보인다. 폭이 바뀌는 동안 움직임이
46
+ 생기므로 전환을 짧게 두되, 움직임을 줄여 달라는 설정은 따른다. */
47
+ .progress-indicator--dot {
48
+ gap: var(--spacing-xs);
49
+ }
50
+
51
+ .progress-indicator-dot--dot {
52
+ width: 8px;
53
+ height: 8px;
54
+ border-radius: var(--radius-full);
55
+ background: var(--pi-inactive-bg, var(--color-darkWhite));
56
+ transition: width 0.2s ease-out, background 0.2s ease-out;
57
+ }
58
+
59
+ .progress-indicator-dot--dot.done {
60
+ background: color-mix(in srgb, var(--color-main) 40%, transparent);
61
+ }
62
+
63
+ .progress-indicator-dot--dot.active {
64
+ width: 24px;
65
+ background: var(--color-main);
66
+ }
67
+
68
+ @media (prefers-reduced-motion: reduce) {
69
+ .progress-indicator-dot--dot { transition: none; }
70
+ }
@@ -13,6 +13,24 @@ export interface ProgressIndicatorProps {
13
13
  * inactiveBg·inactiveColor 를 직접 주면 그쪽이 이긴다.
14
14
  */
15
15
  transparent?: boolean;
16
+ /**
17
+ * 표시 방식.
18
+ *
19
+ * - `numbered` — 번호를 적은 52×28 칸. 기본값이다. 훈련 팝업처럼 "지금 몇
20
+ * 번째인지" 를 글로 읽어야 하는 자리에 쓴다.
21
+ * - `dot` — 번호 없는 8px 점. 지금 칸만 알약으로 늘어난다. 화면에서 멀리
22
+ * 떨어져 보는 안내처럼, 진행이 있다는 것만 알리고 본문에 자리를 내주는
23
+ * 자리에 쓴다. 좁은 화면에서도 접지 않는다 — 점은 이미 작다.
24
+ */
25
+ variant?: 'numbered' | 'dot';
26
+ /**
27
+ * 단계가 바뀔 때 낭독기가 스스로 알리게 한다(`role="status"`).
28
+ *
29
+ * 기본은 알리지 않는다 — 점 모드는 그림에 가까워 `role="img"` + 이름표로
30
+ * 두는 편이 조용하다. 사용자가 넘기는 것이 아니라 화면이 저절로 넘어가는
31
+ * 자리(검사 안내)에서는 켜는 편이 낫다.
32
+ */
33
+ announce?: boolean;
16
34
  }
17
35
  /** @public */
18
- export default function ProgressIndicator({ max, index, inactiveBg, inactiveColor, transparent }: ProgressIndicatorProps): import("react").JSX.Element | null;
36
+ export default function ProgressIndicator({ max, index, inactiveBg, inactiveColor, transparent, variant, announce }: ProgressIndicatorProps): import("react").JSX.Element | null;
@@ -1,4 +1,4 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import useMediaQuery from '../hooks/useMediaQuery';
4
4
  import './ProgressIndicator.css';
@@ -14,7 +14,7 @@ import './ProgressIndicator.css';
14
14
  */
15
15
  const TRANSPARENT_INACTIVE_BG = 'rgba(255, 255, 255, 0.16)';
16
16
  /** @public */
17
- export default function ProgressIndicator({ max, index, inactiveBg, inactiveColor, transparent }) {
17
+ export default function ProgressIndicator({ max, index, inactiveBg, inactiveColor, transparent, variant = 'numbered', announce = false }) {
18
18
  const { t } = useTranslation();
19
19
  const isMobile = useMediaQuery('(max-width: 767px)');
20
20
  if (!Number.isInteger(max) || max <= 0)
@@ -37,6 +37,13 @@ export default function ProgressIndicator({ max, index, inactiveBg, inactiveColo
37
37
  if (!inactiveColor)
38
38
  rootStyle['--pi-inactive-color'] = 'var(--color-white)';
39
39
  }
40
+ /* 점 모드 — 번호가 없으므로 칸마다 읽을 것이 없다. role="list" 로 두면
41
+ 낭독기가 "목록, 4개, 빈 항목…" 으로 읽어 도움이 되지 않는다. 그림 하나로
42
+ 묶고 이름표에 자리를 적는다. 화면이 스스로 넘어가는 자리에서는
43
+ announce 로 role="status" 를 켠다. */
44
+ if (variant === 'dot') {
45
+ return (_jsx("div", { className: "progress-indicator progress-indicator--dot", style: rootStyle, role: announce ? 'status' : 'img', "aria-label": groupLabel, children: Array.from({ length: max }).map((_, i) => (_jsx("span", { "aria-hidden": "true", className: `progress-indicator-dot--dot${i < idx ? ' done' : i === idx ? ' active' : ''}` }, i))) }));
46
+ }
40
47
  // 모바일: 현재 단계만 표시 (n / max 형태)
41
48
  if (isMobile) {
42
49
  return (_jsx("div", { className: "progress-indicator progress-indicator--mobile", style: rootStyle, role: "list", "aria-label": groupLabel, children: _jsxs("span", { role: "listitem", className: "progress-indicator-dot active body-3", children: [idx + 1, " / ", max] }) }));
@@ -30,6 +30,18 @@
30
30
  flex-shrink: 0;
31
31
  }
32
32
 
33
+ /* 제목 앞 아이콘 — Panel 머리의 아이콘과 같은 크기·같은 색. 표와 판넬을
34
+ 나란히 놓는 화면에서 두 머리가 같은 모양이 되도록. */
35
+ .table-header__icon {
36
+ width: 20px;
37
+ height: 20px;
38
+ flex-shrink: 0;
39
+ display: flex;
40
+ align-items: center;
41
+ justify-content: center;
42
+ color: var(--t-item-fg, var(--color-main));
43
+ }
44
+
33
45
  .table-header__title {
34
46
  color: var(--color-darkGray);
35
47
  }
@@ -66,6 +66,13 @@ export type TableProps<T extends {
66
66
  size?: 'small' | 'medium' | 'large';
67
67
  /** 테이블 상단 그룹 헤더 제목. 지정하면 .table-header 영역이 렌더됩니다. */
68
68
  title?: ReactNode;
69
+ /**
70
+ * 제목 앞에 서는 lucide 아이콘 이름. Panel 의 `icon` 과 같은 자리다.
71
+ *
72
+ * 이 자리가 없어서 부르는 쪽이 아이콘을 `title` 노드 안에 넣고 있었다 —
73
+ * 표와 판넬을 나란히 놓는 화면에서 둘의 머리 모양이 미묘하게 갈린다.
74
+ */
75
+ icon?: string;
69
76
  /** 제목 옆 항목 갯수 표시 */
70
77
  count?: number;
71
78
  /** 접힘 상태 — true면 필드/행 영역을 숨김. onToggleCollapse와 함께 사용 */
@@ -91,4 +98,4 @@ export type TableProps<T extends {
91
98
  /** @public */
92
99
  export default function Table<T extends {
93
100
  id?: string | number;
94
- }>({ fields, headerGroups, items, renderRow, onRowClick, onRowMouseEnter, onRowMouseLeave, onRowDragStart, onRowDragEnd, draggingId, gridTemplateColumns, resizable, resizeMode, resizeStorageKey, size, title, count, collapsed, onToggleCollapse, headerActions, empty, loading, dragOver, onDragOver, onDragLeave, onDrop, renderExpandedRow, expandedId, }: TableProps<T>): import("react").JSX.Element;
101
+ }>({ fields, headerGroups, items, renderRow, onRowClick, onRowMouseEnter, onRowMouseLeave, onRowDragStart, onRowDragEnd, draggingId, gridTemplateColumns, resizable, resizeMode, resizeStorageKey, size, title, icon, count, collapsed, onToggleCollapse, headerActions, empty, loading, dragOver, onDragOver, onDragLeave, onDrop, renderExpandedRow, expandedId, }: TableProps<T>): import("react").JSX.Element;
@@ -15,6 +15,7 @@ import { useState, useRef, useCallback, useEffect } from 'react';
15
15
  import ChevronUp from 'lucide-react/dist/esm/icons/chevron-up.mjs';
16
16
  import ChevronDown from 'lucide-react/dist/esm/icons/chevron-down.mjs';
17
17
  import Button from './Button';
18
+ import Icon from './Icon';
18
19
  import Loader from './Loader';
19
20
  function TableCell({ children, className, style }) {
20
21
  return _jsx("div", { className: className ? `table-cell ${className}` : 'table-cell', style: style, children: children });
@@ -60,7 +61,7 @@ function TableField({ children, onClick, className, sortDir, onResizeStart }) {
60
61
  return (_jsxs("div", { onClick: onClick, onKeyDown: onClick ? handleKeyDown : undefined, role: onClick ? 'button' : undefined, tabIndex: onClick ? 0 : undefined, "aria-sort": sortDir ? (sortDir === 'asc' ? 'ascending' : 'descending') : undefined, className: cx('table-field body-3', className, sortDir ? 'table-field--sorted' : '', onResizeStart ? 'table-field--resizable' : ''), children: [children, sortDir && _jsx(SortArrow, { dir: sortDir }), onResizeStart && (_jsx("span", { className: "table-field__resizer", onPointerDown: onResizeStart, onClick: e => e.stopPropagation(), "aria-hidden": "true" }))] }));
61
62
  }
62
63
  /** @public */
63
- export default function Table({ fields = [], headerGroups, items = [], renderRow, onRowClick, onRowMouseEnter, onRowMouseLeave, onRowDragStart, onRowDragEnd, draggingId, gridTemplateColumns, resizable = false, resizeMode = 'grow', resizeStorageKey, size = 'small', title, count, collapsed = false, onToggleCollapse, headerActions, empty, loading, dragOver = false, onDragOver, onDragLeave, onDrop, renderExpandedRow, expandedId, }) {
64
+ export default function Table({ fields = [], headerGroups, items = [], renderRow, onRowClick, onRowMouseEnter, onRowMouseLeave, onRowDragStart, onRowDragEnd, draggingId, gridTemplateColumns, resizable = false, resizeMode = 'grow', resizeStorageKey, size = 'small', title, icon, count, collapsed = false, onToggleCollapse, headerActions, empty, loading, dragOver = false, onDragOver, onDragLeave, onDrop, renderExpandedRow, expandedId, }) {
64
65
  const { t } = useTranslation();
65
66
  // ── 컬럼 폭 드래그 리사이즈 (resizable) ──
66
67
  const MIN_COL_W = 48;
@@ -183,7 +184,7 @@ export default function Table({ fields = [], headerGroups, items = [], renderRow
183
184
  return (_jsx("div", { className: `table-wrap table-wrap--${size}${dragOver ? ' table-wrap--dragover' : ''}${collapsed ? ' table-wrap--collapsed' : ''}`, style: gridStyle, onDragOver: onDragOver, onDragLeave: onDragLeave, onDrop: onDrop, children: _jsxs("div", { className: "table body-2", children: [hasHeader && (_jsxs("div", { className: "table-header", onClick: onToggleCollapse, role: onToggleCollapse ? 'button' : undefined, tabIndex: onToggleCollapse ? 0 : undefined, "aria-expanded": onToggleCollapse ? !collapsed : undefined, onKeyDown: onToggleCollapse ? (e) => { if (e.key === 'Enter' || e.key === ' ') {
184
185
  e.preventDefault();
185
186
  onToggleCollapse();
186
- } } : undefined, children: [onToggleCollapse && (_jsx(Button, { size: 40, type: "dot", variant: "transparent-gray", useBorder: false, icon: collapsed ? 'chevron-right' : 'chevron-down', ariaLabel: collapsed ? t('common.expand', '펼치기') : t('common.collapse', '접기'), className: "table-header__chevron" })), _jsx("span", { className: "table-header__title h5b", children: title }), count !== undefined && _jsx("span", { className: "table-header__count body-3b", children: count }), headerActions && (_jsx("span", { className: "table-header__actions", onClick: e => e.stopPropagation(), children: headerActions }))] })), !collapsed && (_jsxs(_Fragment, { children: [headerGroups && headerGroups.length > 0 && (_jsx("div", { className: "table-fields table-fields--groups", children: headerGroups.map((g, i) => (_jsx("div", { className: cx('table-field body-3', g.className), style: { gridColumn: `span ${g.span}` }, children: g.label }, i))) })), _jsx("div", { className: "table-fields", ref: fieldsRef, children: fields.map((f, i) => (_jsx(TableField, { onClick: f.onClick, className: f.className, sortDir: f.sortDir,
187
+ } } : undefined, children: [onToggleCollapse && (_jsx(Button, { size: 40, type: "dot", variant: "transparent-gray", useBorder: false, icon: collapsed ? 'chevron-right' : 'chevron-down', ariaLabel: collapsed ? t('common.expand', '펼치기') : t('common.collapse', '접기'), className: "table-header__chevron" })), icon && (_jsx(Icon, { icon: icon, label: typeof title === 'string' ? title : undefined, className: "table-header__icon" })), _jsx("span", { className: "table-header__title h5b", children: title }), count !== undefined && _jsx("span", { className: "table-header__count body-3b", children: count }), headerActions && (_jsx("span", { className: "table-header__actions", onClick: e => e.stopPropagation(), children: headerActions }))] })), !collapsed && (_jsxs(_Fragment, { children: [headerGroups && headerGroups.length > 0 && (_jsx("div", { className: "table-fields table-fields--groups", children: headerGroups.map((g, i) => (_jsx("div", { className: cx('table-field body-3', g.className), style: { gridColumn: `span ${g.span}` }, children: g.label }, i))) })), _jsx("div", { className: "table-fields", ref: fieldsRef, children: fields.map((f, i) => (_jsx(TableField, { onClick: f.onClick, className: f.className, sortDir: f.sortDir,
187
188
  /* fit 모드는 오른쪽 이웃에서 폭을 덜어 오므로, 덜어 올 컬럼이 없는 자리에는
188
189
  손잡이를 두지 않는다 — 두면 그 컬럼만 grow처럼 넓어져 표가 밀린다. */
189
190
  onResizeStart: resizable && i < fields.length - 1 && f.resizable !== false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ihabdevteam/core",
3
- "version": "0.12.2",
3
+ "version": "0.13.0",
4
4
  "private": false,
5
5
  "main": "dist/ihabdevteam-core.cjs.js",
6
6
  "module": "dist/ihabdevteam-core.esm.js",
@@ -113,6 +113,7 @@
113
113
  "smoke-test": "node ./scripts/smoke-test.js",
114
114
  "audit:exports": "node ./scripts/audit-exports.cjs",
115
115
  "audit:docs": "node ./scripts/audit-docs.cjs",
116
+ "audit:props": "node ./scripts/audit-props-tables.cjs",
116
117
  "analyze:bundle": "node ./scripts/analyze-bundle.cjs",
117
118
  "pack:check": "bash ./scripts/publish-check.sh",
118
119
  "check:size": "size-limit",