sellmate-design-system-react 9.0.0-beta.32 → 9.0.0-beta.33
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 +7 -2
- package/dist/components/SGnb/SGnb.d.ts +6 -0
- package/dist/components/SGnb/gnb.config.d.ts +3 -3
- package/dist/components/SGnbSystem/README.md +43 -1
- package/dist/components/SGnbSystem/SGnbSystem.d.ts +48 -2
- package/dist/components/SPortal/README.md +2 -0
- package/dist/components/STooltip/README.md +2 -0
- package/dist/index.cjs +90 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +90 -17
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +50 -3
- package/dist/llms.txt +7 -2
- package/dist/styles.css +18 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -1618,7 +1618,7 @@ export default function AppShell({
|
|
|
1618
1618
|
```tsx
|
|
1619
1619
|
{/* 폭을 기억해야 하면 menuWidth 를 앱이 쥐고 onMenuWidthChange 로 되받아 저장한다.
|
|
1620
1620
|
초기값만 정하면 되면 defaultMenuWidth 하나로 끝난다. */}
|
|
1621
|
-
<SGnb items={MENU} value={current} onValueChange={navigate} resizable defaultMenuWidth={
|
|
1621
|
+
<SGnb items={MENU} value={current} onValueChange={navigate} resizable defaultMenuWidth={220} />
|
|
1622
1622
|
```
|
|
1623
1623
|
|
|
1624
1624
|
`onMenuWidthChange` 는 **드래그를 놓는 순간**(또는 방향키 조작) 한 번만 온다 — 저장 로직을 그대로 붙여도 프레임마다 쓰이지 않는다. 접혀 있거나 레일 리프가 활성이라 깔 메뉴가 없으면 조절선은 나오지 않는다.
|
|
@@ -1739,7 +1739,12 @@ import { SModalOutlet } from 'sellmate-design-system-react';
|
|
|
1739
1739
|
- **`header="fix"` 를 접으면 알림·계정 아이콘만 남는다** — `actions`·`domain`·`setting` 은 48px 폭에 놓을 자리가 없어 렌더되지 않고, 알림 개수는 점 배지가 된다. **알림도 계정도 안 쓰는 조합이면 접힌 패널은 아예 렌더되지 않는다** — 접힌 상태에서도 반드시 눌러야 하는 것이 그 둘 밖에 있으면 `foldedTop`/`foldedFooter` 로 따로 준다.
|
|
1740
1740
|
- **`header="full"` 은 접어도 상단바가 남으므로 조각들도 그대로 남는다.** 대신 가로로 자리가 넉넉하지 않아 알림·설정이 라벨을 벗고 아이콘(알림은 개수까지)만 남는다 — 이건 컴포넌트가 알아서 하므로 앱이 라벨을 지우지 않는다.
|
|
1741
1741
|
- **`account` 를 쓰면 `account.listBox` 가 필수다** (§3-5-8) — 계정 행을 누르면 이메일·이름·권한과 계정 설정·언어 변경·로그아웃이 예외 없이 뜬다. 뜨는 방향은 판이 놓인 자리가 정하므로 앱이 넘기지 않는다 — 판이면 계정 행 위로, 상단바면 아래로 펼치고, 접힌 레일도 판과 같다. `account.onClick` 은 패널을 여는 것 말고 따로 할 일(로깅 등)이 있을 때만 준다.
|
|
1742
|
-
- **알림 개수는 `alert.count` 하나로 표현한다.** 1 이상이면 벨이 울리는 아이콘과 강조색으로 바뀐다 — 색은 GNB 색이 정하므로 앱이 직접 칠하지 않는다.
|
|
1742
|
+
- **알림 개수는 `alert.count` 하나로 표현한다.** 1 이상이면 벨이 울리는 아이콘과 강조색으로 바뀐다 — 색은 GNB 색이 정하므로 앱이 직접 칠하지 않는다. **`resizable` 로 메뉴를 기본 폭보다 좁게 줄이면 개수를 적을 가로가 모자라 접힘과 같은 점 배지로 바뀐다** — 컴포넌트가 알아서 하므로 앱이 폭을 보고 `count` 를 지우지 않는다.
|
|
1743
|
+
- **알림을 눌러 뜨는 목록은 `alert.listBox` 에 내용만 넘긴다** — `SPortal` 을 따로 띄워 알림 버튼에 붙이지 않는다. 목록에 무엇을 쌓을지는 서비스마다 다르지만 **뜨는 자리는 늘 같아야 하므로**, 방향(판·접힌 레일은 버튼 오른쪽 · 상단바는 아래로 오른쪽 끝)과 바깥 클릭·ESC 닫힘, 배경·라운드·그림자는 컴포넌트가 쥔다. 여닫는 일도 알림 버튼이 하므로 **`onOpenChange` 는 그 사실을 알아야 할 때만** 받는다(연 김에 읽음 처리하는 화면 등) — 이 값으로 목록을 대신 열거나 막지 않는다. 계정 행(`account.listBox`)과 같은 규칙이다.
|
|
1744
|
+
- **알림에 안내 툴팁을 띄우려면 `alert.tooltip` 에 문구만 넘긴다** — `STooltip` 을 직접 세워 알림 버튼에 붙이지 않는다. 색(판이 light 면 기본 · 그 밖은 강조)과 방향(판·접힌 레일은 오른쪽 · 상단바는 아래)은 자리가 정하고, 스스로 사라지지 않다가 **알림을 누르거나 버튼에서 커서를 뺄 때** 닫힌다.
|
|
1745
|
+
- **닫힘은 `onTooltipDismiss` 로 받아 `tooltip` 을 비워 둔다.** 같은 값을 계속 넘기는 동안에는 다시 뜨지 않고, **비웠다 다시 넘기면 문구가 같아도 새 안내로 뜬다** — 새 알림마다 같은 안내를 다시 띄우는 화면이 막히지 않는다.
|
|
1746
|
+
- 재노출 신호는 문구가 **없음 → 있음** 으로 바뀌는 것이다. 한 이벤트 핸들러 안에서 비웠다 곧바로 넣으면 렌더가 한 번으로 묶여 신호가 되지 않는다 — 닫을 때 비우고, 다시 필요할 때 넘긴다.
|
|
1747
|
+
- 컴포넌트가 아는 범위는 그 자리가 서 있는 동안뿐이다(새로고침하거나 GNB 를 접어 알림이 다른 자리로 옮겨 서면 새로 마운트된다). **그 사용자에게 두 번 다시 보이지 않아야 하면 앱이 닫힘을 저장해 두고 `tooltip` 을 넘기지 않는다.**
|
|
1743
1748
|
- **`header="fix"` + `useRail` 에서 하위 메뉴가 없는 레일 아이템이 활성이면 메뉴 컬럼째 사라지므로 이 패널도 함께 빠진다.** 항상 보여야 하는 계정·알림이라면 그런 레일 리프를 두지 않는다 — 또는 `header="full"` 로 두면 상단바에 남는다(그런 레일 리프가 있으면 GNB 가 `header` 를 `full` 로 강제한다).
|
|
1744
1749
|
|
|
1745
1750
|
### 4-2. 목록 페이지 (필터 + 테이블)
|
|
@@ -32,6 +32,12 @@ export interface SGnbSystemContextValue {
|
|
|
32
32
|
* 것을 스스로 닫아야 하고, 그 신호가 이 값이다.
|
|
33
33
|
*/
|
|
34
34
|
active: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* 이 자리가 메뉴 기본 폭(GNB_MENU_WIDTH)보다 좁은가 — `resizable` 로 줄인 메뉴 컬럼이 그렇다.
|
|
37
|
+
* 좁아진 판에서는 알림 개수를 적을 가로가 모자라 개수 대신 점 배지가 붙는다.
|
|
38
|
+
* 없으면 좁지 않은 것으로 본다(접힘 레일·상단바는 자기 규칙을 따르므로 이 값과 무관하다).
|
|
39
|
+
*/
|
|
40
|
+
narrow?: boolean;
|
|
35
41
|
}
|
|
36
42
|
export declare const SGnbSystemContext: import("react").Context<SGnbSystemContextValue | null>;
|
|
37
43
|
export interface SGnbProps extends Omit<HTMLAttributes<HTMLDivElement>, 'color'> {
|
|
@@ -116,13 +116,13 @@ export declare const GNB_EXPAND_MS = 200;
|
|
|
116
116
|
* 메뉴 고정 폭. 두 header 모두 메뉴는 이 폭으로 좌측에 붙는다(토큰 없음 → 상수).
|
|
117
117
|
* header="full" 에서 SLayout 이 "메뉴 오른쪽 = 페이지" 영역을 잡을 때도 이 값을 쓴다.
|
|
118
118
|
*/
|
|
119
|
-
export declare const GNB_MENU_WIDTH =
|
|
119
|
+
export declare const GNB_MENU_WIDTH = 214;
|
|
120
120
|
/**
|
|
121
121
|
* resizable 일 때 메뉴 폭이 움직일 수 있는 범위(px). 레일 폭은 고정이고 메뉴 컬럼만 늘고 준다.
|
|
122
|
-
*
|
|
122
|
+
* 기본 폭(GNB_MENU_WIDTH)이 이 범위 안에 있다. 대응 토큰이 없어 상수로 둔다.
|
|
123
123
|
*/
|
|
124
124
|
export declare const GNB_MENU_MIN_WIDTH = 200;
|
|
125
|
-
export declare const GNB_MENU_MAX_WIDTH =
|
|
125
|
+
export declare const GNB_MENU_MAX_WIDTH = 240;
|
|
126
126
|
/** 메뉴 폭 조절에서 방향키 한 번에 움직이는 양(px). Shift 를 함께 누르면 large. */
|
|
127
127
|
export declare const GNB_MENU_RESIZE_KEY_STEP: {
|
|
128
128
|
normal: number;
|
|
@@ -52,12 +52,50 @@ export interface SGnbSystemAlert {
|
|
|
52
52
|
/** 라벨 텍스트. 기본 `'알림'` */
|
|
53
53
|
label?: string;
|
|
54
54
|
/**
|
|
55
|
-
* 읽지 않은 알림 개수. 1 이상이면 벨이 울리는 아이콘·강조색으로 바뀌고
|
|
55
|
+
* 읽지 않은 알림 개수. 1 이상이면 벨이 울리는 아이콘·강조색으로 바뀌고 개수가 붙는다.
|
|
56
|
+
* 개수를 적을 가로가 모자란 자리(접힌 레일 · 기본 폭보다 좁게 줄인 판)에서는 점 배지로 바뀐다.
|
|
56
57
|
* 표기는 컴포넌트가 맡는다 — 세 자리마다 콤마를 넣어 그리므로 앱이 포맷한 문자열을 넘기지 않는다.
|
|
57
58
|
*/
|
|
58
59
|
count?: number;
|
|
59
60
|
/** 클릭 */
|
|
60
61
|
onClick?: () => void;
|
|
62
|
+
/**
|
|
63
|
+
* 알림 버튼에 붙는 안내 툴팁의 문구(한 줄이 한 항목). 주면 뜬다 — **문구만 앱이 정하고**
|
|
64
|
+
* 색·방향·여닫힘은 컴포넌트가 쥔다: 색은 판이 light 면 기본, 그 밖(dark·상단바)이면 강조색이고
|
|
65
|
+
* 방향은 자리가 정한다(판·접힌 레일이면 오른쪽, 상단바면 아래).
|
|
66
|
+
*
|
|
67
|
+
* 스스로 사라지지 않는다 — **알림 버튼을 누르거나, 버튼에 얹었다 커서를 뺄 때** 닫히고,
|
|
68
|
+
* 같은 값을 계속 넘기는 동안에는 다시 뜨지 않는다.
|
|
69
|
+
*
|
|
70
|
+
* **다시 띄우려면 비웠다가 다시 넘긴다**(`undefined` → 문구). 문구가 같아도 상관없다 —
|
|
71
|
+
* 컴포넌트는 닫았다는 사실만 기억하고 문구 내용은 기억하지 않으므로, 새 알림마다 같은 안내를
|
|
72
|
+
* 다시 띄우는 화면도 막히지 않는다.
|
|
73
|
+
*/
|
|
74
|
+
tooltip?: string[];
|
|
75
|
+
/**
|
|
76
|
+
* 알림을 누르면 뜨는 목록의 **내용**. 주면 컴포넌트가 알림 버튼에 붙여 띄운다 —
|
|
77
|
+
* 목록에 무엇을 쌓을지는 서비스마다 다르지만 **뜨는 자리는 늘 같아야 하므로**, 방향·앵커·
|
|
78
|
+
* 여닫힘(바깥 클릭·ESC 포함)과 배경·라운드·그림자는 컴포넌트가 쥐고 앱은 안에 담을 것만 준다.
|
|
79
|
+
* 방향은 자리가 정한다 — 판·접힌 레일이면 버튼 오른쪽, 상단바면 아래.
|
|
80
|
+
*/
|
|
81
|
+
listBox?: ReactNode;
|
|
82
|
+
/**
|
|
83
|
+
* 알림 목록이 열리고 닫힐 때. 여닫는 것은 알림 버튼이 스스로 하므로 **그 사실을 알아야 할
|
|
84
|
+
* 때만** 준다(연 김에 읽음 처리하거나, 열려 있는 동안 다른 층을 접어 두는 화면).
|
|
85
|
+
*
|
|
86
|
+
* 앱이 누르지 않은 닫힘도 온다: GNB 를 접거나 펴면 알림 버튼이 다른 자리로 옮겨 서므로
|
|
87
|
+
* 목록이 닫히고 `false` 가 온다(계정 행과 같다).
|
|
88
|
+
*/
|
|
89
|
+
onOpenChange?: (open: boolean) => void;
|
|
90
|
+
/**
|
|
91
|
+
* 안내 툴팁이 닫힐 때. 받아서 `tooltip` 을 비워 두는 것이 기본 사용법이다 — 그러면 앱이
|
|
92
|
+
* 다음에 넘기는 문구가 곧 다음 안내가 된다.
|
|
93
|
+
*
|
|
94
|
+
* 컴포넌트가 아는 "다시 뜨지 않는다" 는 **이 자리가 서 있는 동안**뿐이라(새로고침하거나
|
|
95
|
+
* GNB 를 접어 알림이 다른 자리로 옮겨 서면 새로 마운트된다), 그 사용자에게 두 번 다시 보이지
|
|
96
|
+
* 않아야 하면 앱이 이 신호를 저장해 두고 `tooltip` 을 그만 넘긴다.
|
|
97
|
+
*/
|
|
98
|
+
onTooltipDismiss?: () => void;
|
|
61
99
|
}
|
|
62
100
|
```
|
|
63
101
|
|
|
@@ -130,7 +168,9 @@ export const GNB_SYSTEM_COLORS = ['light', 'dark'] as const;
|
|
|
130
168
|
- [SAccountListBox](../SAccountListBox)
|
|
131
169
|
- [SGnb](../SGnb)
|
|
132
170
|
- [SIcon](../SIcon)
|
|
171
|
+
- [SPortal](../SPortal)
|
|
133
172
|
- [SSystemActionButton](../SSystemActionButton)
|
|
173
|
+
- [STooltip](../STooltip)
|
|
134
174
|
|
|
135
175
|
### Graph
|
|
136
176
|
|
|
@@ -139,6 +179,8 @@ graph TD;
|
|
|
139
179
|
SGnbSystem --> SAccountListBox
|
|
140
180
|
SGnbSystem --> SGnb
|
|
141
181
|
SGnbSystem --> SIcon
|
|
182
|
+
SGnbSystem --> SPortal
|
|
142
183
|
SGnbSystem --> SSystemActionButton
|
|
184
|
+
SGnbSystem --> STooltip
|
|
143
185
|
style SGnbSystem fill:#f9f,stroke:#333,stroke-width:4px
|
|
144
186
|
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type HTMLAttributes } from 'react';
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
2
|
import { type SAccountListBoxContent } from '../SAccountListBox';
|
|
3
3
|
import { type SSystemActionButtonProps } from '../SSystemActionButton';
|
|
4
4
|
import { type SGnbSystemColor } from './gnbSystem.config';
|
|
@@ -23,12 +23,50 @@ export interface SGnbSystemAlert {
|
|
|
23
23
|
/** 라벨 텍스트. 기본 `'알림'` */
|
|
24
24
|
label?: string;
|
|
25
25
|
/**
|
|
26
|
-
* 읽지 않은 알림 개수. 1 이상이면 벨이 울리는 아이콘·강조색으로 바뀌고
|
|
26
|
+
* 읽지 않은 알림 개수. 1 이상이면 벨이 울리는 아이콘·강조색으로 바뀌고 개수가 붙는다.
|
|
27
|
+
* 개수를 적을 가로가 모자란 자리(접힌 레일 · 기본 폭보다 좁게 줄인 판)에서는 점 배지로 바뀐다.
|
|
27
28
|
* 표기는 컴포넌트가 맡는다 — 세 자리마다 콤마를 넣어 그리므로 앱이 포맷한 문자열을 넘기지 않는다.
|
|
28
29
|
*/
|
|
29
30
|
count?: number;
|
|
30
31
|
/** 클릭 */
|
|
31
32
|
onClick?: () => void;
|
|
33
|
+
/**
|
|
34
|
+
* 알림 버튼에 붙는 안내 툴팁의 문구(한 줄이 한 항목). 주면 뜬다 — **문구만 앱이 정하고**
|
|
35
|
+
* 색·방향·여닫힘은 컴포넌트가 쥔다: 색은 판이 light 면 기본, 그 밖(dark·상단바)이면 강조색이고
|
|
36
|
+
* 방향은 자리가 정한다(판·접힌 레일이면 오른쪽, 상단바면 아래).
|
|
37
|
+
*
|
|
38
|
+
* 스스로 사라지지 않는다 — **알림 버튼을 누르거나, 버튼에 얹었다 커서를 뺄 때** 닫히고,
|
|
39
|
+
* 같은 값을 계속 넘기는 동안에는 다시 뜨지 않는다.
|
|
40
|
+
*
|
|
41
|
+
* **다시 띄우려면 비웠다가 다시 넘긴다**(`undefined` → 문구). 문구가 같아도 상관없다 —
|
|
42
|
+
* 컴포넌트는 닫았다는 사실만 기억하고 문구 내용은 기억하지 않으므로, 새 알림마다 같은 안내를
|
|
43
|
+
* 다시 띄우는 화면도 막히지 않는다.
|
|
44
|
+
*/
|
|
45
|
+
tooltip?: string[];
|
|
46
|
+
/**
|
|
47
|
+
* 알림을 누르면 뜨는 목록의 **내용**. 주면 컴포넌트가 알림 버튼에 붙여 띄운다 —
|
|
48
|
+
* 목록에 무엇을 쌓을지는 서비스마다 다르지만 **뜨는 자리는 늘 같아야 하므로**, 방향·앵커·
|
|
49
|
+
* 여닫힘(바깥 클릭·ESC 포함)과 배경·라운드·그림자는 컴포넌트가 쥐고 앱은 안에 담을 것만 준다.
|
|
50
|
+
* 방향은 자리가 정한다 — 판·접힌 레일이면 버튼 오른쪽, 상단바면 아래.
|
|
51
|
+
*/
|
|
52
|
+
listBox?: ReactNode;
|
|
53
|
+
/**
|
|
54
|
+
* 알림 목록이 열리고 닫힐 때. 여닫는 것은 알림 버튼이 스스로 하므로 **그 사실을 알아야 할
|
|
55
|
+
* 때만** 준다(연 김에 읽음 처리하거나, 열려 있는 동안 다른 층을 접어 두는 화면).
|
|
56
|
+
*
|
|
57
|
+
* 앱이 누르지 않은 닫힘도 온다: GNB 를 접거나 펴면 알림 버튼이 다른 자리로 옮겨 서므로
|
|
58
|
+
* 목록이 닫히고 `false` 가 온다(계정 행과 같다).
|
|
59
|
+
*/
|
|
60
|
+
onOpenChange?: (open: boolean) => void;
|
|
61
|
+
/**
|
|
62
|
+
* 안내 툴팁이 닫힐 때. 받아서 `tooltip` 을 비워 두는 것이 기본 사용법이다 — 그러면 앱이
|
|
63
|
+
* 다음에 넘기는 문구가 곧 다음 안내가 된다.
|
|
64
|
+
*
|
|
65
|
+
* 컴포넌트가 아는 "다시 뜨지 않는다" 는 **이 자리가 서 있는 동안**뿐이라(새로고침하거나
|
|
66
|
+
* GNB 를 접어 알림이 다른 자리로 옮겨 서면 새로 마운트된다), 그 사용자에게 두 번 다시 보이지
|
|
67
|
+
* 않아야 하면 앱이 이 신호를 저장해 두고 `tooltip` 을 그만 넘긴다.
|
|
68
|
+
*/
|
|
69
|
+
onTooltipDismiss?: () => void;
|
|
32
70
|
}
|
|
33
71
|
/** 설정 버튼 */
|
|
34
72
|
export interface SGnbSystemSetting {
|
|
@@ -121,6 +159,14 @@ export interface SGnbSystemProps extends Omit<HTMLAttributes<HTMLDivElement>, 'c
|
|
|
121
159
|
* `alert.count` 가 1 이상이면 벨이 울리는 아이콘(`bellRinging`)과 강조색으로 바뀐다 — light 는 파랑,
|
|
122
160
|
* 어두운 면은 노랑(토큰이 정한다). 0 이거나 없으면 조용한 벨(`bell`)에 기본 색이다.
|
|
123
161
|
*
|
|
162
|
+
* 안내 툴팁(`alert.tooltip`)은 문구를 받은 동안 떠 있다가 알림을 누르거나 커서를 빼면 닫힌다.
|
|
163
|
+
* 다시 띄우는 신호는 문구가 **없음 → 있음** 으로 바뀌는 것이라, 같은 문구도 비웠다 다시 넘기면
|
|
164
|
+
* 새 안내로 뜬다.
|
|
165
|
+
*
|
|
166
|
+
* 판이 **메뉴 기본 폭보다 좁으면**(GNB 의 `resizable` 로 줄인 컬럼) 알림 개수를 적을 가로가
|
|
167
|
+
* 모자라 접힘과 같은 점 배지로 바뀐다 — 숫자가 설정 버튼을 밀어내거나 잘리는 대신, 알림이
|
|
168
|
+
* 있다는 사실만 남긴다. 좁은지는 담은 SGnb 가 내려주므로 앱이 고르는 prop 이 없다.
|
|
169
|
+
*
|
|
124
170
|
* 색은 놓인 면을 따른다: 판 위는 `light`/`dark`(오션블루 판), 판 없이 상단바 면에 바로 얹는 `top` 의
|
|
125
171
|
* dark 는 한 단계 어두운 `darker`(네이비) 색표다 — GNB_SYSTEM_TOP_COLOR_CONFIG 가 그 대응을 쥔다.
|
|
126
172
|
*
|
|
@@ -54,6 +54,7 @@ export type SPortalAlign = 'start' | 'center' | 'end';
|
|
|
54
54
|
|
|
55
55
|
- [SAccountListBox](../SAccountListBox)
|
|
56
56
|
- [SChipInput](../SChipInput)
|
|
57
|
+
- [SGnbSystem](../SGnbSystem)
|
|
57
58
|
- [SSelect](../SSelect)
|
|
58
59
|
|
|
59
60
|
### Graph
|
|
@@ -62,6 +63,7 @@ export type SPortalAlign = 'start' | 'center' | 'end';
|
|
|
62
63
|
graph TD;
|
|
63
64
|
SAccountListBox --> SPortal
|
|
64
65
|
SChipInput --> SPortal
|
|
66
|
+
SGnbSystem --> SPortal
|
|
65
67
|
SSelect --> SPortal
|
|
66
68
|
style SPortal fill:#f9f,stroke:#333,stroke-width:4px
|
|
67
69
|
```
|
|
@@ -66,6 +66,7 @@ export type STooltipType = 'default' | 'danger' | 'warning' | 'accent';
|
|
|
66
66
|
|
|
67
67
|
- [SChipFilter](../SChipFilter)
|
|
68
68
|
- [SField](../SField)
|
|
69
|
+
- [SGnbSystem](../SGnbSystem)
|
|
69
70
|
- [SKeyValueTable](../SKeyValueTable)
|
|
70
71
|
- [SSectionHeaderCard](../SSectionHeaderCard)
|
|
71
72
|
- [SStepper](../SStepper)
|
|
@@ -84,6 +85,7 @@ graph TD;
|
|
|
84
85
|
STooltip --> SIcon
|
|
85
86
|
SChipFilter --> STooltip
|
|
86
87
|
SField --> STooltip
|
|
88
|
+
SGnbSystem --> STooltip
|
|
87
89
|
SKeyValueTable --> STooltip
|
|
88
90
|
SSectionHeaderCard --> STooltip
|
|
89
91
|
SStepper --> STooltip
|
package/dist/index.cjs
CHANGED
|
@@ -9270,9 +9270,9 @@ var GNB_RAIL = {
|
|
|
9270
9270
|
var GNB_RAIL_WIDTH = 68;
|
|
9271
9271
|
var GNB_FOLD_MS = 200;
|
|
9272
9272
|
var GNB_EXPAND_MS = 200;
|
|
9273
|
-
var GNB_MENU_WIDTH =
|
|
9273
|
+
var GNB_MENU_WIDTH = 214;
|
|
9274
9274
|
var GNB_MENU_MIN_WIDTH = 200;
|
|
9275
|
-
var GNB_MENU_MAX_WIDTH =
|
|
9275
|
+
var GNB_MENU_MAX_WIDTH = 240;
|
|
9276
9276
|
var GNB_MENU_RESIZE_KEY_STEP = { normal: 10, large: 50 };
|
|
9277
9277
|
var clampGnbMenuWidth = (width) => Math.min(GNB_MENU_MAX_WIDTH, Math.max(GNB_MENU_MIN_WIDTH, Math.round(width)));
|
|
9278
9278
|
var GNB_FULL_LOGO_WIDTH = 140;
|
|
@@ -9830,8 +9830,15 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
|
|
|
9830
9830
|
"topContent"
|
|
9831
9831
|
) : null;
|
|
9832
9832
|
const systemMenuContext = react.useMemo(
|
|
9833
|
-
|
|
9834
|
-
|
|
9833
|
+
// 기본 폭보다 줄여 놓은 메뉴 컬럼이면 판에 알린다 — 알림 개수가 점 배지로 줄어든다.
|
|
9834
|
+
() => ({
|
|
9835
|
+
color,
|
|
9836
|
+
folded: false,
|
|
9837
|
+
placement: "panel",
|
|
9838
|
+
active: !railFolded,
|
|
9839
|
+
narrow: menuWidth < GNB_MENU_WIDTH
|
|
9840
|
+
}),
|
|
9841
|
+
[color, railFolded, menuWidth]
|
|
9835
9842
|
);
|
|
9836
9843
|
const systemFoldedContext = react.useMemo(
|
|
9837
9844
|
() => ({ color, folded: true, placement: "panel", active: true }),
|
|
@@ -10098,7 +10105,7 @@ var GNB_SYSTEM_SETTING_LABEL = "\uC124\uC815";
|
|
|
10098
10105
|
function TokenIcon3({ name, size }) {
|
|
10099
10106
|
return /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name, size: "100%", style: { width: size, height: size } });
|
|
10100
10107
|
}
|
|
10101
|
-
|
|
10108
|
+
var SystemButton = /* @__PURE__ */ react.forwardRef(function SystemButton2({
|
|
10102
10109
|
color,
|
|
10103
10110
|
icon,
|
|
10104
10111
|
label,
|
|
@@ -10110,21 +10117,22 @@ function SystemButton({
|
|
|
10110
10117
|
dot,
|
|
10111
10118
|
accentColor,
|
|
10112
10119
|
stretch,
|
|
10113
|
-
buttonRef,
|
|
10114
10120
|
hasPopup,
|
|
10115
10121
|
expanded,
|
|
10116
|
-
onClick
|
|
10117
|
-
|
|
10122
|
+
onClick,
|
|
10123
|
+
onMouseLeave
|
|
10124
|
+
}, ref) {
|
|
10118
10125
|
const c = SYSTEM_ACTION_BUTTON_COLOR_CONFIG[color];
|
|
10119
10126
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10120
10127
|
"button",
|
|
10121
10128
|
{
|
|
10122
|
-
ref
|
|
10129
|
+
ref,
|
|
10123
10130
|
type: "button",
|
|
10124
10131
|
"aria-label": label ? void 0 : ariaLabel,
|
|
10125
10132
|
"aria-haspopup": hasPopup ? "dialog" : void 0,
|
|
10126
10133
|
"aria-expanded": hasPopup ? expanded : void 0,
|
|
10127
10134
|
onClick,
|
|
10135
|
+
onMouseLeave,
|
|
10128
10136
|
className: cn(
|
|
10129
10137
|
"group box-border flex cursor-pointer items-center border-none bg-(--gsb-bg) text-(--gsb-text) transition-colors hover:bg-(--gsb-bg-hover)",
|
|
10130
10138
|
stretch ? "min-w-0 flex-1" : "shrink-0",
|
|
@@ -10175,7 +10183,7 @@ function SystemButton({
|
|
|
10175
10183
|
]
|
|
10176
10184
|
}
|
|
10177
10185
|
);
|
|
10178
|
-
}
|
|
10186
|
+
});
|
|
10179
10187
|
var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
|
|
10180
10188
|
color: colorProp,
|
|
10181
10189
|
folded: foldedProp,
|
|
@@ -10194,6 +10202,7 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
|
|
|
10194
10202
|
const isTop = placement === "top";
|
|
10195
10203
|
const folded = !isTop && (foldedProp ?? gnb2?.folded ?? false);
|
|
10196
10204
|
const active = gnb2?.active ?? true;
|
|
10205
|
+
const narrow = !isTop && !folded && (gnb2?.narrow ?? false);
|
|
10197
10206
|
const c = GNB_SYSTEM_COLOR_CONFIG[color];
|
|
10198
10207
|
const t = GNB_SYSTEM_TOP_COLOR_CONFIG[color];
|
|
10199
10208
|
const itemColor = isTop ? t.item : color;
|
|
@@ -10212,13 +10221,39 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
|
|
|
10212
10221
|
setAccountOpen(next);
|
|
10213
10222
|
account?.onOpenChange?.(next);
|
|
10214
10223
|
};
|
|
10224
|
+
const alertButtonRef = react.useRef(null);
|
|
10225
|
+
const [alertListOpen, setAlertListOpen] = react.useState(false);
|
|
10226
|
+
const hasAlertList = alert2?.listBox != null;
|
|
10227
|
+
const commitAlertListOpen = (next) => {
|
|
10228
|
+
setAlertListOpen(next);
|
|
10229
|
+
alert2?.onOpenChange?.(next);
|
|
10230
|
+
};
|
|
10215
10231
|
react.useEffect(() => {
|
|
10216
10232
|
if (active || !accountOpen) return;
|
|
10217
10233
|
setAccountOpen(false);
|
|
10218
10234
|
account?.onOpenChange?.(false);
|
|
10219
10235
|
}, [active, accountOpen, account]);
|
|
10236
|
+
react.useEffect(() => {
|
|
10237
|
+
if (active || !alertListOpen) return;
|
|
10238
|
+
setAlertListOpen(false);
|
|
10239
|
+
alert2?.onOpenChange?.(false);
|
|
10240
|
+
}, [active, alertListOpen, alert2]);
|
|
10220
10241
|
const alertCount = alert2?.count ?? 0;
|
|
10221
10242
|
const notified = alertCount > 0;
|
|
10243
|
+
const alertTooltip = (alert2?.tooltip ?? []).filter((line) => line.trim() !== "");
|
|
10244
|
+
const hasAlertTooltip = alertTooltip.length > 0;
|
|
10245
|
+
const [alertTooltipDismissed, setAlertTooltipDismissed] = react.useState(false);
|
|
10246
|
+
const hadAlertTooltip = react.useRef(hasAlertTooltip);
|
|
10247
|
+
if (hadAlertTooltip.current !== hasAlertTooltip) {
|
|
10248
|
+
hadAlertTooltip.current = hasAlertTooltip;
|
|
10249
|
+
if (hasAlertTooltip && alertTooltipDismissed) setAlertTooltipDismissed(false);
|
|
10250
|
+
}
|
|
10251
|
+
const alertTooltipOpen = hasAlertTooltip && active && !alertTooltipDismissed;
|
|
10252
|
+
const dismissAlertTooltip = () => {
|
|
10253
|
+
if (!alertTooltipOpen) return;
|
|
10254
|
+
setAlertTooltipDismissed(true);
|
|
10255
|
+
alert2?.onTooltipDismiss?.();
|
|
10256
|
+
};
|
|
10222
10257
|
const alertLabel = alert2?.label ?? GNB_SYSTEM_ALERT_LABEL;
|
|
10223
10258
|
const settingLabel = setting?.label ?? GNB_SYSTEM_SETTING_LABEL;
|
|
10224
10259
|
const alertButton = alert2 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -10231,13 +10266,51 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
|
|
|
10231
10266
|
paddingX: GNB_SYSTEM_LAYOUT.alertPaddingX,
|
|
10232
10267
|
iconColor: notified ? alertIconColor : void 0,
|
|
10233
10268
|
hoverBg: notified ? alertHoverBg : void 0,
|
|
10234
|
-
count: folded ? void 0 : alertCount,
|
|
10235
|
-
dot: folded && notified,
|
|
10269
|
+
count: folded || narrow ? void 0 : alertCount,
|
|
10270
|
+
dot: (folded || narrow) && notified,
|
|
10236
10271
|
accentColor: alertCountColor,
|
|
10237
10272
|
stretch: !folded && !isTop,
|
|
10238
|
-
|
|
10273
|
+
ref: alertButtonRef,
|
|
10274
|
+
hasPopup: hasAlertList,
|
|
10275
|
+
expanded: alertListOpen,
|
|
10276
|
+
onClick: () => {
|
|
10277
|
+
dismissAlertTooltip();
|
|
10278
|
+
alert2.onClick?.();
|
|
10279
|
+
if (hasAlertList) commitAlertListOpen(!alertListOpen);
|
|
10280
|
+
},
|
|
10281
|
+
onMouseLeave: hasAlertTooltip ? dismissAlertTooltip : void 0
|
|
10239
10282
|
}
|
|
10240
10283
|
);
|
|
10284
|
+
const alertListBox = alert2 && hasAlertList && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10285
|
+
SPortal,
|
|
10286
|
+
{
|
|
10287
|
+
open: alertListOpen && active,
|
|
10288
|
+
onClose: () => commitAlertListOpen(false),
|
|
10289
|
+
anchorRef: alertButtonRef,
|
|
10290
|
+
placement: isTop ? "bottom" : "right",
|
|
10291
|
+
align: "end",
|
|
10292
|
+
offset: 8,
|
|
10293
|
+
viewportPadding: 8,
|
|
10294
|
+
ariaLabel: alert2.label ?? GNB_SYSTEM_ALERT_LABEL,
|
|
10295
|
+
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
10296
|
+
className: "rounded-(--radius-8)",
|
|
10297
|
+
children: alert2.listBox
|
|
10298
|
+
}
|
|
10299
|
+
);
|
|
10300
|
+
const alertNode = alertButton && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10301
|
+
hasAlertTooltip ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
10302
|
+
STooltip2,
|
|
10303
|
+
{
|
|
10304
|
+
trigger: "none",
|
|
10305
|
+
open: alertTooltipOpen,
|
|
10306
|
+
message: alertTooltip,
|
|
10307
|
+
tooltipType: color === "light" ? "default" : "accent",
|
|
10308
|
+
placement: isTop ? "bottom" : "right",
|
|
10309
|
+
children: alertButton
|
|
10310
|
+
}
|
|
10311
|
+
) : alertButton,
|
|
10312
|
+
alertListBox
|
|
10313
|
+
] });
|
|
10241
10314
|
const settingButton = setting && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10242
10315
|
SystemButton,
|
|
10243
10316
|
{
|
|
@@ -10293,7 +10366,7 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
|
|
|
10293
10366
|
)
|
|
10294
10367
|
})
|
|
10295
10368
|
);
|
|
10296
|
-
if (
|
|
10369
|
+
if (alertNode) segments.push({ key: "alert", node: alertNode });
|
|
10297
10370
|
if (settingButton) segments.push({ key: "setting", node: settingButton });
|
|
10298
10371
|
if (domainTag || accountButton) {
|
|
10299
10372
|
segments.push({
|
|
@@ -10351,7 +10424,7 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
|
|
|
10351
10424
|
"data-folded": "",
|
|
10352
10425
|
...rest,
|
|
10353
10426
|
children: [
|
|
10354
|
-
|
|
10427
|
+
alertNode,
|
|
10355
10428
|
account && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10356
10429
|
SystemButton,
|
|
10357
10430
|
{
|
|
@@ -10359,7 +10432,7 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
|
|
|
10359
10432
|
icon: "user",
|
|
10360
10433
|
ariaLabel: account.label ?? "account",
|
|
10361
10434
|
paddingX: GNB_SYSTEM_LAYOUT.alertPaddingX,
|
|
10362
|
-
|
|
10435
|
+
ref: foldedAccountRef,
|
|
10363
10436
|
hasPopup: true,
|
|
10364
10437
|
expanded: accountOpen,
|
|
10365
10438
|
onClick: () => {
|
|
@@ -10405,7 +10478,7 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
|
|
|
10405
10478
|
domainTag,
|
|
10406
10479
|
hasUserBlock && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
10407
10480
|
(alert2 || setting) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: GNB_SYSTEM_LAYOUT.gap }, children: [
|
|
10408
|
-
|
|
10481
|
+
alertNode,
|
|
10409
10482
|
alert2 && setting && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10410
10483
|
"span",
|
|
10411
10484
|
{
|