@ihabdevteam/core 0.11.1 → 0.12.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.
- package/dist/components.cjs.js +173 -168
- package/dist/components.esm.css +1 -1
- package/dist/hooks.cjs.js +159 -154
- package/dist/ihabdevteam-core.cjs.js +42 -37
- package/dist/ihabdevteam-core.d.ts +19 -1
- package/dist/packages/core/src/components/Panel.css +36 -0
- package/dist/packages/core/src/components/Panel.d.ts +19 -1
- package/dist/packages/core/src/components/Panel.js +3 -2
- package/dist/packages/core/src/utils/lucideIconSet.js +2 -0
- package/package.json +1 -1
|
@@ -3001,7 +3001,7 @@ export declare interface PairStats {
|
|
|
3001
3001
|
total: number;
|
|
3002
3002
|
}
|
|
3003
3003
|
|
|
3004
|
-
export declare function Panel({ title, actions, size, minHeight, maxWidth, className, scrollable, useBorder, useBg, useRowBorder, labelWidth, form, loading, empty, children }: PanelProps): JSX.Element;
|
|
3004
|
+
export declare function Panel({ title, icon, disc, actions, size, minHeight, maxWidth, className, scrollable, useBorder, useBg, useRowBorder, labelWidth, form, loading, empty, children }: PanelProps): JSX.Element;
|
|
3005
3005
|
|
|
3006
3006
|
/** @public */
|
|
3007
3007
|
export declare type PanelElement = HTMLDivElement & {
|
|
@@ -3017,6 +3017,24 @@ export declare function PanelGrid({ cols, children }: {
|
|
|
3017
3017
|
|
|
3018
3018
|
declare interface PanelProps {
|
|
3019
3019
|
title?: ReactNode;
|
|
3020
|
+
/**
|
|
3021
|
+
* 제목 앞에 서는 lucide 아이콘 이름. Section 의 `icon` 과 같은 자리다.
|
|
3022
|
+
*
|
|
3023
|
+
* 제목 노드 안에 직접 넣지 말 것 — 그러면 설명(`disc`)이 아이콘 밑으로
|
|
3024
|
+
* 들어가 제목 글자와 왼쪽 선이 어긋난다. 여기로 주면 아이콘이 제목·설명
|
|
3025
|
+
* 묶음 밖에 서서 둘의 왼쪽이 맞는다.
|
|
3026
|
+
*/
|
|
3027
|
+
icon?: string;
|
|
3028
|
+
/**
|
|
3029
|
+
* 제목 아래 한 줄 설명. Section 의 `disc` 와 같은 자리다.
|
|
3030
|
+
*
|
|
3031
|
+
* 머리가 제목 한 줄뿐이면, 칸이 무엇을 하는 자리인지 적을 곳이 없어 부르는
|
|
3032
|
+
* 쪽이 설명을 첫 행(`PanelRow variant="description"`)으로 내리게 된다 —
|
|
3033
|
+
* 고르는 것이 없는 행이 하나 늘고, 행 높이(56px)까지 차지한다.
|
|
3034
|
+
* 설명을 `title` 에 끼워 넣는 것도 답이 아니다: 제목은 `<h2>` 안에 그려지므로
|
|
3035
|
+
* 스크린리더가 설명까지 제목으로 읽는다.
|
|
3036
|
+
*/
|
|
3037
|
+
disc?: ReactNode;
|
|
3020
3038
|
actions?: ReactNode;
|
|
3021
3039
|
/** 행 높이 스케일 — small 48 / medium 56 / large 64. 기본 medium */
|
|
3022
3040
|
size?: PanelSize;
|
|
@@ -35,14 +35,50 @@
|
|
|
35
35
|
box-sizing: border-box;
|
|
36
36
|
border-bottom: 1px solid var(--color-darkWhite);
|
|
37
37
|
}
|
|
38
|
+
/* 머리 밑에 아무것도 없으면 가르는 선도 없다 — 판넬 자신의 테두리와 1px 을
|
|
39
|
+
사이에 두고 겹쳐 두 줄로 보인다(실측: 머리만 있는 판넬 높이 58px). */
|
|
40
|
+
.panel__header:last-child {
|
|
41
|
+
border-bottom: none;
|
|
42
|
+
}
|
|
38
43
|
/* header 높이도 size 스케일을 따름 — small 48 / medium 56 / large 64 */
|
|
39
44
|
.panel--small .panel__header { min-height: 48px; }
|
|
40
45
|
.panel--medium .panel__header { min-height: 56px; }
|
|
41
46
|
.panel--large .panel__header { min-height: 64px; }
|
|
47
|
+
/* 제목 앞 아이콘 — Section 과 같은 크기·같은 색. 제목·설명 묶음 밖에 서므로
|
|
48
|
+
설명도 제목 글자와 같은 왼쪽 선에서 시작한다. */
|
|
49
|
+
.panel__icon {
|
|
50
|
+
width: 20px;
|
|
51
|
+
height: 20px;
|
|
52
|
+
flex-shrink: 0;
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
justify-content: center;
|
|
56
|
+
margin-right: var(--spacing-s);
|
|
57
|
+
color: var(--t-item-fg, var(--color-main));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* 제목 + 설명 한 덩이. 설명이 없으면 한 줄짜리라 예전과 같은 모양이다. */
|
|
61
|
+
.panel__title-group {
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: column;
|
|
64
|
+
gap: 4px;
|
|
65
|
+
min-width: 0;
|
|
66
|
+
}
|
|
42
67
|
.panel__title {
|
|
43
68
|
color: var(--color-darkGray);
|
|
44
69
|
margin: 0;
|
|
45
70
|
}
|
|
71
|
+
/* 색은 행의 부제(panel-row__sub)와 같다. 급도 같은 caption-1 을 쓴다 —
|
|
72
|
+
머리와 행의 곁글이 한 화면에 함께 서므로(Section 의 disc 는 body-3 이지만
|
|
73
|
+
그쪽은 판넬 밖 제목이라 옆에 견줄 곁글이 없다). */
|
|
74
|
+
.panel__disc {
|
|
75
|
+
color: var(--color-gray);
|
|
76
|
+
margin: 0;
|
|
77
|
+
}
|
|
78
|
+
/* 설명이 붙어도 머리 높이는 size 스케일 그대로다 — 위아래 여백을 따로 주면
|
|
79
|
+
그만큼 머리만 커져서, 부제(sub)가 붙어도 높이가 그대로인 행과 어긋난다
|
|
80
|
+
(실측: padding 12px 을 줬더니 56 → 74). 제목+설명 두 줄은 49px 이라
|
|
81
|
+
medium(56)·large(64) 안에 들어간다. small(48) 에서만 살짝 넘친다. */
|
|
46
82
|
.panel__actions {
|
|
47
83
|
display: flex;
|
|
48
84
|
gap: 6px;
|
|
@@ -4,6 +4,24 @@ import './Panel.css';
|
|
|
4
4
|
type PanelSize = 'small' | 'medium' | 'large';
|
|
5
5
|
interface PanelProps {
|
|
6
6
|
title?: ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* 제목 앞에 서는 lucide 아이콘 이름. Section 의 `icon` 과 같은 자리다.
|
|
9
|
+
*
|
|
10
|
+
* 제목 노드 안에 직접 넣지 말 것 — 그러면 설명(`disc`)이 아이콘 밑으로
|
|
11
|
+
* 들어가 제목 글자와 왼쪽 선이 어긋난다. 여기로 주면 아이콘이 제목·설명
|
|
12
|
+
* 묶음 밖에 서서 둘의 왼쪽이 맞는다.
|
|
13
|
+
*/
|
|
14
|
+
icon?: string;
|
|
15
|
+
/**
|
|
16
|
+
* 제목 아래 한 줄 설명. Section 의 `disc` 와 같은 자리다.
|
|
17
|
+
*
|
|
18
|
+
* 머리가 제목 한 줄뿐이면, 칸이 무엇을 하는 자리인지 적을 곳이 없어 부르는
|
|
19
|
+
* 쪽이 설명을 첫 행(`PanelRow variant="description"`)으로 내리게 된다 —
|
|
20
|
+
* 고르는 것이 없는 행이 하나 늘고, 행 높이(56px)까지 차지한다.
|
|
21
|
+
* 설명을 `title` 에 끼워 넣는 것도 답이 아니다: 제목은 `<h2>` 안에 그려지므로
|
|
22
|
+
* 스크린리더가 설명까지 제목으로 읽는다.
|
|
23
|
+
*/
|
|
24
|
+
disc?: ReactNode;
|
|
7
25
|
actions?: ReactNode;
|
|
8
26
|
/** 행 높이 스케일 — small 48 / medium 56 / large 64. 기본 medium */
|
|
9
27
|
size?: PanelSize;
|
|
@@ -27,7 +45,7 @@ interface PanelProps {
|
|
|
27
45
|
empty?: ReactNode;
|
|
28
46
|
children?: ReactNode;
|
|
29
47
|
}
|
|
30
|
-
export default function Panel({ title, actions, size, minHeight, maxWidth, className, scrollable, useBorder, useBg, useRowBorder, labelWidth, form, loading, empty, children }: PanelProps): import("react").JSX.Element;
|
|
48
|
+
export default function Panel({ title, icon, disc, actions, size, minHeight, maxWidth, className, scrollable, useBorder, useBg, useRowBorder, labelWidth, form, loading, empty, children }: PanelProps): import("react").JSX.Element;
|
|
31
49
|
/** @public */
|
|
32
50
|
export declare function PanelGrid({ cols, children }: {
|
|
33
51
|
cols?: number;
|
|
@@ -8,12 +8,13 @@ import SegmentedControl from './SegmentedControl';
|
|
|
8
8
|
import Dropdown from './Dropdown';
|
|
9
9
|
import Button from './Button';
|
|
10
10
|
import Badge from './Badge';
|
|
11
|
+
import Icon from './Icon';
|
|
11
12
|
import { deviceKindVariant } from '../utils/deviceKind';
|
|
12
13
|
import TextField from './TextField';
|
|
13
14
|
import Loader from './Loader';
|
|
14
15
|
import './Panel.css';
|
|
15
16
|
const noop = () => { };
|
|
16
|
-
export default function Panel({ title, actions, size = 'medium', minHeight, maxWidth, className, scrollable, useBorder = true, useBg = true, useRowBorder = true, labelWidth, form = false, loading, empty, children }) {
|
|
17
|
+
export default function Panel({ title, icon, disc, actions, size = 'medium', minHeight, maxWidth, className, scrollable, useBorder = true, useBg = true, useRowBorder = true, labelWidth, form = false, loading, empty, children }) {
|
|
17
18
|
const cls = cx('panel', `panel--${size}`, form ? 'panel--form' : '',
|
|
18
19
|
/* minHeight 패널은 마지막 행 아래 빈 공간이 생길 수 있으므로 행 하단 구분선 사용 */
|
|
19
20
|
minHeight !== undefined ? 'panel--fill' : '', !useBorder ? 'panel--no-border' : '', !useBg ? 'panel--no-bg' : '', !useRowBorder ? 'panel--no-row-border' : '', className);
|
|
@@ -24,7 +25,7 @@ export default function Panel({ title, actions, size = 'medium', minHeight, maxW
|
|
|
24
25
|
style.maxWidth = typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth;
|
|
25
26
|
if (labelWidth !== undefined)
|
|
26
27
|
style['--panel-label-width'] = typeof labelWidth === 'number' ? `${labelWidth}px` : labelWidth;
|
|
27
|
-
return (_jsxs("div", { className: cls, style: Object.keys(style).length ? style : undefined, children: [title != null && (_jsxs("div", { className:
|
|
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
29
|
}
|
|
29
30
|
// ── PanelGrid ──────────────────────────────────────────────────────────────
|
|
30
31
|
/** @public */
|
|
@@ -155,6 +155,7 @@ import WrenchIcon from 'lucide-react/dist/esm/icons/wrench.mjs';
|
|
|
155
155
|
import XIcon from 'lucide-react/dist/esm/icons/x.mjs';
|
|
156
156
|
import ZapIcon from 'lucide-react/dist/esm/icons/zap.mjs';
|
|
157
157
|
import AnchorIcon from 'lucide-react/dist/esm/icons/anchor.mjs';
|
|
158
|
+
import ArmchairIcon from 'lucide-react/dist/esm/icons/armchair.mjs';
|
|
158
159
|
import ArrowUpAZIcon from 'lucide-react/dist/esm/icons/arrow-up-a-z.mjs';
|
|
159
160
|
import BarChart2Icon from 'lucide-react/dist/esm/icons/bar-chart-2.mjs';
|
|
160
161
|
import CalendarIcon from 'lucide-react/dist/esm/icons/calendar.mjs';
|
|
@@ -194,6 +195,7 @@ export const STATIC_LUCIDE_ICONS = {
|
|
|
194
195
|
'alert-triangle': AlertTriangleIcon,
|
|
195
196
|
'align-start-vertical': AlignStartVerticalIcon,
|
|
196
197
|
'anchor': AnchorIcon,
|
|
198
|
+
'armchair': ArmchairIcon,
|
|
197
199
|
'arrow-down': ArrowDownIcon,
|
|
198
200
|
'arrow-left': ArrowLeftIcon,
|
|
199
201
|
'arrow-right': ArrowRightIcon,
|