sellmate-design-system-react 9.0.0-beta.102 → 9.0.0-beta.103
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 +20 -0
- package/dist/components/SIcon/icons.gen.d.ts +3 -0
- package/dist/components/SSelect/README.md +2 -2
- package/dist/components/SSelect/SSelect.d.ts +2 -2
- package/dist/components/SSystemActionButton/README.md +7 -0
- package/dist/components/SSystemActionButton/SSystemActionButton.d.ts +31 -1
- package/dist/index.cjs +255 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +253 -19
- package/dist/index.js.map +1 -1
- package/dist/lib/locale-context.d.ts +26 -0
- package/dist/lib/locale.d.ts +46 -0
- package/dist/llms-full.txt +29 -2
- package/dist/llms.txt +20 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -139,6 +139,8 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
139
139
|
|
|
140
140
|
콤마 없는 `39000` 은 자릿수를 세어야 읽히지만 `39,000` 은 한눈에 읽힌다. 숫자를 그대로 출력하는 코드는 미완성으로 본다.
|
|
141
141
|
|
|
142
|
+
**앱이 `SLocaleProvider` 로 로케일을 바꾸는 경우(§4-1)에는 `useLocale().formatNumber(v)` 로 쓴다** — 선택한 로케일의 숫자 구분을 따른다. 로케일을 바꾸지 않는 앱은 `toLocaleString()` 그대로 쓴다. **날짜는 로케일을 바꿔도 아래 `YYYY-MM-DD` 표기가 그대로다.**
|
|
143
|
+
|
|
142
144
|
**번호·코드는 제외한다.** 전화번호·사업자번호·송장번호·상품코드처럼 대상을 가리키는 값은 크기를 비교하는 숫자가 아니라 **서식이 정해진 문자열**이다. 여기에 콤마를 넣으면 송장번호 `123456789` 가 `123,456,789` 로 보여 값 자체가 달라진다.
|
|
143
145
|
|
|
144
146
|
**날짜는 `YYYY-MM-DD` 로 쓴다.** 자릿수를 채우고 하이픈으로 구분한다 — `2026-08-13`.
|
|
@@ -1559,6 +1561,7 @@ tableRef.current.scrollToRow(row); // 복원
|
|
|
1559
1561
|
- **태그의 색·이름을 밖에서 직접 주지 않는다** (`status`). `option.color`·`option.label` 은 없다 — 지금 상태가 가리키는 `options` 칸이 곧 태그다. 색이 상태의 뜻이라 둘이 어긋나면 안 되기 때문이다.
|
|
1560
1562
|
- **상태 메뉴의 색은 칸마다 준다** — 점과 글자가 그 상태의 색으로 함께 물든다. 상태는 색 자체가 뜻이라 고르는 자리에서도 색을 보고 고른다.
|
|
1561
1563
|
- `switch` 는 메뉴를 갖지 않는다 — 우측 문구가 "지금 값"이 아니라 보조 조작 문구라, 고를 목록이 있으면 그것은 `subSelect` 다.
|
|
1564
|
+
- **라벨 옆에 뱃지·카운트를 붙일 때는 `labelSlot` 을 쓴다** (`account` `select` `switch` `subSelect`). 라벨이 길면 라벨만 잘리고 슬롯은 밀리지 않는다. 행 전체가 버튼이라 **슬롯에 버튼·링크를 넣지 않는다**(button 중첩). `status` 는 태그가 라벨 자리를 차지해 받지 않는다. 텍스트를 넘기면 라벨과 같은 서체·색을 상속하고, 색을 바꿀 때는 토큰(`--sys-color-*`)으로 덮는다(고정 색은 어두운 면에서 묻힌다). 라벨 자체의 색은 바꾸지 못한다.
|
|
1562
1565
|
- 높이·라운드·아이콘 크기·좌우 여백은 전부 토큰이 넣는다. 직접 주지 않는다.
|
|
1563
1566
|
|
|
1564
1567
|
#### 3-5-8. `SAccountListBox` — 계정 행을 눌러 뜨는 계정 패널
|
|
@@ -2457,6 +2460,23 @@ import { SModalOutlet } from 'sellmate-design-system-react';
|
|
|
2457
2460
|
|
|
2458
2461
|
`SModal.confirm/loading/create` 로 띄운 모달이 그려지는 자리다. outlet 이 앱 트리 안에 있어야 모달이 앱의 Context(QueryClient·Router·Theme 등)를 상속한다 — outlet 이 없으면 모달은 뜨지만 별도 React 루트라 Provider 가 닿지 않는다(§3-3-4). 모달은 언제나 `body` 로 portal 되므로 outlet 을 어디에 두든 레이아웃에는 영향이 없고, **셸 안에 넣을 필요도 없다.** 토스트를 쓴다면 `SToastContainer` 도 같은 자리에 둔다.
|
|
2459
2462
|
|
|
2463
|
+
**컴포넌트가 내장한 문구(aria-label·placeholder·"전체" 등)의 언어는 `SLocaleProvider` 가 정한다 — 앱 루트에 한 번 두고, `SModalOutlet` 은 그 안쪽에 둔다.** 안쪽에 두어야 명령형 모달도 같은 로케일을 상속한다. Provider 가 없으면 한국어다.
|
|
2464
|
+
|
|
2465
|
+
```tsx
|
|
2466
|
+
import { SLocaleProvider, SModalOutlet } from 'sellmate-design-system-react';
|
|
2467
|
+
|
|
2468
|
+
<SLocaleProvider locale={userLocale}>
|
|
2469
|
+
<RouterProvider router={router} />
|
|
2470
|
+
<SModalOutlet />
|
|
2471
|
+
</SLocaleProvider>;
|
|
2472
|
+
```
|
|
2473
|
+
|
|
2474
|
+
- 지원 로케일은 `SLOCALES` 에 있다. `en-US` 처럼 지역이 붙어도 되고, **지원하지 않는 값은 예외 없이 한국어로 폴백한다.** `zh` 는 간체 문구라 `zh-TW` 도 간체로 나온다.
|
|
2475
|
+
- **`ja`·`zh` 문구는 원어민 검수 전 초안이다.** 사용자에게 노출하기 전에 검수한다.
|
|
2476
|
+
- 일부 문구만 바꾸려면 `messages` 로 덮어쓴다 — 나머지는 로케일 문구를 유지한다. `messages` 는 모듈 상수나 `useMemo` 로 안정시킨다(렌더마다 새 객체를 만들면 하위 컴포넌트가 매번 다시 그려진다).
|
|
2477
|
+
- 개별 prop(`placeholder` 등)을 직접 주면 로케일 문구보다 prop 이 우선한다. **내장 문구를 앱이 직접 번역해 prop 으로 넘기지 않는다** — Provider 가 이미 처리한다.
|
|
2478
|
+
- 아직 로케일을 따르는 컴포넌트는 `SPagination`·`SSelect` 뿐이고, 나머지는 순차로 옮기는 중이다. 로케일을 바꿔도 그 밖의 컴포넌트 문구는 한국어로 남는다.
|
|
2479
|
+
|
|
2460
2480
|
**최소 너비는 `SLayout` 이 보장한다 — 앱이 `min-w-*` 를 직접 주지 않는다.** 창이 최소 너비(`SLAYOUT_MIN_WIDTH`, GNB 포함한 전체 기준)보다 좁아지면 GNB·상단바는 제자리에 남고 **`SPage` 안에만 가로 스크롤이 생긴다.** 문서(브라우저 창)에는 가로 스크롤이 생기지 않는다. 그래서 셸을 감싸는 요소에 `min-width` 나 `overflow-x` 를 걸지 않는다 — 걸면 창 전체가 스크롤되어 GNB 가 화면 밖으로 밀린다.
|
|
2461
2481
|
|
|
2462
2482
|
**창이 최소 너비보다 넓을 때 본문을 어떻게 세울지는 `SPage` 의 `contentWidth` 가 정한다 — 폭을 직접 계산하지 않는다.** 넓은 모니터에서 본문이 끝까지 늘어나 성기어지는 화면이 있으므로 세 가지 중 하나를 고른다.
|
|
@@ -55,6 +55,7 @@ export declare const ICONS: {
|
|
|
55
55
|
readonly coupon: (p: IconRenderProps) => import("react").JSX.Element;
|
|
56
56
|
readonly dashboard: (p: IconRenderProps) => import("react").JSX.Element;
|
|
57
57
|
readonly date: (p: IconRenderProps) => import("react").JSX.Element;
|
|
58
|
+
readonly dollar: (p: IconRenderProps) => import("react").JSX.Element;
|
|
58
59
|
readonly dot: (p: IconRenderProps) => import("react").JSX.Element;
|
|
59
60
|
readonly download: (p: IconRenderProps) => import("react").JSX.Element;
|
|
60
61
|
readonly drag: (p: IconRenderProps) => import("react").JSX.Element;
|
|
@@ -62,6 +63,8 @@ export declare const ICONS: {
|
|
|
62
63
|
readonly etc: (p: IconRenderProps) => import("react").JSX.Element;
|
|
63
64
|
readonly event: (p: IconRenderProps) => import("react").JSX.Element;
|
|
64
65
|
readonly focus: (p: IconRenderProps) => import("react").JSX.Element;
|
|
66
|
+
readonly fullscreen: (p: IconRenderProps) => import("react").JSX.Element;
|
|
67
|
+
readonly fullscreenExit: (p: IconRenderProps) => import("react").JSX.Element;
|
|
65
68
|
readonly global: (p: IconRenderProps) => import("react").JSX.Element;
|
|
66
69
|
readonly helpFill: (p: IconRenderProps) => import("react").JSX.Element;
|
|
67
70
|
readonly helpOutline: (p: IconRenderProps) => import("react").JSX.Element;
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
| `valueDisplay?` | `SSelectValueDisplay` | `'text'` | 트리거에 선택값을 보여주는 방식. - `text`: 선택 라벨을 쉼표로 이어 한 줄로 보여준다. 넘치면 말줄임한다. - `chip`: 선택값마다 칩을 낸다. 칩의 × 를 누르면 그 값만 선택에서 빠지고, 드롭다운은 열리지 않는다. 칩이 한 줄을 넘으면 줄바꿈하고 트리거가 그만큼 높아진다. `chip` 은 `multi`·`multi_depth`·`multi_tree` 에서만 동작한다. 단일 선택 type 에서는 무시하고 `text` 로 보여준다. 전체 선택이면 칩 대신 `allSelectedLabel` 을 보여준다. `multi_depth`·`multi_tree` 에서 그룹의 하위 리프를 전부 고르면 리프 칩 대신 그룹명 칩 하나로 묶고, 그 칩의 × 는 그룹의 리프를 한꺼번에 뺀다. 비활성(select 자체나 해당 옵션)인 칩에는 × 를 내지 않는다. |
|
|
17
17
|
| `showSearch?` | `boolean` | `false` | 검색 입력 사용 |
|
|
18
18
|
| `showSelectAll?` | `boolean` | `false` | 전체선택 옵션 사용 (multi 전용) |
|
|
19
|
-
| `allSelectedLabel?` | `string` |
|
|
20
|
-
| `placeholder?` | `string` |
|
|
19
|
+
| `allSelectedLabel?` | `string` | — | 전체선택 레이블. 생략하면 `SLocaleProvider` 로케일의 기본 문구(ko: "전체")를 쓴다 |
|
|
20
|
+
| `placeholder?` | `string` | — | placeholder. 생략하면 `SLocaleProvider` 로케일의 기본 문구(ko: "선택")를 쓴다 |
|
|
21
21
|
| `disabled?` | `boolean` | `false` | 비활성 |
|
|
22
22
|
| `clearable?` | `boolean` | `false` | 선택값 지우기(×) 버튼 노출. 선택값이 있고 비활성이 아닐 때만 나타나며, 누르면 드롭다운을 열지 않고 값만 비운다. |
|
|
23
23
|
| `error?` | `boolean` | `false` | 에러 상태 |
|
|
@@ -75,9 +75,9 @@ export interface SSelectProps<TValue extends SSelectChangeValue = SSelectChangeV
|
|
|
75
75
|
showSearch?: boolean;
|
|
76
76
|
/** 전체선택 옵션 사용 (multi 전용) */
|
|
77
77
|
showSelectAll?: boolean;
|
|
78
|
-
/** 전체선택
|
|
78
|
+
/** 전체선택 레이블. 생략하면 `SLocaleProvider` 로케일의 기본 문구(ko: "전체")를 쓴다 */
|
|
79
79
|
allSelectedLabel?: string;
|
|
80
|
-
/** placeholder */
|
|
80
|
+
/** placeholder. 생략하면 `SLocaleProvider` 로케일의 기본 문구(ko: "선택")를 쓴다 */
|
|
81
81
|
placeholder?: string;
|
|
82
82
|
/** 비활성 */
|
|
83
83
|
disabled?: boolean;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|------|------|---------|-------------|
|
|
11
11
|
| `type` | `'account'` | — | 계정 행 |
|
|
12
12
|
| `label?` | `string` | — | 라벨 텍스트 |
|
|
13
|
+
| `labelSlot?` | `ReactNode` | — | 라벨 오른쪽에 붙는 표시용 요소(뱃지·카운트 등). 라벨이 길면 라벨만 잘리고 이 요소는 밀리지 않는다. 텍스트를 넘기면 라벨과 같은 서체·색을 상속한다 — 색을 바꾸려면 넘기는 쪽에서 토큰(`--sys-color-*`)으로 덮고, 고정 색은 `dark`·`darker` 면에서 묻히니 세 색 모두에서 확인한다. 라벨 자체의 색은 바꾸지 못한다. 행 전체가 버튼이라 **버튼·링크 같은 조작 요소는 넣지 않는다**(button 중첩). |
|
|
13
14
|
| `option` | `SSystemActionButtonAccountOption` | — | 누르면 뜨는 계정 리스트박스. **필수다** — 계정 행은 늘 이 패널의 트리거이고, 눌러도 아무것도 뜨지 않는 계정 행은 없다. 아이콘은 `user` 로 고정이라 여기서 받지 않는다. |
|
|
14
15
|
|
|
15
16
|
### SSystemActionButtonBase
|
|
@@ -29,6 +30,7 @@
|
|
|
29
30
|
|------|------|---------|-------------|
|
|
30
31
|
| `type` | `'account' \| 'select' \| 'switch' \| 'subSelect' \| 'status'` | — | 계정 행 |
|
|
31
32
|
| `label?` | `string` | — | 라벨 텍스트 |
|
|
33
|
+
| `labelSlot?` | `ReactNode` | — | 라벨 오른쪽에 붙는 표시용 요소(뱃지·카운트 등). 라벨이 길면 라벨만 잘리고 이 요소는 밀리지 않는다. 텍스트를 넘기면 라벨과 같은 서체·색을 상속한다 — 색을 바꾸려면 넘기는 쪽에서 토큰(`--sys-color-*`)으로 덮고, 고정 색은 `dark`·`darker` 면에서 묻히니 세 색 모두에서 확인한다. 라벨 자체의 색은 바꾸지 못한다. 행 전체가 버튼이라 **버튼·링크 같은 조작 요소는 넣지 않는다**(button 중첩). |
|
|
32
34
|
| `option?` | `<union 5종>` | — | 누르면 뜨는 계정 리스트박스. **필수다** — 계정 행은 늘 이 패널의 트리거이고, 눌러도 아무것도 뜨지 않는 계정 행은 없다. 아이콘은 `user` 로 고정이라 여기서 받지 않는다. |
|
|
33
35
|
|
|
34
36
|
### SSystemActionButtonSelect
|
|
@@ -39,6 +41,7 @@
|
|
|
39
41
|
|------|------|---------|-------------|
|
|
40
42
|
| `type` | `'select'` | — | 화살표만 붙는 행 |
|
|
41
43
|
| `label?` | `string` | — | 라벨 텍스트 |
|
|
44
|
+
| `labelSlot?` | `ReactNode` | — | 라벨 오른쪽에 붙는 표시용 요소(뱃지·카운트 등). 라벨이 길면 라벨만 잘리고 이 요소는 밀리지 않는다. 텍스트를 넘기면 라벨과 같은 서체·색을 상속한다 — 색을 바꾸려면 넘기는 쪽에서 토큰(`--sys-color-*`)으로 덮고, 고정 색은 `dark`·`darker` 면에서 묻히니 세 색 모두에서 확인한다. 라벨 자체의 색은 바꾸지 못한다. 행 전체가 버튼이라 **버튼·링크 같은 조작 요소는 넣지 않는다**(button 중첩). |
|
|
42
45
|
| `option?` | `SSystemActionButtonIconOption` | — | 선행 아이콘. 아이콘 없이 라벨만 두는 행이면 통째로 생략한다 |
|
|
43
46
|
|
|
44
47
|
### SSystemActionButtonStatus
|
|
@@ -49,6 +52,7 @@
|
|
|
49
52
|
|------|------|---------|-------------|
|
|
50
53
|
| `type` | `'status'` | — | 라벨 자리에 상태 태그가 들어가는 행 |
|
|
51
54
|
| `label?` | `never` | — | 태그가 라벨 자리를 차지하므로 받지 않는다 |
|
|
55
|
+
| `labelSlot?` | `never` | — | 태그가 라벨 자리를 차지하므로 받지 않는다 |
|
|
52
56
|
| `option` | `SSystemActionButtonStatusOption` | — | 상태 태그 + 고를 목록. **필수다** — 상태 행은 늘 그 상태를 바꾸는 메뉴의 트리거다. |
|
|
53
57
|
|
|
54
58
|
### SSystemActionButtonSubSelect
|
|
@@ -59,6 +63,7 @@
|
|
|
59
63
|
|------|------|---------|-------------|
|
|
60
64
|
| `type` | `'subSelect'` | — | 우측에 지금 선택된 값이 붙는 행 |
|
|
61
65
|
| `label?` | `string` | — | 라벨 텍스트 |
|
|
66
|
+
| `labelSlot?` | `ReactNode` | — | 라벨 오른쪽에 붙는 표시용 요소(뱃지·카운트 등). 라벨이 길면 라벨만 잘리고 이 요소는 밀리지 않는다. 텍스트를 넘기면 라벨과 같은 서체·색을 상속한다 — 색을 바꾸려면 넘기는 쪽에서 토큰(`--sys-color-*`)으로 덮고, 고정 색은 `dark`·`darker` 면에서 묻히니 세 색 모두에서 확인한다. 라벨 자체의 색은 바꾸지 못한다. 행 전체가 버튼이라 **버튼·링크 같은 조작 요소는 넣지 않는다**(button 중첩). |
|
|
62
67
|
| `option` | `SSystemActionButtonSubSelectOption` | — | 선행 아이콘 + 우측 값 + 고를 목록 |
|
|
63
68
|
|
|
64
69
|
### SSystemActionButtonSwitch
|
|
@@ -69,6 +74,7 @@
|
|
|
69
74
|
|------|------|---------|-------------|
|
|
70
75
|
| `type` | `'switch'` | — | 우측에 보조 조작 문구가 붙는 행 |
|
|
71
76
|
| `label?` | `string` | — | 라벨 텍스트 |
|
|
77
|
+
| `labelSlot?` | `ReactNode` | — | 라벨 오른쪽에 붙는 표시용 요소(뱃지·카운트 등). 라벨이 길면 라벨만 잘리고 이 요소는 밀리지 않는다. 텍스트를 넘기면 라벨과 같은 서체·색을 상속한다 — 색을 바꾸려면 넘기는 쪽에서 토큰(`--sys-color-*`)으로 덮고, 고정 색은 `dark`·`darker` 면에서 묻히니 세 색 모두에서 확인한다. 라벨 자체의 색은 바꾸지 못한다. 행 전체가 버튼이라 **버튼·링크 같은 조작 요소는 넣지 않는다**(button 중첩). |
|
|
72
78
|
| `option?` | `SSystemActionButtonTextOption` | — | 선행 아이콘 + 우측 액션 텍스트. 둘 다 두지 않으면 통째로 생략한다 |
|
|
73
79
|
|
|
74
80
|
### SSystemActionButtonText
|
|
@@ -79,6 +85,7 @@
|
|
|
79
85
|
|------|------|---------|-------------|
|
|
80
86
|
| `type` | `'switch' \| 'subSelect'` | — | 우측에 보조 조작 문구가 붙는 행 |
|
|
81
87
|
| `label?` | `string` | — | 라벨 텍스트 |
|
|
88
|
+
| `labelSlot?` | `ReactNode` | — | 라벨 오른쪽에 붙는 표시용 요소(뱃지·카운트 등). 라벨이 길면 라벨만 잘리고 이 요소는 밀리지 않는다. 텍스트를 넘기면 라벨과 같은 서체·색을 상속한다 — 색을 바꾸려면 넘기는 쪽에서 토큰(`--sys-color-*`)으로 덮고, 고정 색은 `dark`·`darker` 면에서 묻히니 세 색 모두에서 확인한다. 라벨 자체의 색은 바꾸지 못한다. 행 전체가 버튼이라 **버튼·링크 같은 조작 요소는 넣지 않는다**(button 중첩). |
|
|
82
89
|
| `option?` | `SSystemActionButtonTextOption \| SSystemActionButtonSubSelectOption` | — | 선행 아이콘 + 우측 액션 텍스트. 둘 다 두지 않으면 통째로 생략한다 |
|
|
83
90
|
|
|
84
91
|
## Types
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ButtonHTMLAttributes } from 'react';
|
|
1
|
+
import { type ButtonHTMLAttributes, type ReactNode } from 'react';
|
|
2
2
|
import { type SAccountListBoxContent } from '../SAccountListBox';
|
|
3
3
|
import { type SIconName } from '../SIcon';
|
|
4
4
|
import { type STagColor } from '../STag';
|
|
@@ -93,6 +93,13 @@ export interface SSystemActionButtonAccountProps extends SSystemActionButtonBase
|
|
|
93
93
|
type: 'account';
|
|
94
94
|
/** 라벨 텍스트 */
|
|
95
95
|
label?: string;
|
|
96
|
+
/**
|
|
97
|
+
* 라벨 오른쪽에 붙는 표시용 요소(뱃지·카운트 등). 라벨이 길면 라벨만 잘리고 이 요소는 밀리지 않는다.
|
|
98
|
+
* 텍스트를 넘기면 라벨과 같은 서체·색을 상속한다 — 색을 바꾸려면 넘기는 쪽에서 토큰(`--sys-color-*`)으로
|
|
99
|
+
* 덮고, 고정 색은 `dark`·`darker` 면에서 묻히니 세 색 모두에서 확인한다. 라벨 자체의 색은 바꾸지 못한다.
|
|
100
|
+
* 행 전체가 버튼이라 **버튼·링크 같은 조작 요소는 넣지 않는다**(button 중첩).
|
|
101
|
+
*/
|
|
102
|
+
labelSlot?: ReactNode;
|
|
96
103
|
/**
|
|
97
104
|
* 누르면 뜨는 계정 리스트박스. **필수다** — 계정 행은 늘 이 패널의 트리거이고, 눌러도 아무것도
|
|
98
105
|
* 뜨지 않는 계정 행은 없다. 아이콘은 `user` 로 고정이라 여기서 받지 않는다.
|
|
@@ -105,6 +112,13 @@ export interface SSystemActionButtonSelectProps extends SSystemActionButtonBaseP
|
|
|
105
112
|
type: 'select';
|
|
106
113
|
/** 라벨 텍스트 */
|
|
107
114
|
label?: string;
|
|
115
|
+
/**
|
|
116
|
+
* 라벨 오른쪽에 붙는 표시용 요소(뱃지·카운트 등). 라벨이 길면 라벨만 잘리고 이 요소는 밀리지 않는다.
|
|
117
|
+
* 텍스트를 넘기면 라벨과 같은 서체·색을 상속한다 — 색을 바꾸려면 넘기는 쪽에서 토큰(`--sys-color-*`)으로
|
|
118
|
+
* 덮고, 고정 색은 `dark`·`darker` 면에서 묻히니 세 색 모두에서 확인한다. 라벨 자체의 색은 바꾸지 못한다.
|
|
119
|
+
* 행 전체가 버튼이라 **버튼·링크 같은 조작 요소는 넣지 않는다**(button 중첩).
|
|
120
|
+
*/
|
|
121
|
+
labelSlot?: ReactNode;
|
|
108
122
|
/** 선행 아이콘. 아이콘 없이 라벨만 두는 행이면 통째로 생략한다 */
|
|
109
123
|
option?: SSystemActionButtonIconOption;
|
|
110
124
|
}
|
|
@@ -114,6 +128,13 @@ export interface SSystemActionButtonSwitchProps extends SSystemActionButtonBaseP
|
|
|
114
128
|
type: 'switch';
|
|
115
129
|
/** 라벨 텍스트 */
|
|
116
130
|
label?: string;
|
|
131
|
+
/**
|
|
132
|
+
* 라벨 오른쪽에 붙는 표시용 요소(뱃지·카운트 등). 라벨이 길면 라벨만 잘리고 이 요소는 밀리지 않는다.
|
|
133
|
+
* 텍스트를 넘기면 라벨과 같은 서체·색을 상속한다 — 색을 바꾸려면 넘기는 쪽에서 토큰(`--sys-color-*`)으로
|
|
134
|
+
* 덮고, 고정 색은 `dark`·`darker` 면에서 묻히니 세 색 모두에서 확인한다. 라벨 자체의 색은 바꾸지 못한다.
|
|
135
|
+
* 행 전체가 버튼이라 **버튼·링크 같은 조작 요소는 넣지 않는다**(button 중첩).
|
|
136
|
+
*/
|
|
137
|
+
labelSlot?: ReactNode;
|
|
117
138
|
/** 선행 아이콘 + 우측 액션 텍스트. 둘 다 두지 않으면 통째로 생략한다 */
|
|
118
139
|
option?: SSystemActionButtonTextOption;
|
|
119
140
|
}
|
|
@@ -123,6 +144,13 @@ export interface SSystemActionButtonSubSelectProps extends SSystemActionButtonBa
|
|
|
123
144
|
type: 'subSelect';
|
|
124
145
|
/** 라벨 텍스트 */
|
|
125
146
|
label?: string;
|
|
147
|
+
/**
|
|
148
|
+
* 라벨 오른쪽에 붙는 표시용 요소(뱃지·카운트 등). 라벨이 길면 라벨만 잘리고 이 요소는 밀리지 않는다.
|
|
149
|
+
* 텍스트를 넘기면 라벨과 같은 서체·색을 상속한다 — 색을 바꾸려면 넘기는 쪽에서 토큰(`--sys-color-*`)으로
|
|
150
|
+
* 덮고, 고정 색은 `dark`·`darker` 면에서 묻히니 세 색 모두에서 확인한다. 라벨 자체의 색은 바꾸지 못한다.
|
|
151
|
+
* 행 전체가 버튼이라 **버튼·링크 같은 조작 요소는 넣지 않는다**(button 중첩).
|
|
152
|
+
*/
|
|
153
|
+
labelSlot?: ReactNode;
|
|
126
154
|
/** 선행 아이콘 + 우측 값 + 고를 목록 */
|
|
127
155
|
option: SSystemActionButtonSubSelectOption;
|
|
128
156
|
}
|
|
@@ -134,6 +162,8 @@ export interface SSystemActionButtonStatusProps extends SSystemActionButtonBaseP
|
|
|
134
162
|
type: 'status';
|
|
135
163
|
/** 태그가 라벨 자리를 차지하므로 받지 않는다 */
|
|
136
164
|
label?: never;
|
|
165
|
+
/** 태그가 라벨 자리를 차지하므로 받지 않는다 */
|
|
166
|
+
labelSlot?: never;
|
|
137
167
|
/**
|
|
138
168
|
* 상태 태그 + 고를 목록. **필수다** — 상태 행은 늘 그 상태를 바꾸는 메뉴의 트리거다.
|
|
139
169
|
*/
|
package/dist/index.cjs
CHANGED
|
@@ -272,6 +272,126 @@ var fieldWidthValue = (v) => {
|
|
|
272
272
|
if (isFieldWidthGrade(v)) return `var(--cmp-field-width-${v})`;
|
|
273
273
|
return typeof v === "number" ? `${v}px` : v;
|
|
274
274
|
};
|
|
275
|
+
|
|
276
|
+
// src/lib/locale.ts
|
|
277
|
+
var SLOCALES = ["ko", "en", "ja", "zh"];
|
|
278
|
+
var DEFAULT_LOCALE = "ko";
|
|
279
|
+
var BUNDLES = {
|
|
280
|
+
ko: {
|
|
281
|
+
pagination: {
|
|
282
|
+
firstPage: "\uCCAB \uD398\uC774\uC9C0",
|
|
283
|
+
prevPage: "\uC774\uC804 \uD398\uC774\uC9C0",
|
|
284
|
+
nextPage: "\uB2E4\uC74C \uD398\uC774\uC9C0",
|
|
285
|
+
lastPage: "\uB9C8\uC9C0\uB9C9 \uD398\uC774\uC9C0",
|
|
286
|
+
prevGroup: "\uC774\uC804 \uADF8\uB8F9",
|
|
287
|
+
nextGroup: "\uB2E4\uC74C \uADF8\uB8F9"
|
|
288
|
+
},
|
|
289
|
+
select: {
|
|
290
|
+
placeholder: "\uC120\uD0DD",
|
|
291
|
+
allSelected: "\uC804\uCCB4",
|
|
292
|
+
clear: "\uC120\uD0DD \uC9C0\uC6B0\uAE30",
|
|
293
|
+
deselect: (label) => `${label} \uC120\uD0DD \uD574\uC81C`,
|
|
294
|
+
searchPlaceholder: "\uAC80\uC0C9",
|
|
295
|
+
empty: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
296
|
+
loading: "\uBD88\uB7EC\uC624\uB294 \uC911..."
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
en: {
|
|
300
|
+
pagination: {
|
|
301
|
+
firstPage: "First page",
|
|
302
|
+
prevPage: "Previous page",
|
|
303
|
+
nextPage: "Next page",
|
|
304
|
+
lastPage: "Last page",
|
|
305
|
+
prevGroup: "Previous pages",
|
|
306
|
+
nextGroup: "Next pages"
|
|
307
|
+
},
|
|
308
|
+
select: {
|
|
309
|
+
placeholder: "Select",
|
|
310
|
+
allSelected: "All",
|
|
311
|
+
clear: "Clear selection",
|
|
312
|
+
deselect: (label) => `Deselect ${label}`,
|
|
313
|
+
searchPlaceholder: "Search",
|
|
314
|
+
empty: "No items to display.",
|
|
315
|
+
loading: "Loading..."
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
ja: {
|
|
319
|
+
pagination: {
|
|
320
|
+
firstPage: "\u6700\u521D\u306E\u30DA\u30FC\u30B8",
|
|
321
|
+
prevPage: "\u524D\u306E\u30DA\u30FC\u30B8",
|
|
322
|
+
nextPage: "\u6B21\u306E\u30DA\u30FC\u30B8",
|
|
323
|
+
lastPage: "\u6700\u5F8C\u306E\u30DA\u30FC\u30B8",
|
|
324
|
+
prevGroup: "\u524D\u306E\u30B0\u30EB\u30FC\u30D7",
|
|
325
|
+
nextGroup: "\u6B21\u306E\u30B0\u30EB\u30FC\u30D7"
|
|
326
|
+
},
|
|
327
|
+
select: {
|
|
328
|
+
placeholder: "\u9078\u629E",
|
|
329
|
+
allSelected: "\u3059\u3079\u3066",
|
|
330
|
+
clear: "\u9078\u629E\u3092\u30AF\u30EA\u30A2",
|
|
331
|
+
deselect: (label) => `${label} \u306E\u9078\u629E\u3092\u89E3\u9664`,
|
|
332
|
+
searchPlaceholder: "\u691C\u7D22",
|
|
333
|
+
empty: "\u8868\u793A\u3059\u308B\u9805\u76EE\u304C\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
334
|
+
loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D..."
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
zh: {
|
|
338
|
+
pagination: {
|
|
339
|
+
firstPage: "\u7B2C\u4E00\u9875",
|
|
340
|
+
prevPage: "\u4E0A\u4E00\u9875",
|
|
341
|
+
nextPage: "\u4E0B\u4E00\u9875",
|
|
342
|
+
lastPage: "\u6700\u540E\u4E00\u9875",
|
|
343
|
+
prevGroup: "\u4E0A\u4E00\u7EC4",
|
|
344
|
+
nextGroup: "\u4E0B\u4E00\u7EC4"
|
|
345
|
+
},
|
|
346
|
+
select: {
|
|
347
|
+
placeholder: "\u8BF7\u9009\u62E9",
|
|
348
|
+
allSelected: "\u5168\u90E8",
|
|
349
|
+
clear: "\u6E05\u9664\u9009\u62E9",
|
|
350
|
+
deselect: (label) => `\u53D6\u6D88\u9009\u62E9 ${label}`,
|
|
351
|
+
searchPlaceholder: "\u641C\u7D22",
|
|
352
|
+
empty: "\u6CA1\u6709\u53EF\u663E\u793A\u7684\u9879\u76EE\u3002",
|
|
353
|
+
loading: "\u52A0\u8F7D\u4E2D..."
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
function normalizeLocale(locale) {
|
|
358
|
+
if (!locale) return DEFAULT_LOCALE;
|
|
359
|
+
const lang = locale.toLowerCase().split(/[-_]/)[0];
|
|
360
|
+
return SLOCALES.includes(lang) ? lang : DEFAULT_LOCALE;
|
|
361
|
+
}
|
|
362
|
+
function mergeDefined(base, override) {
|
|
363
|
+
const next = { ...base };
|
|
364
|
+
if (!override) return next;
|
|
365
|
+
for (const key of Object.keys(override)) {
|
|
366
|
+
if (override[key] !== void 0) next[key] = override[key];
|
|
367
|
+
}
|
|
368
|
+
return next;
|
|
369
|
+
}
|
|
370
|
+
function resolveMessages(locale, override) {
|
|
371
|
+
const base = BUNDLES[normalizeLocale(locale)];
|
|
372
|
+
return {
|
|
373
|
+
pagination: mergeDefined(base.pagination, override?.pagination),
|
|
374
|
+
select: mergeDefined(base.select, override?.select)
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function createValue(locale, override) {
|
|
378
|
+
const normalized = normalizeLocale(locale);
|
|
379
|
+
const numberFormat = new Intl.NumberFormat(normalized);
|
|
380
|
+
return {
|
|
381
|
+
locale: normalized,
|
|
382
|
+
messages: resolveMessages(normalized, override),
|
|
383
|
+
formatNumber: (value) => numberFormat.format(value)
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
var DEFAULT_VALUE = createValue(void 0);
|
|
387
|
+
var LocaleContext = /* @__PURE__ */ react.createContext(DEFAULT_VALUE);
|
|
388
|
+
function SLocaleProvider({ locale, messages, children }) {
|
|
389
|
+
const value = react.useMemo(() => createValue(locale, messages), [locale, messages]);
|
|
390
|
+
return /* @__PURE__ */ jsxRuntime.jsx(LocaleContext.Provider, { value, children });
|
|
391
|
+
}
|
|
392
|
+
function useLocale() {
|
|
393
|
+
return react.useContext(LocaleContext);
|
|
394
|
+
}
|
|
275
395
|
var Icon_account = (p) => {
|
|
276
396
|
const { size = 24, ...rest } = p;
|
|
277
397
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -1739,6 +1859,41 @@ var Icon_date = (p) => {
|
|
|
1739
1859
|
}
|
|
1740
1860
|
);
|
|
1741
1861
|
};
|
|
1862
|
+
var Icon_dollar = (p) => {
|
|
1863
|
+
const { size = 24, ...rest } = p;
|
|
1864
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1865
|
+
"svg",
|
|
1866
|
+
{
|
|
1867
|
+
width: size,
|
|
1868
|
+
height: size,
|
|
1869
|
+
viewBox: "0 0 24 24",
|
|
1870
|
+
fill: "none",
|
|
1871
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1872
|
+
...rest,
|
|
1873
|
+
children: [
|
|
1874
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1875
|
+
"path",
|
|
1876
|
+
{
|
|
1877
|
+
d: "M12 5V7.1M12 7.1V12M12 7.1H15.3333M12 7.1H10.3333C9.04467 7.1 8 8.1969 8 9.55C8 10.9031 9.04467 12 10.3333 12H12M12 12V16.9M12 12H13.6667C14.9553 12 16 13.0969 16 14.45C16 15.8031 14.9553 16.9 13.6667 16.9H12M12 16.9V19M12 16.9H8.66667",
|
|
1878
|
+
stroke: "currentColor",
|
|
1879
|
+
strokeWidth: "1.5",
|
|
1880
|
+
strokeLinecap: "round",
|
|
1881
|
+
strokeLinejoin: "round"
|
|
1882
|
+
}
|
|
1883
|
+
),
|
|
1884
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1885
|
+
"path",
|
|
1886
|
+
{
|
|
1887
|
+
d: "M22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12Z",
|
|
1888
|
+
stroke: "currentColor",
|
|
1889
|
+
strokeWidth: "1.5",
|
|
1890
|
+
strokeLinecap: "round"
|
|
1891
|
+
}
|
|
1892
|
+
)
|
|
1893
|
+
]
|
|
1894
|
+
}
|
|
1895
|
+
);
|
|
1896
|
+
};
|
|
1742
1897
|
var Icon_dot = (p) => {
|
|
1743
1898
|
const { size = 24, ...rest } = p;
|
|
1744
1899
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1955,6 +2110,54 @@ var Icon_focus = (p) => {
|
|
|
1955
2110
|
}
|
|
1956
2111
|
);
|
|
1957
2112
|
};
|
|
2113
|
+
var Icon_fullscreen = (p) => {
|
|
2114
|
+
const { size = 24, ...rest } = p;
|
|
2115
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2116
|
+
"svg",
|
|
2117
|
+
{
|
|
2118
|
+
width: size,
|
|
2119
|
+
height: size,
|
|
2120
|
+
viewBox: "0 0 24 24",
|
|
2121
|
+
fill: "none",
|
|
2122
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2123
|
+
...rest,
|
|
2124
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2125
|
+
"path",
|
|
2126
|
+
{
|
|
2127
|
+
d: "M9 3H4C3.44772 3 3 3.44772 3 4V9M15 3H20C20.5523 3 21 3.44772 21 4V9M21 15V20C21 20.5523 20.5523 21 20 21H15M9 21H4C3.44772 21 3 20.5523 3 20V15",
|
|
2128
|
+
stroke: "currentColor",
|
|
2129
|
+
strokeWidth: "1.5",
|
|
2130
|
+
strokeLinecap: "round",
|
|
2131
|
+
strokeLinejoin: "round"
|
|
2132
|
+
}
|
|
2133
|
+
)
|
|
2134
|
+
}
|
|
2135
|
+
);
|
|
2136
|
+
};
|
|
2137
|
+
var Icon_fullscreenExit = (p) => {
|
|
2138
|
+
const { size = 24, ...rest } = p;
|
|
2139
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2140
|
+
"svg",
|
|
2141
|
+
{
|
|
2142
|
+
width: size,
|
|
2143
|
+
height: size,
|
|
2144
|
+
viewBox: "0 0 24 24",
|
|
2145
|
+
fill: "none",
|
|
2146
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2147
|
+
...rest,
|
|
2148
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2149
|
+
"path",
|
|
2150
|
+
{
|
|
2151
|
+
d: "M3 9H8C8.55228 9 9 8.55228 9 8V3M15 3V8C15 8.55228 15.4477 9 16 9H21M21 15H16C15.4477 15 15 15.4477 15 16V21M9 21V16C9 15.4477 8.55228 15 8 15H3",
|
|
2152
|
+
stroke: "currentColor",
|
|
2153
|
+
strokeWidth: "1.5",
|
|
2154
|
+
strokeLinecap: "round",
|
|
2155
|
+
strokeLinejoin: "round"
|
|
2156
|
+
}
|
|
2157
|
+
)
|
|
2158
|
+
}
|
|
2159
|
+
);
|
|
2160
|
+
};
|
|
1958
2161
|
var Icon_global = (p) => {
|
|
1959
2162
|
const { size = 24, ...rest } = p;
|
|
1960
2163
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3657,6 +3860,7 @@ var ICONS = {
|
|
|
3657
3860
|
coupon: Icon_coupon,
|
|
3658
3861
|
dashboard: Icon_dashboard,
|
|
3659
3862
|
date: Icon_date,
|
|
3863
|
+
dollar: Icon_dollar,
|
|
3660
3864
|
dot: Icon_dot,
|
|
3661
3865
|
download: Icon_download,
|
|
3662
3866
|
drag: Icon_drag,
|
|
@@ -3664,6 +3868,8 @@ var ICONS = {
|
|
|
3664
3868
|
etc: Icon_etc,
|
|
3665
3869
|
event: Icon_event,
|
|
3666
3870
|
focus: Icon_focus,
|
|
3871
|
+
fullscreen: Icon_fullscreen,
|
|
3872
|
+
fullscreenExit: Icon_fullscreenExit,
|
|
3667
3873
|
global: Icon_global,
|
|
3668
3874
|
helpFill: Icon_helpFill,
|
|
3669
3875
|
helpOutline: Icon_helpOutline,
|
|
@@ -10449,7 +10655,17 @@ function TokenIcon2({ name, size }) {
|
|
|
10449
10655
|
return /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name, size: "100%", style: { width: size, height: size } });
|
|
10450
10656
|
}
|
|
10451
10657
|
var SSystemActionButton = /* @__PURE__ */ react.forwardRef(
|
|
10452
|
-
function SSystemActionButton2({
|
|
10658
|
+
function SSystemActionButton2({
|
|
10659
|
+
color = "light",
|
|
10660
|
+
type,
|
|
10661
|
+
label,
|
|
10662
|
+
labelSlot,
|
|
10663
|
+
option,
|
|
10664
|
+
disabled = false,
|
|
10665
|
+
className,
|
|
10666
|
+
style,
|
|
10667
|
+
...rest
|
|
10668
|
+
}, ref) {
|
|
10453
10669
|
const c = SYSTEM_ACTION_BUTTON_COLOR_CONFIG[color];
|
|
10454
10670
|
const spec = SYSTEM_ACTION_BUTTON_TYPE_CONFIG[type];
|
|
10455
10671
|
const listBox = type === "account" ? option ?? {} : void 0;
|
|
@@ -10537,7 +10753,19 @@ var SSystemActionButton = /* @__PURE__ */ react.forwardRef(
|
|
|
10537
10753
|
icon: "dot",
|
|
10538
10754
|
label: selected?.label ?? status.value
|
|
10539
10755
|
}
|
|
10540
|
-
) : /* @__PURE__ */ jsxRuntime.
|
|
10756
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10757
|
+
label != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label }),
|
|
10758
|
+
labelSlot != null && // 라벨↔슬롯 간격에 대응 토큰이 없어 아이콘↔라벨 간격을 같은 호흡으로 쓴다.
|
|
10759
|
+
// 라벨이 없으면 슬롯이 아이콘 바로 옆에서 시작하도록 간격은 라벨이 있을 때만 준다.
|
|
10760
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10761
|
+
"span",
|
|
10762
|
+
{
|
|
10763
|
+
className: "inline-flex shrink-0 items-center",
|
|
10764
|
+
style: label != null ? { marginLeft: SYSTEM_ACTION_BUTTON_LAYOUT.iconLabelGap } : void 0,
|
|
10765
|
+
children: labelSlot
|
|
10766
|
+
}
|
|
10767
|
+
)
|
|
10768
|
+
] }) }),
|
|
10541
10769
|
(actionText != null || spec.actionIcon) && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex shrink-0 items-center", style: { gap: SYSTEM_ACTION_BUTTON_LAYOUT.actionGap }, children: [
|
|
10542
10770
|
actionText != null && spec.actionText && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10543
10771
|
"span",
|
|
@@ -14315,6 +14543,7 @@ function SPagination({
|
|
|
14315
14543
|
className,
|
|
14316
14544
|
style
|
|
14317
14545
|
}) {
|
|
14546
|
+
const t = useLocale().messages.pagination;
|
|
14318
14547
|
const start = Math.floor((currentPage - 1) / PER_PAGE) * PER_PAGE + 1;
|
|
14319
14548
|
const end = Math.min(start + PER_PAGE - 1, lastPage);
|
|
14320
14549
|
const pageNumbers = Array.from({ length: Math.max(end - start + 1, 0) }, (_, i) => start + i);
|
|
@@ -14341,18 +14570,18 @@ function SPagination({
|
|
|
14341
14570
|
}
|
|
14342
14571
|
);
|
|
14343
14572
|
const prevButtons = simple ? currentPage > 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14344
|
-
navBtn("chevronLeftEnd",
|
|
14345
|
-
navBtn("chevronLeft",
|
|
14573
|
+
navBtn("chevronLeftEnd", t.firstPage, () => go(1)),
|
|
14574
|
+
navBtn("chevronLeft", t.prevPage, () => go(currentPage - 1))
|
|
14346
14575
|
] }) : !isFirstGroup && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14347
|
-
navBtn("chevronLeftEnd",
|
|
14348
|
-
navBtn("chevronLeft",
|
|
14576
|
+
navBtn("chevronLeftEnd", t.firstPage, () => go(1)),
|
|
14577
|
+
navBtn("chevronLeft", t.prevGroup, () => groupMove("backward"))
|
|
14349
14578
|
] });
|
|
14350
14579
|
const nextButtons = simple ? currentPage < lastPage && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14351
|
-
navBtn("chevronRight",
|
|
14352
|
-
navBtn("chevronRightEnd",
|
|
14580
|
+
navBtn("chevronRight", t.nextPage, () => go(currentPage + 1)),
|
|
14581
|
+
navBtn("chevronRightEnd", t.lastPage, () => go(lastPage))
|
|
14353
14582
|
] }) : !isLastGroup && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14354
|
-
navBtn("chevronRight",
|
|
14355
|
-
navBtn("chevronRightEnd",
|
|
14583
|
+
navBtn("chevronRight", t.nextGroup, () => groupMove("forward")),
|
|
14584
|
+
navBtn("chevronRightEnd", t.lastPage, () => go(lastPage))
|
|
14356
14585
|
] });
|
|
14357
14586
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14358
14587
|
"div",
|
|
@@ -16444,8 +16673,8 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
16444
16673
|
valueDisplay = "text",
|
|
16445
16674
|
showSearch = false,
|
|
16446
16675
|
showSelectAll = false,
|
|
16447
|
-
allSelectedLabel
|
|
16448
|
-
placeholder
|
|
16676
|
+
allSelectedLabel: allSelectedLabelProp,
|
|
16677
|
+
placeholder: placeholderProp,
|
|
16449
16678
|
disabled = false,
|
|
16450
16679
|
clearable = false,
|
|
16451
16680
|
error = false,
|
|
@@ -16486,6 +16715,9 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
16486
16715
|
const partialOptions = pagingEnabled || serverSearch;
|
|
16487
16716
|
const portalContainer = usePortalContainer();
|
|
16488
16717
|
const insideModal = useInsideModal();
|
|
16718
|
+
const t = useLocale().messages.select;
|
|
16719
|
+
const allSelectedLabel = allSelectedLabelProp ?? t.allSelected;
|
|
16720
|
+
const placeholder = placeholderProp ?? t.placeholder;
|
|
16489
16721
|
const [search, setSearch] = react.useState("");
|
|
16490
16722
|
const [ruleError, setRuleError] = react.useState("");
|
|
16491
16723
|
const [open, setOpen] = react.useState(false);
|
|
@@ -17227,7 +17459,9 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
17227
17459
|
chip.removable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17228
17460
|
TriggerRemoveButton,
|
|
17229
17461
|
{
|
|
17230
|
-
ariaLabel:
|
|
17462
|
+
ariaLabel: t.deselect(
|
|
17463
|
+
isHtmlLabel(chip.label) ? extractText(chip.label) : chip.label
|
|
17464
|
+
),
|
|
17231
17465
|
onRemove: () => handleRemoveChip(chip.values)
|
|
17232
17466
|
}
|
|
17233
17467
|
)
|
|
@@ -17239,7 +17473,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
17239
17473
|
)
|
|
17240
17474
|
) : /* @__PURE__ */ jsxRuntime.jsx(TriggerLabel, { label: triggerText }),
|
|
17241
17475
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-[8px]", children: [
|
|
17242
|
-
showClear && /* @__PURE__ */ jsxRuntime.jsx(TriggerRemoveButton, { ariaLabel:
|
|
17476
|
+
showClear && /* @__PURE__ */ jsxRuntime.jsx(TriggerRemoveButton, { ariaLabel: t.clear, onRemove: handleClear }),
|
|
17243
17477
|
showTriggerSpinner ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "inline-flex shrink-0", "data-select-trigger-spinner": true, children: /* @__PURE__ */ jsxRuntime.jsx(SCircleProgress, { indeterminate: true, type: "neutral", size: 12 }) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
17244
17478
|
SIcon,
|
|
17245
17479
|
{
|
|
@@ -17319,7 +17553,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
17319
17553
|
value: search,
|
|
17320
17554
|
onValueChange: handleSearchChange,
|
|
17321
17555
|
onKeyDown: handleKeyDown,
|
|
17322
|
-
placeholder:
|
|
17556
|
+
placeholder: t.searchPlaceholder,
|
|
17323
17557
|
clearable: true,
|
|
17324
17558
|
"aria-controls": listboxId,
|
|
17325
17559
|
"aria-activedescendant": focusedIndex >= 0 ? activeOptionId : void 0
|
|
@@ -17363,7 +17597,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
17363
17597
|
}
|
|
17364
17598
|
) : loading2 ? null : (
|
|
17365
17599
|
// 첫 페이지를 받는 중에는 "없다"고 단정하지 않는다 — 아래 로딩 표시가 대신 나온다.
|
|
17366
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-[12px] py-[12px] text-left text-[12px] leading-[20px] text-[color:var(--cmp-listBoxItem-content-disabled)]", children:
|
|
17600
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-[12px] py-[12px] text-left text-[12px] leading-[20px] text-[color:var(--cmp-listBoxItem-content-disabled)]", children: t.empty })
|
|
17367
17601
|
),
|
|
17368
17602
|
loading2 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17369
17603
|
"div",
|
|
@@ -17372,7 +17606,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
17372
17606
|
className: "flex items-center justify-center gap-[8px] px-[12px] py-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listBoxItem-content-disabled)]",
|
|
17373
17607
|
children: [
|
|
17374
17608
|
/* @__PURE__ */ jsxRuntime.jsx(SCircleProgress, { indeterminate: true, type: "neutral", size: 16 }),
|
|
17375
|
-
|
|
17609
|
+
t.loading
|
|
17376
17610
|
]
|
|
17377
17611
|
}
|
|
17378
17612
|
)
|
|
@@ -30606,6 +30840,7 @@ exports.SKELETON_TYPES = SKELETON_TYPES;
|
|
|
30606
30840
|
exports.SKELETON_TYPE_CONFIG = SKELETON_TYPE_CONFIG;
|
|
30607
30841
|
exports.SKeyValueTable = SKeyValueTable;
|
|
30608
30842
|
exports.SLAYOUT_MIN_WIDTH = SLAYOUT_MIN_WIDTH;
|
|
30843
|
+
exports.SLOCALES = SLOCALES;
|
|
30609
30844
|
exports.SLauncherListBox = SLauncherListBox;
|
|
30610
30845
|
exports.SLayout = SLayout;
|
|
30611
30846
|
exports.SLayoutContext = SLayoutContext;
|
|
@@ -30615,6 +30850,7 @@ exports.SList = SList2;
|
|
|
30615
30850
|
exports.SListItem = SListItem2;
|
|
30616
30851
|
exports.SLoadingContainer = SLoadingContainer;
|
|
30617
30852
|
exports.SLoadingModal = SLoadingModal;
|
|
30853
|
+
exports.SLocaleProvider = SLocaleProvider;
|
|
30618
30854
|
exports.SLoginCard = SLoginCard2;
|
|
30619
30855
|
exports.SLogo = SLogo;
|
|
30620
30856
|
exports.SMeatballButton = SMeatballButton2;
|
|
@@ -30684,7 +30920,9 @@ exports.isColorKey = isColorKey;
|
|
|
30684
30920
|
exports.isFieldWidthGrade = isFieldWidthGrade;
|
|
30685
30921
|
exports.loading = loading;
|
|
30686
30922
|
exports.normalizeExtension = normalizeExtension;
|
|
30923
|
+
exports.normalizeLocale = normalizeLocale;
|
|
30687
30924
|
exports.resolveColor = resolveColor;
|
|
30925
|
+
exports.useLocale = useLocale;
|
|
30688
30926
|
exports.useSLayout = useSLayout;
|
|
30689
30927
|
//# sourceMappingURL=index.cjs.map
|
|
30690
30928
|
//# sourceMappingURL=index.cjs.map
|