sellmate-design-system-react 9.0.0-beta.49 → 9.0.0-beta.50
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/AGENTS.md +6 -1
- package/dist/components/SBarChart/README.md +1 -0
- package/dist/components/SBarChart/SBarChart.d.ts +6 -0
- package/dist/components/SChatMessage/SChatMessage.d.ts +3 -2
- package/dist/components/SIcon/icons.gen.d.ts +3 -0
- package/dist/components/SKeyValueTable/README.md +1 -0
- package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +8 -1
- package/dist/index.cjs +246 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +246 -12
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +8 -1
- package/dist/llms.txt +6 -1
- package/dist/styles.css +6 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
| **표·목록** | `SChatMessage`(대화의 메시지 한 건) `SChatAttachedFile`(입력창 위, 아직 보내지 않은 첨부 한 칸) `SChatFile`(대화 흐름에 선, 보낸 파일 한 칸) `SChatSystemMessage`(대화 흐름 가운데 서는 시스템 안내) `STable` `STableBar` `SChipFilter` `SKeyValueTable` `SList` `SListItem` `SExpansionList` `SDraggableList` `SDraggableItem` `STree` |
|
|
46
46
|
| **레이아웃** | `SLayout` `SGnb` `SGnbSystem` `SSystemActionButton`(GNB system 패널에 한 줄씩 쌓는 액션 행 — 버튼 고르기는 §3-5) `SAccountListBox`(계정 행을 눌러 뜨는 계정 패널) `SPage` `SPageHeader`(페이지 제목 영역 — `SLayout` 안에서 `SPage` 앞에 둔다) `SSectionHeaderCard` `SCard` `SLoginCard`(통합 계정 로그인 화면의 카드) `SDivider` `SSplitter` `SScrollArea` `SExpansionItem` |
|
|
47
47
|
| **내비게이션** | `STabs` `SPagination` `SStepper` |
|
|
48
|
-
| **차트** | `SBarChart`(막대 그래프 — 항목끼리 크기를
|
|
48
|
+
| **차트** | `SBarChart`(막대 그래프 — 항목끼리 크기를 견준다. `stacked` 로 항목 안의 구성까지) |
|
|
49
49
|
| **표시·상태** | `STag` `SBadge` `SIcon` `SImage` `SCallout` `SGuide` |
|
|
50
50
|
| **진행·로딩** | `SLinearProgress` `SCircleProgress` `SLoadingContainer` `SLoadingModal` |
|
|
51
51
|
| **오버레이** | `STooltip` `SPopover` `SPopup` `SDrawer` `SPortal` |
|
|
@@ -542,6 +542,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
542
542
|
| 사용자가 순서를 드래그로 바꾸게 한다 | `SDraggableList` + `SDraggableItem` | §3-7-6 |
|
|
543
543
|
| 날짜별 일정을 한 달치 격자로 펼쳐 보여준다 | `SCalendarBoard` | §3-7-4 |
|
|
544
544
|
| 항목끼리 크기를 눈으로 견주게 한다 (기간별 추이·채널별 비중) | `SBarChart` | 정확한 값을 읽어야 하면 `STable` — 그래프는 "어느 쪽이 큰가" 를 답하지 "얼마인가" 를 답하지 않는다 |
|
|
545
|
+
| 항목의 크기와 **그 안의 구성**을 함께 보여준다 (주문 상태별 내역, 유입 경로별 몫) | `SBarChart stacked` | 계열끼리 견주는 것이 목적이면 `stacked` 없이 나란히 세운다. 더해서 뜻이 없는 값(비율·평균)은 쌓지 않는다 — 합계 라벨이 거짓말이 된다 |
|
|
545
546
|
| 표 위에 건수 요약과 액션을 얹는다 | `STableBar` | §4-2 |
|
|
546
547
|
| 상태·분류를 라벨로 찍는다 | `STag` | §3-1 |
|
|
547
548
|
| 색 점만으로 상태를 찍는다 | `SBadge` | §3-1 |
|
|
@@ -2153,6 +2154,10 @@ export default function ProductCreatePage() {
|
|
|
2153
2154
|
- 조회 값은 `type: 'text'` 행으로 표시한다. **상태·분류 태그도 별도 영역이 아니라 표의 한 행**으로 넣는다 (`render` 에 `STag`).
|
|
2154
2155
|
- 행이 많아지면 **유형별로 섹션을 나누고, 각 섹션을 `SSectionHeaderCard` 로 감싼다.**
|
|
2155
2156
|
섹션 제목은 `title` prop 으로, 바디 여백은 `padding` prop 으로 준다.
|
|
2157
|
+
- **한 화면에 행이 많아 훑어보기가 목적이면 `SKeyValueTable` 에 `dense` 를 켠다** — 셀 상하 여백과
|
|
2158
|
+
최소 높이가 함께 내려가 행이 좁아진다. 다만 **읽기 전용(`text`) 행에서만 실제로 좁아진다**:
|
|
2159
|
+
폼 필드가 든 행은 필드 자체의 높이가 행 높이를 정하므로 거의 변하지 않는다. 그래서 필터(§4-2)나
|
|
2160
|
+
폼(§4-3) 표에 켜 봐야 눈에 띄는 변화가 없다.
|
|
2156
2161
|
- **수정·삭제 버튼은 하단에 둔다.** 내용이 짧아 우측 상단에 두는 변형도 있으나 기본은 하단이다.
|
|
2157
2162
|
- **상세 페이지도 `contentHeight="fill"` 이 기본이다**(§2-2). 섹션이 많아 페이지가 실제로 스크롤되는 화면에서만 `auto` + `scrollEndSpacing` 을 켠다.
|
|
2158
2163
|
- **섹션마다 독립 인라인 폼이 있는 형태**도 상세 페이지의 변형이다. 섹션 안에서 바로 수정·저장하게 하는 화면인데, 이때 버튼 강조는 **섹션 단위가 아니라 페이지 단위로 판단한다** — §3-5-1 의 "`secondary` 연속 배치 금지"는 섹션이 다르면 적용되지 않는다. 그 섹션 안에서 닫히는 저장·취소는 `SSectionHeaderCard` 의 `button`·`footerLeft` 로 넘긴다 (§3-7-8). 아래 예처럼 **페이지 전체를 확정하는 버튼은 카드 밖 하단 줄**에 둔다 — 둘을 섞지 않는다.
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
| `categories` | `string[]` | — | 가로축(가로 막대면 세로축)에 놓일 항목 이름 |
|
|
12
12
|
| `series` | `SBarChartSeries[]` | — | 계열 목록. 각 `data` 는 `categories` 와 같은 순서다 |
|
|
13
13
|
| `direction?` | `SBarChartDirection` | `'vertical'` | 막대가 자라는 방향 |
|
|
14
|
+
| `stacked?` | `boolean` | `false` | 계열을 나란히 놓는 대신 **한 막대에 쌓는다**. 항목의 크기와 그 안의 구성을 함께 볼 때 쓴다. 첫 계열이 기준선에 붙고, 값 라벨은 조각마다가 아니라 **항목의 합계**를 한 번 적는다. 음수는 0 아래로 따로 쌓이며, 값 축도 개별 값이 아닌 항목별 합계로 잡힌다 |
|
|
14
15
|
| `palette?` | `SBarChartPalette` | `'default'` | 색 팔레트. 계열이 하나면 계열 대신 **항목**마다 색이 바뀐다. `custom` 일 때만 `colors` 를 본다 |
|
|
15
16
|
| `colors?` | `SBarChartColor[]` | — | `palette='custom'` 에서 쓸 색 이름을 계열 순서대로. 계열보다 짧으면 앞에서부터 순환한다 |
|
|
16
17
|
| `max?` | `number` | — | 값 축의 최댓값. 주지 않으면 데이터에서 읽기 좋은 값으로 정한다 |
|
|
@@ -39,6 +39,12 @@ export interface SBarChartProps {
|
|
|
39
39
|
series: SBarChartSeries[];
|
|
40
40
|
/** 막대가 자라는 방향 */
|
|
41
41
|
direction?: SBarChartDirection;
|
|
42
|
+
/**
|
|
43
|
+
* 계열을 나란히 놓는 대신 **한 막대에 쌓는다**. 항목의 크기와 그 안의 구성을 함께 볼 때 쓴다.
|
|
44
|
+
* 첫 계열이 기준선에 붙고, 값 라벨은 조각마다가 아니라 **항목의 합계**를 한 번 적는다.
|
|
45
|
+
* 음수는 0 아래로 따로 쌓이며, 값 축도 개별 값이 아닌 항목별 합계로 잡힌다
|
|
46
|
+
*/
|
|
47
|
+
stacked?: boolean;
|
|
42
48
|
/** 색 팔레트. 계열이 하나면 계열 대신 **항목**마다 색이 바뀐다. `custom` 일 때만 `colors` 를 본다 */
|
|
43
49
|
palette?: SBarChartPalette;
|
|
44
50
|
/** `palette='custom'` 에서 쓸 색 이름을 계열 순서대로. 계열보다 짧으면 앞에서부터 순환한다 */
|
|
@@ -116,7 +116,8 @@ export interface SChatMessageProps extends Omit<HTMLAttributes<HTMLDivElement>,
|
|
|
116
116
|
`direction` 하나로 받은 메시지(왼쪽)와
|
|
117
117
|
* 보낸 메시지(오른쪽)가 갈리고, 그에 따라 정렬과 말풍선 색이 함께 뒤집힌다.
|
|
118
118
|
*
|
|
119
|
-
* **말풍선 폭은 내용이 정한다** — 짧은 메시지는 글자만큼만 차지하고, 길면
|
|
120
|
-
*
|
|
119
|
+
* **말풍선 폭은 내용이 정한다** — 짧은 메시지는 글자만큼만 차지하고, 길면 접힌다. 다만 반대편
|
|
120
|
+
* 끝까지 가지는 않는다: 받은 메시지는 오른쪽, 보낸 메시지는 왼쪽에 여백이 남아 어느 쪽이 말한
|
|
121
|
+
* 것인지가 폭으로도 읽힌다. 대화 폭을 더 좁히려면 이 컴포넌트가 아니라 담는 쪽을 좁힌다.
|
|
121
122
|
*/
|
|
122
123
|
export declare const SChatMessage: import("react").ForwardRefExoticComponent<SChatMessageProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -28,6 +28,7 @@ export declare const ICONS: {
|
|
|
28
28
|
readonly caretLeft: (p: IconRenderProps) => import("react").JSX.Element;
|
|
29
29
|
readonly caretRight: (p: IconRenderProps) => import("react").JSX.Element;
|
|
30
30
|
readonly caretUp: (p: IconRenderProps) => import("react").JSX.Element;
|
|
31
|
+
readonly chat: (p: IconRenderProps) => import("react").JSX.Element;
|
|
31
32
|
readonly check: (p: IconRenderProps) => import("react").JSX.Element;
|
|
32
33
|
readonly checkFill: (p: IconRenderProps) => import("react").JSX.Element;
|
|
33
34
|
readonly checkOutline: (p: IconRenderProps) => import("react").JSX.Element;
|
|
@@ -54,6 +55,7 @@ export declare const ICONS: {
|
|
|
54
55
|
readonly edit: (p: IconRenderProps) => import("react").JSX.Element;
|
|
55
56
|
readonly etc: (p: IconRenderProps) => import("react").JSX.Element;
|
|
56
57
|
readonly event: (p: IconRenderProps) => import("react").JSX.Element;
|
|
58
|
+
readonly focus: (p: IconRenderProps) => import("react").JSX.Element;
|
|
57
59
|
readonly global: (p: IconRenderProps) => import("react").JSX.Element;
|
|
58
60
|
readonly helpFill: (p: IconRenderProps) => import("react").JSX.Element;
|
|
59
61
|
readonly helpOutline: (p: IconRenderProps) => import("react").JSX.Element;
|
|
@@ -64,6 +66,7 @@ export declare const ICONS: {
|
|
|
64
66
|
readonly launcher: (p: IconRenderProps) => import("react").JSX.Element;
|
|
65
67
|
readonly leftRight: (p: IconRenderProps) => import("react").JSX.Element;
|
|
66
68
|
readonly line: (p: IconRenderProps) => import("react").JSX.Element;
|
|
69
|
+
readonly link: (p: IconRenderProps) => import("react").JSX.Element;
|
|
67
70
|
readonly location: (p: IconRenderProps) => import("react").JSX.Element;
|
|
68
71
|
readonly logout: (p: IconRenderProps) => import("react").JSX.Element;
|
|
69
72
|
readonly minus: (p: IconRenderProps) => import("react").JSX.Element;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|------|------|---------|-------------|
|
|
11
11
|
| `fields?` | `SKeyValueField[][]` | `[]` | 2차원 배열. row → [th|td] 필드들 |
|
|
12
12
|
| `values?` | `Record<string, unknown>` | `{}` | field name을 key로 하는 값 객체 (`{ [name]: value }`). 지정 시 해당 field의 값으로 사용되며, field별 `options.value`보다 우선합니다. `onChange`의 `detail.values`와 함께 controlled 패턴으로 사용합니다. |
|
|
13
|
+
| `dense?` | `boolean` | `false` | 행을 좁게 그린다 — 셀의 상하 패딩(8px → 6px)과 짝이 되는 최소 높이(44px → 32px)를 함께 내린다. 한 화면에 행이 많아 훑어보기가 목적인 상세 조회 표에 쓴다. 좌우 패딩과 글자 크기는 그대로다. **`STable` 과 달리 밀도 토글이 붙지 않는 고정값이다** — 준 값 그대로 그린다. 읽기 전용(`text`) 행에서만 실제로 좁아진다: 폼 필드 행은 필드 높이가 행 높이를 정한다 |
|
|
13
14
|
| `search?` | `boolean` | `false` | 우측 검색 패널 |
|
|
14
15
|
| `radius?` | `'default' \| 'useTop' \| 'full'` | `'default'` | border-radius 제어 |
|
|
15
16
|
| `bordered?` | `boolean` | `true` | 바깥 테두리. 기본은 `true`. `SSectionHeaderCard` 의 `padding="none"` 안에 넣어 카드 가장자리까지 채울 때 `false` 로 끈다 — 카드가 이미 바깥 테두리를 그리므로, 켜 두면 1px 두 개가 나란히 놓여 그 변만 2px 로 보인다. |
|
|
@@ -104,6 +104,13 @@ export interface SKeyValueTableProps {
|
|
|
104
104
|
* `onChange`의 `detail.values`와 함께 controlled 패턴으로 사용합니다.
|
|
105
105
|
*/
|
|
106
106
|
values?: Record<string, unknown>;
|
|
107
|
+
/**
|
|
108
|
+
* 행을 좁게 그린다 — 셀의 상하 패딩(8px → 6px)과 짝이 되는 최소 높이(44px → 32px)를 함께
|
|
109
|
+
* 내린다. 한 화면에 행이 많아 훑어보기가 목적인 상세 조회 표에 쓴다. 좌우 패딩과 글자 크기는
|
|
110
|
+
* 그대로다. **`STable` 과 달리 밀도 토글이 붙지 않는 고정값이다** — 준 값 그대로 그린다.
|
|
111
|
+
* 읽기 전용(`text`) 행에서만 실제로 좁아진다: 폼 필드 행은 필드 높이가 행 높이를 정한다
|
|
112
|
+
*/
|
|
113
|
+
dense?: boolean;
|
|
107
114
|
/** 우측 검색 패널 */
|
|
108
115
|
search?: boolean;
|
|
109
116
|
/** border-radius 제어 */
|
|
@@ -123,5 +130,5 @@ export interface SKeyValueTableProps {
|
|
|
123
130
|
style?: CSSProperties;
|
|
124
131
|
}
|
|
125
132
|
/** SKeyValueTable — sd-key-value-table 포팅. th/td 폼 레이아웃 + 필드 렌더러. */
|
|
126
|
-
export declare function SKeyValueTable({ fields, values, search, radius, bordered, onChange, onSearch, className, style, }: SKeyValueTableProps): import("react").JSX.Element | null;
|
|
133
|
+
export declare function SKeyValueTable({ fields, values, dense, search, radius, bordered, onChange, onSearch, className, style, }: SKeyValueTableProps): import("react").JSX.Element | null;
|
|
127
134
|
export {};
|
package/dist/index.cjs
CHANGED
|
@@ -967,6 +967,29 @@ var Icon_caretUp = (p) => {
|
|
|
967
967
|
}
|
|
968
968
|
);
|
|
969
969
|
};
|
|
970
|
+
var Icon_chat = (p) => {
|
|
971
|
+
const { size = 24, ...rest } = p;
|
|
972
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
973
|
+
"svg",
|
|
974
|
+
{
|
|
975
|
+
width: size,
|
|
976
|
+
height: size,
|
|
977
|
+
viewBox: "0 0 24 24",
|
|
978
|
+
fill: "none",
|
|
979
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
980
|
+
...rest,
|
|
981
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
982
|
+
"path",
|
|
983
|
+
{
|
|
984
|
+
fillRule: "evenodd",
|
|
985
|
+
clipRule: "evenodd",
|
|
986
|
+
d: "M12.2961 2.25C15.6684 2.25008 18.4344 4.83725 18.7228 8.13477C21.4143 9.74397 22.7011 13.2749 21.1398 16.3975C20.6005 17.4762 20.4853 18.7183 20.8166 19.8779L21.048 20.6885C21.2975 21.5618 20.3398 22.2835 19.5695 21.8027L16.2853 19.75H12.0002C9.43974 19.75 7.24026 18.2099 6.27457 16.0059L4.16129 17.3037C3.38392 17.7807 2.42724 17.0507 2.6818 16.1748L2.92301 15.3428C3.27732 14.1243 3.1547 12.8165 2.57926 11.6855C0.381511 7.36716 3.51808 2.25032 8.36344 2.25H12.2961ZM8.36344 3.75C4.63792 3.75032 2.22559 7.6845 3.9152 11.0049C4.60038 12.3512 4.79173 13.8901 4.46598 15.3564L6.89567 13.8643L7.06656 13.7744C7.24277 13.6973 7.43434 13.6572 7.62809 13.6572H12.2961C15.0317 13.6571 17.2499 11.4397 17.2502 8.7041C17.2502 5.9683 15.0318 3.75008 12.2961 3.75H8.36344Z",
|
|
987
|
+
fill: "currentColor"
|
|
988
|
+
}
|
|
989
|
+
)
|
|
990
|
+
}
|
|
991
|
+
);
|
|
992
|
+
};
|
|
970
993
|
var Icon_check = (p) => {
|
|
971
994
|
const { size = 24, ...rest } = p;
|
|
972
995
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1678,6 +1701,59 @@ var Icon_event = (p) => {
|
|
|
1678
1701
|
}
|
|
1679
1702
|
);
|
|
1680
1703
|
};
|
|
1704
|
+
var Icon_focus = (p) => {
|
|
1705
|
+
const { size = 24, ...rest } = p;
|
|
1706
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1707
|
+
"svg",
|
|
1708
|
+
{
|
|
1709
|
+
width: size,
|
|
1710
|
+
height: size,
|
|
1711
|
+
viewBox: "0 0 24 24",
|
|
1712
|
+
fill: "none",
|
|
1713
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1714
|
+
...rest,
|
|
1715
|
+
children: [
|
|
1716
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1717
|
+
"path",
|
|
1718
|
+
{
|
|
1719
|
+
d: "M3 16.25C3.41421 16.25 3.75 16.5858 3.75 17V20C3.75 20.1381 3.86193 20.25 4 20.25H7C7.41421 20.25 7.75 20.5858 7.75 21C7.75 21.4142 7.41421 21.75 7 21.75H4C3.0335 21.75 2.25 20.9665 2.25 20V17C2.25 16.5858 2.58579 16.25 3 16.25Z",
|
|
1720
|
+
fill: "currentColor"
|
|
1721
|
+
}
|
|
1722
|
+
),
|
|
1723
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1724
|
+
"path",
|
|
1725
|
+
{
|
|
1726
|
+
d: "M21 16.25C21.4142 16.25 21.75 16.5858 21.75 17V20C21.75 20.9665 20.9665 21.75 20 21.75H17C16.5858 21.75 16.25 21.4142 16.25 21C16.25 20.5858 16.5858 20.25 17 20.25H20C20.1381 20.25 20.25 20.1381 20.25 20V17C20.25 16.5858 20.5858 16.25 21 16.25Z",
|
|
1727
|
+
fill: "currentColor"
|
|
1728
|
+
}
|
|
1729
|
+
),
|
|
1730
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1731
|
+
"path",
|
|
1732
|
+
{
|
|
1733
|
+
fillRule: "evenodd",
|
|
1734
|
+
clipRule: "evenodd",
|
|
1735
|
+
d: "M12 8.25C14.0711 8.25 15.75 9.92893 15.75 12C15.75 14.0711 14.0711 15.75 12 15.75C9.92893 15.75 8.25 14.0711 8.25 12C8.25 9.92893 9.92893 8.25 12 8.25ZM12 9.75C10.7574 9.75 9.75 10.7574 9.75 12C9.75 13.2426 10.7574 14.25 12 14.25C13.2426 14.25 14.25 13.2426 14.25 12C14.25 10.7574 13.2426 9.75 12 9.75Z",
|
|
1736
|
+
fill: "currentColor"
|
|
1737
|
+
}
|
|
1738
|
+
),
|
|
1739
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1740
|
+
"path",
|
|
1741
|
+
{
|
|
1742
|
+
d: "M7 2.25C7.41421 2.25 7.75 2.58579 7.75 3C7.75 3.41421 7.41421 3.75 7 3.75H4C3.86193 3.75 3.75 3.86193 3.75 4V7C3.75 7.41421 3.41421 7.75 3 7.75C2.58579 7.75 2.25 7.41421 2.25 7V4C2.25 3.0335 3.0335 2.25 4 2.25H7Z",
|
|
1743
|
+
fill: "currentColor"
|
|
1744
|
+
}
|
|
1745
|
+
),
|
|
1746
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1747
|
+
"path",
|
|
1748
|
+
{
|
|
1749
|
+
d: "M20 2.25C20.9665 2.25 21.75 3.0335 21.75 4V7C21.75 7.41421 21.4142 7.75 21 7.75C20.5858 7.75 20.25 7.41421 20.25 7V4C20.25 3.86193 20.1381 3.75 20 3.75H17C16.5858 3.75 16.25 3.41421 16.25 3C16.25 2.58579 16.5858 2.25 17 2.25H20Z",
|
|
1750
|
+
fill: "currentColor"
|
|
1751
|
+
}
|
|
1752
|
+
)
|
|
1753
|
+
]
|
|
1754
|
+
}
|
|
1755
|
+
);
|
|
1756
|
+
};
|
|
1681
1757
|
var Icon_global = (p) => {
|
|
1682
1758
|
const { size = 24, ...rest } = p;
|
|
1683
1759
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2038,6 +2114,43 @@ var Icon_line = (p) => {
|
|
|
2038
2114
|
}
|
|
2039
2115
|
);
|
|
2040
2116
|
};
|
|
2117
|
+
var Icon_link = (p) => {
|
|
2118
|
+
const { size = 24, ...rest } = p;
|
|
2119
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2120
|
+
"svg",
|
|
2121
|
+
{
|
|
2122
|
+
width: size,
|
|
2123
|
+
height: size,
|
|
2124
|
+
viewBox: "0 0 24 24",
|
|
2125
|
+
fill: "none",
|
|
2126
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2127
|
+
...rest,
|
|
2128
|
+
children: [
|
|
2129
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2130
|
+
"path",
|
|
2131
|
+
{
|
|
2132
|
+
d: "M10 6.25C10.4142 6.25 10.75 6.58579 10.75 7C10.75 7.41421 10.4142 7.75 10 7.75H7C4.65279 7.75 2.75 9.65279 2.75 12C2.75 14.3472 4.65279 16.25 7 16.25H10C10.4142 16.25 10.75 16.5858 10.75 17C10.75 17.4142 10.4142 17.75 10 17.75H7C3.82436 17.75 1.25 15.1756 1.25 12C1.25 8.82436 3.82436 6.25 7 6.25H10Z",
|
|
2133
|
+
fill: "currentColor"
|
|
2134
|
+
}
|
|
2135
|
+
),
|
|
2136
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2137
|
+
"path",
|
|
2138
|
+
{
|
|
2139
|
+
d: "M17 6.25C20.1756 6.25 22.75 8.82436 22.75 12C22.75 15.1756 20.1756 17.75 17 17.75H14C13.5858 17.75 13.25 17.4142 13.25 17C13.25 16.5858 13.5858 16.25 14 16.25H17C19.3472 16.25 21.25 14.3472 21.25 12C21.25 9.65279 19.3472 7.75 17 7.75H14C13.5858 7.75 13.25 7.41421 13.25 7C13.25 6.58579 13.5858 6.25 14 6.25H17Z",
|
|
2140
|
+
fill: "currentColor"
|
|
2141
|
+
}
|
|
2142
|
+
),
|
|
2143
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2144
|
+
"path",
|
|
2145
|
+
{
|
|
2146
|
+
d: "M16 11.25C16.4142 11.25 16.75 11.5858 16.75 12C16.75 12.4142 16.4142 12.75 16 12.75H8C7.58579 12.75 7.25 12.4142 7.25 12C7.25 11.5858 7.58579 11.25 8 11.25H16Z",
|
|
2147
|
+
fill: "currentColor"
|
|
2148
|
+
}
|
|
2149
|
+
)
|
|
2150
|
+
]
|
|
2151
|
+
}
|
|
2152
|
+
);
|
|
2153
|
+
};
|
|
2041
2154
|
var Icon_location = (p) => {
|
|
2042
2155
|
const { size = 24, ...rest } = p;
|
|
2043
2156
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3249,6 +3362,7 @@ var ICONS = {
|
|
|
3249
3362
|
caretLeft: Icon_caretLeft,
|
|
3250
3363
|
caretRight: Icon_caretRight,
|
|
3251
3364
|
caretUp: Icon_caretUp,
|
|
3365
|
+
chat: Icon_chat,
|
|
3252
3366
|
check: Icon_check,
|
|
3253
3367
|
checkFill: Icon_checkFill,
|
|
3254
3368
|
checkOutline: Icon_checkOutline,
|
|
@@ -3275,6 +3389,7 @@ var ICONS = {
|
|
|
3275
3389
|
edit: Icon_edit,
|
|
3276
3390
|
etc: Icon_etc,
|
|
3277
3391
|
event: Icon_event,
|
|
3392
|
+
focus: Icon_focus,
|
|
3278
3393
|
global: Icon_global,
|
|
3279
3394
|
helpFill: Icon_helpFill,
|
|
3280
3395
|
helpOutline: Icon_helpOutline,
|
|
@@ -3285,6 +3400,7 @@ var ICONS = {
|
|
|
3285
3400
|
launcher: Icon_launcher,
|
|
3286
3401
|
leftRight: Icon_leftRight,
|
|
3287
3402
|
line: Icon_line,
|
|
3403
|
+
link: Icon_link,
|
|
3288
3404
|
location: Icon_location,
|
|
3289
3405
|
logout: Icon_logout,
|
|
3290
3406
|
minus: Icon_minus,
|
|
@@ -5024,6 +5140,11 @@ var SChatMessageImpl = /* @__PURE__ */ react.forwardRef(function SChatMessage({
|
|
|
5024
5140
|
// items-start 라 이름이 있든 없든 아바타는 언제나 첫 줄에 붙는다.
|
|
5025
5141
|
"flex items-start gap-(--cmp-chatMessage-avatarGap)",
|
|
5026
5142
|
outgoing && "flex-row-reverse",
|
|
5143
|
+
// 반대편은 비워 둔다 — 받은 메시지는 오른쪽, 보낸 메시지는 왼쪽. 긴 메시지가 화면 폭을
|
|
5144
|
+
// 다 차지하면 어느 쪽이 말한 것인지가 자리로 읽히지 않으므로, 말풍선이 반대편 끝까지
|
|
5145
|
+
// 가지 못하게 막는다. 논리 속성(ps/pe)을 쓰지 않는 이유: flex-row-reverse 는 글 방향을
|
|
5146
|
+
// 뒤집지 않아 보낸 메시지에서 여백이 같은 쪽에 남는다.
|
|
5147
|
+
outgoing ? "pl-(--cmp-chatMessage-row-paddingInset)" : "pr-(--cmp-chatMessage-row-paddingInset)",
|
|
5027
5148
|
className
|
|
5028
5149
|
),
|
|
5029
5150
|
...rest,
|
|
@@ -17720,6 +17841,7 @@ var cssLen2 = (v) => v == null ? void 0 : typeof v === "number" ? `${v}px` : v;
|
|
|
17720
17841
|
function SKeyValueTable({
|
|
17721
17842
|
fields = [],
|
|
17722
17843
|
values = {},
|
|
17844
|
+
dense = false,
|
|
17723
17845
|
search = false,
|
|
17724
17846
|
radius = "default",
|
|
17725
17847
|
bordered = true,
|
|
@@ -17734,8 +17856,8 @@ function SKeyValueTable({
|
|
|
17734
17856
|
value,
|
|
17735
17857
|
values: { ...values, [name]: value }
|
|
17736
17858
|
});
|
|
17737
|
-
const cellHeight = "var(--cmp-table-keyValue-height)";
|
|
17738
|
-
const cellPadY = "var(--cmp-table-keyValue-body-paddingY)";
|
|
17859
|
+
const cellHeight = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-keyValue-height)";
|
|
17860
|
+
const cellPadY = dense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-keyValue-body-paddingY)";
|
|
17739
17861
|
const renderField = (f) => {
|
|
17740
17862
|
if (f.render) return f.render;
|
|
17741
17863
|
const opt = { ...f.options ?? {} };
|
|
@@ -18253,6 +18375,7 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18253
18375
|
categories,
|
|
18254
18376
|
series,
|
|
18255
18377
|
direction = "vertical",
|
|
18378
|
+
stacked = false,
|
|
18256
18379
|
palette = "default",
|
|
18257
18380
|
colors: customColors,
|
|
18258
18381
|
max,
|
|
@@ -18272,6 +18395,7 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18272
18395
|
const { ref: plotRef, size } = useElementSize();
|
|
18273
18396
|
const { ref: axisTextRef, size: axisText } = useElementSize();
|
|
18274
18397
|
const { ref: axisSampleRef, size: axisSample } = useElementSize();
|
|
18398
|
+
const clipId = react.useId();
|
|
18275
18399
|
const [hovered, setHovered] = react.useState(null);
|
|
18276
18400
|
const hoveredCategory = hovered?.category ?? null;
|
|
18277
18401
|
const perCategory = series.length === 1;
|
|
@@ -18279,23 +18403,37 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18279
18403
|
(seriesIndex, categoryIndex) => paletteColor(palette, perCategory ? categoryIndex : seriesIndex, customColors),
|
|
18280
18404
|
[palette, customColors, perCategory]
|
|
18281
18405
|
);
|
|
18406
|
+
const stackTotals = react.useMemo(
|
|
18407
|
+
() => categories.map(
|
|
18408
|
+
(_, categoryIndex) => series.reduce(
|
|
18409
|
+
(acc, s) => {
|
|
18410
|
+
const value = s.data[categoryIndex];
|
|
18411
|
+
if (value == null || !Number.isFinite(value)) return acc;
|
|
18412
|
+
return value < 0 ? { positive: acc.positive, negative: acc.negative + value } : { positive: acc.positive + value, negative: acc.negative };
|
|
18413
|
+
},
|
|
18414
|
+
{ positive: 0, negative: 0 }
|
|
18415
|
+
)
|
|
18416
|
+
),
|
|
18417
|
+
[categories, series]
|
|
18418
|
+
);
|
|
18282
18419
|
const scale = react.useMemo(
|
|
18283
18420
|
() => niceScale(
|
|
18284
|
-
series.flatMap((s) => s.data),
|
|
18421
|
+
stacked ? stackTotals.flatMap((total) => [total.positive, total.negative]) : series.flatMap((s) => s.data),
|
|
18285
18422
|
tickCount,
|
|
18286
18423
|
max
|
|
18287
18424
|
),
|
|
18288
|
-
[series, tickCount, max]
|
|
18425
|
+
[stacked, stackTotals, series, tickCount, max]
|
|
18289
18426
|
);
|
|
18427
|
+
const barSlots = stacked ? 1 : series.length;
|
|
18290
18428
|
const axisLength = vertical ? size.width : size.height;
|
|
18291
18429
|
const layout = react.useMemo(
|
|
18292
|
-
() => bandLayout(axisLength, categories.length,
|
|
18293
|
-
[axisLength, categories.length,
|
|
18430
|
+
() => bandLayout(axisLength, categories.length, barSlots, barSize),
|
|
18431
|
+
[axisLength, categories.length, barSlots, barSize]
|
|
18294
18432
|
);
|
|
18295
18433
|
const zeroRatio = ratioOf(0, scale);
|
|
18296
|
-
const minPlotWidth = vertical ? categories.length * minBand(
|
|
18434
|
+
const minPlotWidth = vertical ? categories.length * minBand(barSlots) : 0;
|
|
18297
18435
|
const totalHeight = height ?? (vertical ? 320 : void 0);
|
|
18298
|
-
const plotHeight = totalHeight == null ? Math.max(1, categories.length) * minBand(
|
|
18436
|
+
const plotHeight = totalHeight == null ? Math.max(1, categories.length) * minBand(barSlots) : typeof totalHeight === "number" ? Math.max(0, totalHeight - axisText.height) : `calc(${totalHeight} - ${axisText.height}px)`;
|
|
18299
18437
|
const legend = showLegend ? /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { items: series.map((s, i) => ({ name: s.name, color: colorAt(i, 0) })) }) : null;
|
|
18300
18438
|
const handleMove = (event) => {
|
|
18301
18439
|
if (!showTooltip || categories.length === 0 || series.length === 0) return;
|
|
@@ -18352,7 +18490,7 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18352
18490
|
}
|
|
18353
18491
|
);
|
|
18354
18492
|
const bars = react.useMemo(
|
|
18355
|
-
() => size.width > 0 && size.height > 0 ? series.flatMap(
|
|
18493
|
+
() => !stacked && size.width > 0 && size.height > 0 ? series.flatMap(
|
|
18356
18494
|
(s, seriesIndex) => categories.map((_, categoryIndex) => {
|
|
18357
18495
|
const value = s.data[categoryIndex];
|
|
18358
18496
|
if (value == null || !Number.isFinite(value)) return null;
|
|
@@ -18429,9 +18567,105 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18429
18567
|
formatValue,
|
|
18430
18568
|
onBarClick,
|
|
18431
18569
|
colorAt,
|
|
18432
|
-
hoveredCategory
|
|
18570
|
+
hoveredCategory,
|
|
18571
|
+
stacked
|
|
18433
18572
|
]
|
|
18434
18573
|
);
|
|
18574
|
+
const stackedBars = react.useMemo(() => {
|
|
18575
|
+
if (!stacked || size.width <= 0 || size.height <= 0) return [];
|
|
18576
|
+
const pxOf = (value) => vertical ? size.height - ratioOf(value, scale) * size.height : ratioOf(value, scale) * size.width;
|
|
18577
|
+
return categories.map((_, categoryIndex) => {
|
|
18578
|
+
const dimmed = hoveredCategory != null && hoveredCategory !== categoryIndex;
|
|
18579
|
+
const barStart = layout.offset + categoryIndex * layout.band + (layout.band - layout.bar) / 2;
|
|
18580
|
+
let positive = 0;
|
|
18581
|
+
let negative = 0;
|
|
18582
|
+
const segments = series.flatMap((s, seriesIndex) => {
|
|
18583
|
+
const value = s.data[categoryIndex];
|
|
18584
|
+
if (value == null || !Number.isFinite(value) || value === 0) return [];
|
|
18585
|
+
const from = value < 0 ? negative + value : positive;
|
|
18586
|
+
const to = value < 0 ? negative : positive + value;
|
|
18587
|
+
if (value < 0) negative += value;
|
|
18588
|
+
else positive += value;
|
|
18589
|
+
return [{ seriesIndex, name: s.name, value, from, to }];
|
|
18590
|
+
});
|
|
18591
|
+
if (segments.length === 0) return null;
|
|
18592
|
+
const boxOf = (from, to) => {
|
|
18593
|
+
const a = pxOf(from);
|
|
18594
|
+
const b = pxOf(to);
|
|
18595
|
+
return vertical ? { x: barStart, y: Math.min(a, b), width: layout.bar, height: Math.abs(a - b) } : { x: Math.min(a, b), y: barStart, width: Math.abs(a - b), height: layout.bar };
|
|
18596
|
+
};
|
|
18597
|
+
const outlineOf = (extent, negativeSide) => {
|
|
18598
|
+
const box3 = negativeSide ? boxOf(extent, 0) : boxOf(0, extent);
|
|
18599
|
+
return barPath(box3.x, box3.y, box3.width, box3.height, direction, negativeSide);
|
|
18600
|
+
};
|
|
18601
|
+
const positiveClip = `${clipId}-p-${categoryIndex}`;
|
|
18602
|
+
const negativeClip = `${clipId}-n-${categoryIndex}`;
|
|
18603
|
+
const total = positive + negative;
|
|
18604
|
+
const outer = pxOf(total >= 0 ? positive : negative);
|
|
18605
|
+
const labelX = vertical ? barStart + layout.bar / 2 : total >= 0 ? outer + VALUE_LABEL_GAP : outer - VALUE_LABEL_GAP;
|
|
18606
|
+
const labelY = vertical ? total >= 0 ? outer - VALUE_LABEL_GAP : outer + VALUE_LABEL_GAP + 10 : barStart + layout.bar / 2;
|
|
18607
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
18608
|
+
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
18609
|
+
positive > 0 && /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: positiveClip, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: outlineOf(positive, false) }) }),
|
|
18610
|
+
negative < 0 && /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: negativeClip, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: outlineOf(negative, true) }) })
|
|
18611
|
+
] }),
|
|
18612
|
+
segments.map((segment) => {
|
|
18613
|
+
const box3 = boxOf(segment.from, segment.to);
|
|
18614
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18615
|
+
"rect",
|
|
18616
|
+
{
|
|
18617
|
+
x: box3.x,
|
|
18618
|
+
y: box3.y,
|
|
18619
|
+
width: box3.width,
|
|
18620
|
+
height: box3.height,
|
|
18621
|
+
clipPath: `url(#${segment.value < 0 ? negativeClip : positiveClip})`,
|
|
18622
|
+
style: {
|
|
18623
|
+
fill: colorAt(segment.seriesIndex, categoryIndex),
|
|
18624
|
+
// 흐림은 조각에만 건다 — 묶음에 걸면 합계 라벨까지 같이 흐려진다.
|
|
18625
|
+
opacity: dimmed ? BAR_OPACITY_DIMMED : BAR_OPACITY_DEFAULT,
|
|
18626
|
+
cursor: onBarClick ? "pointer" : void 0
|
|
18627
|
+
},
|
|
18628
|
+
onClick: onBarClick ? () => onBarClick({
|
|
18629
|
+
seriesIndex: segment.seriesIndex,
|
|
18630
|
+
categoryIndex,
|
|
18631
|
+
value: segment.value
|
|
18632
|
+
}) : void 0,
|
|
18633
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("title", { children: `${categories[categoryIndex]} ${segment.name} ${formatValue(segment.value)}` })
|
|
18634
|
+
},
|
|
18635
|
+
segment.seriesIndex
|
|
18636
|
+
);
|
|
18637
|
+
}),
|
|
18638
|
+
showValueLabel && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18639
|
+
"text",
|
|
18640
|
+
{
|
|
18641
|
+
x: labelX,
|
|
18642
|
+
y: labelY,
|
|
18643
|
+
className: "typo-body-sm-medium",
|
|
18644
|
+
style: { fill: BAR_VALUE_COLOR },
|
|
18645
|
+
textAnchor: vertical ? "middle" : total >= 0 ? "start" : "end",
|
|
18646
|
+
dominantBaseline: vertical ? "auto" : "central",
|
|
18647
|
+
children: formatValue(total)
|
|
18648
|
+
}
|
|
18649
|
+
)
|
|
18650
|
+
] }, categoryIndex);
|
|
18651
|
+
});
|
|
18652
|
+
}, [
|
|
18653
|
+
stacked,
|
|
18654
|
+
size.width,
|
|
18655
|
+
size.height,
|
|
18656
|
+
series,
|
|
18657
|
+
categories,
|
|
18658
|
+
layout,
|
|
18659
|
+
scale,
|
|
18660
|
+
vertical,
|
|
18661
|
+
direction,
|
|
18662
|
+
showValueLabel,
|
|
18663
|
+
formatValue,
|
|
18664
|
+
onBarClick,
|
|
18665
|
+
colorAt,
|
|
18666
|
+
hoveredCategory,
|
|
18667
|
+
clipId
|
|
18668
|
+
]);
|
|
18435
18669
|
const axisLabels = /* @__PURE__ */ jsxRuntime.jsx(
|
|
18436
18670
|
ChartAxisLabels,
|
|
18437
18671
|
{
|
|
@@ -18465,7 +18699,7 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18465
18699
|
width: size.width,
|
|
18466
18700
|
height: size.height,
|
|
18467
18701
|
role: "img",
|
|
18468
|
-
"aria-label": `${categories.length}\uAC1C \uD56D\uBAA9, ${series.length}\uAC1C \uACC4\uC5F4 \uB9C9\uB300 \uADF8\uB798\uD504`,
|
|
18702
|
+
"aria-label": `${categories.length}\uAC1C \uD56D\uBAA9, ${series.length}\uAC1C \uACC4\uC5F4 ${stacked ? "\uB204\uC801 " : ""}\uB9C9\uB300 \uADF8\uB798\uD504`,
|
|
18469
18703
|
children: [
|
|
18470
18704
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18471
18705
|
ChartGrid,
|
|
@@ -18490,7 +18724,7 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18490
18724
|
}
|
|
18491
18725
|
}
|
|
18492
18726
|
),
|
|
18493
|
-
bars
|
|
18727
|
+
stacked ? stackedBars : bars
|
|
18494
18728
|
]
|
|
18495
18729
|
}
|
|
18496
18730
|
),
|