sellmate-design-system-react 9.0.0-beta.90 → 9.0.0-beta.91
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 +33 -13
- package/dist/components/SChatInput/README.md +8 -2
- package/dist/components/SChatInput/SChatInput.d.ts +54 -4
- package/dist/components/SDatePicker/README.md +1 -0
- package/dist/components/SDatePicker/SDatePicker.d.ts +9 -1
- package/dist/components/SDateRangePicker/README.md +1 -0
- package/dist/components/SDateRangePicker/SDateRangePicker.d.ts +9 -1
- package/dist/components/SExpansionItem/README.md +1 -0
- package/dist/components/SExpansionItem/SExpansionItem.d.ts +10 -0
- package/dist/components/SGhostButton/README.md +3 -1
- package/dist/components/SGhostButton/SGhostButton.d.ts +18 -3
- package/dist/index.cjs +429 -167
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +429 -167
- package/dist/index.js.map +1 -1
- package/dist/lib/date.d.ts +9 -0
- package/dist/llms-full.txt +47 -16
- package/dist/llms.txt +33 -13
- package/dist/styles.css +3 -6
- package/dist/theme.css +0 -6
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -1435,6 +1435,7 @@ tableRef.current.scrollToRow(row); // 복원
|
|
|
1435
1435
|
- **`ariaLabel` 은 필수다.** 라벨이 없어 스크린리더가 읽을 것이 아이콘밖에 없다. 뜻이 덜 명확한 아이콘은 **`tooltipText`** 로 이름을 띄운다.
|
|
1436
1436
|
- 여러 개를 나란히 둘 때 간격은 **`gap-sd-4` 고정** — 가로·세로가 같다 (§2-2).
|
|
1437
1437
|
- **라벨이 필요하거나 화면의 주 액션이면 `SGhostButton` 이 아니라 `SButton` 이다.** 위계가 낮다는 이유만으로 `SGhostButton` 을 고르지 않는다 — 라벨이 붙는 저강조 액션은 `SButton` 의 `outline` 조합(§3-5-1)이다.
|
|
1438
|
+
- **다른 화면·문서로 가는 아이콘 버튼은 `href` 를 준다.** 링크(`<a>`)로 그려져 가운데 클릭·⌘클릭·주소 복사가 듣는다. `onClick` 에서 `location`·`window.open` 으로 옮기거나 `<a>` 로 감싸지 않는다. 새 탭이면 `target="_blank"` 만 준다 — `rel` 은 컴포넌트가 붙인다.
|
|
1438
1439
|
|
|
1439
1440
|
```tsx
|
|
1440
1441
|
// 테이블 행 끝 인라인 액션 — 수정은 action, 행 삭제는 default, 간격은 gap-sd-4
|
|
@@ -1452,6 +1453,8 @@ tableRef.current.scrollToRow(row); // 복원
|
|
|
1452
1453
|
✅ <SGhostButton icon="close" ariaLabel="닫기" onClick={onClose} /> // 모달 닫기 = default
|
|
1453
1454
|
✅ <SGhostButton icon="copy" ariaLabel="상품코드 복사" tooltipText="복사" /> // 뜻이 덜 명확 → 툴팁
|
|
1454
1455
|
❌ <SGhostButton icon="download" ariaLabel="엑셀 다운로드" /> // 목록의 주 액션 → SButton
|
|
1456
|
+
✅ <SGhostButton icon="helpOutline" ariaLabel="도움말" href={HELP_URL} target="_blank" />
|
|
1457
|
+
❌ <SGhostButton icon="helpOutline" ariaLabel="도움말" onClick={() => window.open(HELP_URL)} /> // 가는 버튼 → href
|
|
1455
1458
|
```
|
|
1456
1459
|
|
|
1457
1460
|
##### `SMeatballButton` — ⋯ 뒤에 메뉴를 접어 둘 때
|
|
@@ -1877,6 +1880,8 @@ useEffect(() => {
|
|
|
1877
1880
|
| `STimePicker` | md | lg |
|
|
1878
1881
|
| `STimeRangePicker` | md | lg (오전/오후 표시는 두 사이즈 모두 lg) |
|
|
1879
1882
|
|
|
1883
|
+
`SDatePicker`·`SDateRangePicker` 에 `showWeekday` 를 켜면 날짜 뒤에 요일이 붙어(`2026-10-19 월요일`) 붙는 글자(띄어쓰기 + 요일 3자) 폭만큼 위 표의 하한·상한이 넓어진다 — 등급이 바뀌는 것이 아니다. 늘어난 폭은 컴포넌트가 스스로 잡으므로 요일 때문에 `width` 를 따로 주지 않는다. 표시만 바뀌고 값 형식은 그대로라, **요일을 붙이려고 값을 가공하거나 `hint` 에 요일을 따로 적지 않는다.**
|
|
1884
|
+
|
|
1880
1885
|
`SDateRangePicker` 가 한 등급씩 위인 것은 값이 `YYYY-MM-DD ~ YYYY-MM-DD` 로 두 배가 넘기 때문이다. 같은 이유로 `STimeRangePicker` 의 오전/오후 모드도 sm 에서 한 등급 위를 쓴다 — 그 모드의 최소 폭이 md 등급을 이미 넘어, 그대로 두면 하한이 상한을 넘어 상한이 무력해진다.
|
|
1881
1886
|
|
|
1882
1887
|
네 컴포넌트 모두 이 상한을 `maxWidth` 로 덮을 수 있다 — 등급을 주면 그 등급이 상한이 되고, `width="100%" maxWidth="100%"` 면 부모 폭을 그대로 채운다. **폭이 이미 좁게 정해진 자리(팝오버·좁은 카드)에서 쓴다.**
|
|
@@ -1975,7 +1980,7 @@ const [from, setFrom] = useState<string | null>(null);
|
|
|
1975
1980
|
- **펼침 버튼·들여쓰기는 컴포넌트가 그린다.** 기본은 보이는 첫 컬럼이고 `treeColumn` 으로 옮긴다. 그 컬럼은 왼쪽 정렬로 두고, 셀 내용은 `render`·`format` 으로 바꾼다 — `renderCell` 은 펼침 버튼을 넣을 자리가 없어 에러가 난다.
|
|
1976
1981
|
- **셀 병합은 가로(`colSpan`)만 한다.** 트리 컬럼이 아닌 컬럼은 `renderCell` 로 `<td>` 를 바꿀 수 있고, 한 행 안에서 끝나는 `colSpan` 은 접고 펴도 그대로다. **`rowSpan` 으로 세로 병합하지 않는다** — 행이 접히면 사라진 행 몫까지 병합이 남아 아래 행의 칸을 덮고, 덮인 행의 칸은 옆 컬럼으로 밀려난다. 부모와 하위 행에 같은 값이 반복되면 부모 행에만 쓰고 하위 행은 비워 둔다.
|
|
1977
1982
|
- **펼침 영역은 트리 컬럼 셀 전체다.** 하위 행이 있는 행은 펼침 버튼뿐 아니라 그 셀 어디를 눌러도 접고 편다. 다른 셀을 누르면 행 클릭(`onRowClick`)이다 — 트리 컬럼 셀을 누른 것은 행 클릭으로 가지 않는다.
|
|
1978
|
-
-
|
|
1983
|
+
- **펼침·접힘 모션은 컴포넌트가 넣는다.** 하위 행이 부모 아래에서 서랍처럼 펼쳐지고 접히며, 아래 행들도 함께 내려가고 올라온다. 모션을 줄인 환경에서는 꺼진다. 행(`rowClassName`)에 애니메이션·`transform`·`clip-path` 를 직접 주지 않는다 — 컴포넌트가 행의 위치를 움직이는 것과 겹친다. `onExpandedChange` 는 모션을 기다리지 않고 누른 즉시 온다.
|
|
1979
1984
|
- **트리 컬럼에 링크·버튼을 넣어도 된다.** 셀 안의 링크·버튼·입력을 누르면 그 동작만 일어나고 펼침은 일어나지 않는다 — `stopPropagation` 을 직접 넣지 않는다. 상품명을 상세 링크로 거는 것처럼 쓴다.
|
|
1980
1985
|
- **선택은 계층을 따른다.** 부모를 고르면 접힌 하위 행까지 함께 골라지고, 일부만 골라진 부모는 "일부 선택"으로 그려진다. 하위 행이 모두 골라지면 부모도 `selected` 에 들어간다 — 처리 대상이 잎 행뿐이면 받은 목록에서 하위 행이 없는 행만 걸러 쓴다.
|
|
1981
1986
|
- **가로로 스크롤되는 표는 트리 컬럼을 왼쪽에 고정한다**(`stickyColumn={{ left: 1 }}`, 트리 컬럼이 첫 컬럼일 때). 스크롤로 들여쓰기가 밀려나면 어느 행이 누구의 하위인지 읽히지 않는다. 체크박스 열은 `selectable` 이면 늘 고정되므로 개수에 넣지 않는다.
|
|
@@ -2024,6 +2029,13 @@ const [selectedId, setSelectedId] = useState<string>();
|
|
|
2024
2029
|
- **리스트 밖 단독 `SExpansionItem` 은 본문을 다루지 않는다.** 선택하는 목록을 담으려면 `SExpansionList` 로 감싼다.
|
|
2025
2030
|
|
|
2026
2031
|
- **하위를 가지지 않는 항목은 `SExpansionItem` 이 아니라 `SListItem`** 으로 둔다. 펼칠 것이 없는데 펼침 항목으로 만들면 화살표만 남는다.
|
|
2032
|
+
- **제목 줄에 누르는 컨트롤(⋯ 메뉴·아이콘 버튼)은 `headerAction` 에 둔다.** 제목 줄은 통째로 여닫는 버튼이라 `title`·`trailing` 에 컨트롤을 넣으면 버튼이 중첩되고 누를 때마다 함께 여닫힌다. `headerAction` 은 그 버튼 밖에 그려져 눌러도 여닫히지 않는다 — `stopPropagation` 이나 제어 모드(`expanded`)로 막지 않는다. 태그·건수처럼 보기만 하는 것은 그대로 `trailing` 이다.
|
|
2033
|
+
|
|
2034
|
+
```tsx
|
|
2035
|
+
✅ <SExpansionItem title="상품 문의" trailing={<STag label="3" color="grey" />}
|
|
2036
|
+
headerAction={<SMeatballButton size="xs" items={folderMenu} onItemClick={v => onFolderAction(id, v)} />}>…</SExpansionItem>
|
|
2037
|
+
❌ <SExpansionItem title="상품 문의" trailing={<SMeatballButton … />}>…</SExpansionItem> {/* 버튼 안 버튼 — 누르면 함께 여닫힌다 */}
|
|
2038
|
+
```
|
|
2027
2039
|
|
|
2028
2040
|
#### 3-7-8. SCard vs SSectionHeaderCard
|
|
2029
2041
|
|
|
@@ -4510,7 +4522,8 @@ export default function StoreSetupPage() {
|
|
|
4510
4522
|
- **날짜가 바뀌는 자리에는 날짜 구분선을 끼운다** — 가로 `SDivider` 두 개 사이에 날짜(`typo-body-sm-default` + `text-fg-tertiary`). 일어난 사실이 아니라 흐름의 경계라 시스템 안내 알약(`SChatSystemMessage`)을 쓰지 않는다. **날짜는 `2026년 10월 6일 화요일`** 로 쓴다 — 말풍선 시각과 같은 대화 예외다(§1-4). `toLocaleDateString()` 은 로케일에 따라 결과가 바뀌므로 쓰지 않고 연·월·일·요일을 직접 이어 붙인다. 가로 구분선은 기본이 전체 폭이라 한 줄에 둘을 놓을 때는 `className="w-auto flex-1"` 로 남은 폭을 나눠 갖게 한다. 앞뒤 간격은 시스템 안내와 같은 토큰이다. 날짜가 다르면 같은 시각이어도 한 묶음으로 합치지 않는다.
|
|
4511
4523
|
- 대화의 시각은 `오후 5:52` 로 쓴다 (§1-4 대화 예외). 읽음 표시는 보낸 메시지에만, 템플릿으로 보낸 글은 `variant="template"` 로 면을 나눈다.
|
|
4512
4524
|
- **입력 중인 글은 페이지가 상담마다 든다.** 상담을 옮겨도 쓰던 글이 남고, 템플릿 패널이 그 글에 넣을 수 있다. 템플릿은 누르면 **입력창에 넣는다** — 바로 보내지 않고 상담사가 고쳐 보낸다. 보내기 전 첨부는 입력창 위에 `SChatAttachedFile` 로 쌓는다.
|
|
4513
|
-
- **첨부를 받는 대화면 `
|
|
4525
|
+
- **첨부를 받는 대화면 `onAttachFiles` 와 `onPasteFiles` 에 같은 함수를 넘긴다** — 첨부 버튼으로 고른 파일과 붙여넣은 파일·캡처 이미지를 같은 자리에 쌓는다. 파일 선택 창은 입력창이 연다 — `<input type="file">` 을 따로 두지 않는다. `onAttach` 는 서버 파일함 모달처럼 앱이 직접 고르는 흐름에만 쓴다. 붙여넣기에서 파일을 골라내고 글로 들어가지 않게 막는 것은 입력창이 한다 — `onPaste` 로 직접 처리하지 않는다. 첨부가 쌓여 있으면 `hasAttachments` 를 켠다 — 글 없이 파일만 보낼 수 있고, 이때 `onSend` 에는 빈 문자열이 온다.
|
|
4526
|
+
- **입력창의 일부만 막을 때는 그 동작만 잠근다.** 첨부가 올라가는 중이면 `sendDisabled` 로 전송만 잠근다 — 글을 적고 파일을 더 붙이는 것은 된다. 첨부 수가 상한에 닿았으면 `attachDisabled` 로 첨부를 잠그고 이유는 `attachTooltip` 으로 알린다 — 파일 붙여넣기도 함께 막힌다. 상한 아래에서 여러 파일이 한 번에 들어와 넘치는 것은 앱이 `onPasteFiles` 에서 잘라 낸다. `disabled` 는 입력까지 잠그므로 종료된 대화에만, `busy` 는 정지 버튼으로 바뀌므로 응답을 기다릴 때만 쓴다.
|
|
4514
4527
|
- **상담 종료는 `SChatInput` 의 `footerAction` 이다** — 전송과 층이 다른 동작이라 입력창 아래 보조 슬롯(`STextLink`)에 두고, 실행 전에 `SModal.confirm` 으로 묻는다. 종료된 상담은 입력창을 `disabled` 로 잠그고 종료 링크를 뺀다.
|
|
4515
4528
|
- 목록의 상태는 `STag` 다 — 색 점(`SBadge`)만으로 찍지 않는다 (§3-1). 템플릿 분류는 `SExpansionList` 루트 하나에 분류(`SExpansionItem`) 안 템플릿(`SListItem`)을 바로 넣는다 (§3-7-7).
|
|
4516
4529
|
|
|
@@ -4734,7 +4747,14 @@ function Conversation({
|
|
|
4734
4747
|
}) {
|
|
4735
4748
|
const initial = useConsultMessages(consult.id);
|
|
4736
4749
|
const [entries, setEntries] = useState<ChatEntry[]>(initial);
|
|
4737
|
-
|
|
4750
|
+
// 보내기 전 첨부. 같은 파일을 두 번 붙일 수 있으므로 이름이 아니라 id 로 가른다
|
|
4751
|
+
const [attached, setAttached] = useState<{ id: number; file: File }[]>([]);
|
|
4752
|
+
const nextAttachId = useRef(0);
|
|
4753
|
+
// 첨부 버튼으로 고른 파일과 붙여넣은 파일을 같은 함수로 받아 같은 자리에 쌓는다
|
|
4754
|
+
const addFiles = (files: File[]) => {
|
|
4755
|
+
const added = files.map(file => ({ id: nextAttachId.current++, file }));
|
|
4756
|
+
setAttached(current => [...current, ...added]);
|
|
4757
|
+
};
|
|
4738
4758
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
4739
4759
|
const closed = consult.status === 'closed';
|
|
4740
4760
|
|
|
@@ -4764,13 +4784,13 @@ function Conversation({
|
|
|
4764
4784
|
},
|
|
4765
4785
|
]
|
|
4766
4786
|
: []),
|
|
4767
|
-
...attached.map((
|
|
4787
|
+
...attached.map(({ id, file }) => ({
|
|
4768
4788
|
kind: 'message' as const,
|
|
4769
|
-
id: `f${current.length}-${
|
|
4789
|
+
id: `f${current.length}-${id}`,
|
|
4770
4790
|
direction: 'outgoing' as const,
|
|
4771
4791
|
date,
|
|
4772
4792
|
time,
|
|
4773
|
-
file: { name, size:
|
|
4793
|
+
file: { name: file.name, size: file.size },
|
|
4774
4794
|
})),
|
|
4775
4795
|
]);
|
|
4776
4796
|
onDraftChange('');
|
|
@@ -4861,11 +4881,11 @@ function Conversation({
|
|
|
4861
4881
|
<div className="flex flex-col gap-sd-8 py-sd-16">
|
|
4862
4882
|
{attached.length > 0 && (
|
|
4863
4883
|
<div className="flex flex-row flex-wrap gap-sd-8 px-sd-24">
|
|
4864
|
-
{attached.map(
|
|
4884
|
+
{attached.map(({ id, file }) => (
|
|
4865
4885
|
<SChatAttachedFile
|
|
4866
|
-
key={
|
|
4867
|
-
name={name}
|
|
4868
|
-
onRemove={() => setAttached(current => current.filter(
|
|
4886
|
+
key={id}
|
|
4887
|
+
name={file.name}
|
|
4888
|
+
onRemove={() => setAttached(current => current.filter(a => a.id !== id))}
|
|
4869
4889
|
/>
|
|
4870
4890
|
))}
|
|
4871
4891
|
</div>
|
|
@@ -4875,9 +4895,9 @@ function Conversation({
|
|
|
4875
4895
|
disabled={closed}
|
|
4876
4896
|
onValueChange={onDraftChange}
|
|
4877
4897
|
onSend={send}
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
onPasteFiles={
|
|
4898
|
+
// 파일 선택 창은 입력창이 연다 — <input type="file"> 을 따로 두지 않는다
|
|
4899
|
+
onAttachFiles={addFiles}
|
|
4900
|
+
onPasteFiles={addFiles}
|
|
4881
4901
|
// 첨부가 쌓여 있으면 글 없이도 보낼 수 있다
|
|
4882
4902
|
hasAttachments={attached.length > 0}
|
|
4883
4903
|
// 상담 종료는 전송과 층이 다른 동작 — 입력창 아래 보조 액션 슬롯이다
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
| `placeholder?` | `string` | `DEFAULT_PLACEHOLDER` | 안내 문구. 세 제품이 같은 말로 서도록 기본값을 쥐고 있다 |
|
|
13
13
|
| `disabled?` | `boolean` | `false` | 비활성 |
|
|
14
14
|
| `hasAttachments?` | `boolean` | `false` | 보낼 첨부가 쌓여 있는지. 켜면 글이 비어도 전송 버튼이 열린다 — 파일·이미지만 보낼 수 있다. 첨부 목록은 앱이 쥐므로 입력창은 그 유무만 받는다. 첨부를 받는 대화면 쌓인 첨부 수로 켠다. |
|
|
15
|
+
| `attachAccept?` | `string` | — | 파일 선택 창에서 고를 수 있는 형식 (`<input accept>` 와 같다). 예: `'image/*,.pdf'` |
|
|
16
|
+
| `attachMultiple?` | `boolean` | `true` | 파일 선택 창에서 여러 개를 한 번에 고를 수 있는지 |
|
|
17
|
+
| `attachDisabled?` | `boolean` | `false` | 첨부를 잠근다 — 첨부 버튼(파일 선택 창)이 잠기고, **파일 붙여넣기도 받지 않는다**. 입력과 전송은 그대로 둔다. 첨부 수가 상한에 닿았을 때처럼 **더 붙일 수 없는 자리**에 쓴다. 버튼만 잠그면 캡처 이미지를 붙여넣어 상한을 넘길 수 있으므로 붙여넣기도 함께 막는다 — 파일이 든 붙여넣기는 버려지고 (`onPasteFiles` 가 불리지 않는다) 파일 이름이 글로 들어가지도 않는다. 글만 붙여넣는 것은 된다. 왜 잠겼는지는 `attachTooltip` 으로 알린다. |
|
|
18
|
+
| `attachTooltip?` | `string` | — | 첨부 버튼에 마우스를 올리면 뜨는 툴팁. 받을 수 있는 파일 종류·크기나, 잠긴 이유를 적는다. 버튼의 접근성 이름("파일 첨부")은 바뀌지 않는다. |
|
|
19
|
+
| `sendDisabled?` | `boolean` | `false` | 전송을 잠근다 — 전송 버튼과 Enter 전송이 함께 잠기고, 입력과 첨부는 그대로 둔다. 첨부가 올라가는 중처럼 **아직 보낼 수 없지만 적고 붙이는 것은 되는 자리**에 쓴다. 응답을 기다리는 중이면 이것이 아니라 `busy` 를 켠다 — 그쪽은 정지 버튼으로 바뀐다. |
|
|
15
20
|
| `busy?` | `boolean` | `false` | 응답을 기다리는 중인지. 켜면 전송 버튼 자리에 정지 버튼이 서고 Enter 전송이 잠긴다 — 답이 오는 동안 또 보내지 못하게 막는 자리다. |
|
|
16
21
|
| `footerAction?` | `ReactNode` | — | 입력창 아래 보조 액션 슬롯. 없으면 그 줄이 통째로 빠진다. 상담 종료처럼 **대화 자체를 끝내는, 전송과 층이 다른 동작**이 오는 자리다. 무엇을 놓을지는 앱이 정하고, 입력창은 가운데에 세우는 것까지만 한다 — `STextLink` 를 넣는 것이 보통이다. |
|
|
17
22
|
| `maxRows?` | `number` | `DEFAULT_MAX_ROWS` | 입력창이 자랄 수 있는 최대 줄 수. 여기 닿으면 더 자라지 않고 그 안에서 스크롤한다. |
|
|
@@ -25,8 +30,9 @@
|
|
|
25
30
|
|-------|------|-------------|
|
|
26
31
|
| `onValueChange` | `(value: string) => void` | 값 변경 |
|
|
27
32
|
| `onSend` | `(value: string) => void` | 전송. 전송 버튼을 누르거나 Enter 를 쳤을 때 현재 값을 넘긴다. **값이 비면 전송 버튼이 잠긴다** — 빈 메시지는 보낼 수 없다. 단 `hasAttachments` 가 켜져 있으면 글 없이도 보낼 수 있고, 이때 빈 문자열을 넘긴다. |
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
33
|
+
| `onAttachFiles` | `(files: File[]) => void` | 첨부 버튼으로 고른 파일. **주면 입력창 왼쪽에 첨부 버튼이 서고, 누르면 파일 선택 창이 열린다.** 붙여넣기(`onPasteFiles`)와 같은 모양으로 받는다 — 두 길을 같은 함수로 받아 같은 자리에 쌓는다. 파일 선택 창은 입력창이 연다. 앱이 `<input type="file">` 을 따로 두지 않는다. |
|
|
34
|
+
| `onAttach` | `() => void` | 첨부 버튼을 누름. **주면 입력창 왼쪽에 첨부 버튼이 선다** — 파일 선택 창은 열리지 않는다. 서버 파일함 모달처럼 **앱이 직접 고르는 흐름**에만 쓴다. 기기의 파일을 고르는 것이면 `onAttachFiles` 를 준다. 둘 다 주면 `onAttachFiles` 가 쓰이고 이것은 불리지 않는다. |
|
|
35
|
+
| `onPasteFiles` | `(files: File[]) => void` | 붙여넣은 파일. 클립보드에 파일(캡처한 이미지 포함)이 있으면 불린다. **파일이 있으면 글자 붙여넣기를 막는다** — 그대로 두면 파일 이름이 글로 함께 들어간다. 파일이 없는 붙여넣기는 평소대로 글로 들어간다. 받은 파일을 어디에 쌓을지는 앱이 정한다 — 첨부 버튼으로 고른 파일(`onAttachFiles`)과 같은 함수로 받아 같은 자리에 쌓는 것이 보통이다. |
|
|
30
36
|
| `onStop` | `() => void` | 정지. `busy` 일 때 정지 버튼을 누르면 불린다 |
|
|
31
37
|
|
|
32
38
|
## Dependencies
|
|
@@ -25,14 +25,52 @@ export interface SChatInputProps extends Omit<TextareaHTMLAttributes<HTMLTextAre
|
|
|
25
25
|
* 첨부 목록은 앱이 쥐므로 입력창은 그 유무만 받는다. 첨부를 받는 대화면 쌓인 첨부 수로 켠다.
|
|
26
26
|
*/
|
|
27
27
|
hasAttachments?: boolean;
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* 첨부 버튼으로 고른 파일. **주면 입력창 왼쪽에 첨부 버튼이 서고, 누르면 파일 선택 창이 열린다.**
|
|
30
|
+
*
|
|
31
|
+
* 붙여넣기(`onPasteFiles`)와 같은 모양으로 받는다 — 두 길을 같은 함수로 받아 같은 자리에 쌓는다.
|
|
32
|
+
* 파일 선택 창은 입력창이 연다. 앱이 `<input type="file">` 을 따로 두지 않는다.
|
|
33
|
+
*/
|
|
34
|
+
onAttachFiles?: (files: File[]) => void;
|
|
35
|
+
/** 파일 선택 창에서 고를 수 있는 형식 (`<input accept>` 와 같다). 예: `'image/*,.pdf'` */
|
|
36
|
+
attachAccept?: string;
|
|
37
|
+
/** 파일 선택 창에서 여러 개를 한 번에 고를 수 있는지 */
|
|
38
|
+
attachMultiple?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* 첨부 버튼을 누름. **주면 입력창 왼쪽에 첨부 버튼이 선다** — 파일 선택 창은 열리지 않는다.
|
|
41
|
+
*
|
|
42
|
+
* 서버 파일함 모달처럼 **앱이 직접 고르는 흐름**에만 쓴다. 기기의 파일을 고르는 것이면
|
|
43
|
+
* `onAttachFiles` 를 준다. 둘 다 주면 `onAttachFiles` 가 쓰이고 이것은 불리지 않는다.
|
|
44
|
+
*/
|
|
29
45
|
onAttach?: () => void;
|
|
46
|
+
/**
|
|
47
|
+
* 첨부를 잠근다 — 첨부 버튼(파일 선택 창)이 잠기고, **파일 붙여넣기도 받지 않는다**. 입력과
|
|
48
|
+
* 전송은 그대로 둔다.
|
|
49
|
+
*
|
|
50
|
+
* 첨부 수가 상한에 닿았을 때처럼 **더 붙일 수 없는 자리**에 쓴다. 버튼만 잠그면 캡처 이미지를
|
|
51
|
+
* 붙여넣어 상한을 넘길 수 있으므로 붙여넣기도 함께 막는다 — 파일이 든 붙여넣기는 버려지고
|
|
52
|
+
* (`onPasteFiles` 가 불리지 않는다) 파일 이름이 글로 들어가지도 않는다. 글만 붙여넣는 것은 된다.
|
|
53
|
+
* 왜 잠겼는지는 `attachTooltip` 으로 알린다.
|
|
54
|
+
*/
|
|
55
|
+
attachDisabled?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* 첨부 버튼에 마우스를 올리면 뜨는 툴팁. 받을 수 있는 파일 종류·크기나, 잠긴 이유를 적는다.
|
|
58
|
+
* 버튼의 접근성 이름("파일 첨부")은 바뀌지 않는다.
|
|
59
|
+
*/
|
|
60
|
+
attachTooltip?: string;
|
|
61
|
+
/**
|
|
62
|
+
* 전송을 잠근다 — 전송 버튼과 Enter 전송이 함께 잠기고, 입력과 첨부는 그대로 둔다.
|
|
63
|
+
*
|
|
64
|
+
* 첨부가 올라가는 중처럼 **아직 보낼 수 없지만 적고 붙이는 것은 되는 자리**에 쓴다. 응답을
|
|
65
|
+
* 기다리는 중이면 이것이 아니라 `busy` 를 켠다 — 그쪽은 정지 버튼으로 바뀐다.
|
|
66
|
+
*/
|
|
67
|
+
sendDisabled?: boolean;
|
|
30
68
|
/**
|
|
31
69
|
* 붙여넣은 파일. 클립보드에 파일(캡처한 이미지 포함)이 있으면 불린다.
|
|
32
70
|
*
|
|
33
71
|
* **파일이 있으면 글자 붙여넣기를 막는다** — 그대로 두면 파일 이름이 글로 함께 들어간다.
|
|
34
72
|
* 파일이 없는 붙여넣기는 평소대로 글로 들어간다. 받은 파일을 어디에 쌓을지는 앱이 정한다 —
|
|
35
|
-
* 첨부
|
|
73
|
+
* 첨부 버튼으로 고른 파일(`onAttachFiles`)과 같은 함수로 받아 같은 자리에 쌓는 것이 보통이다.
|
|
36
74
|
*/
|
|
37
75
|
onPasteFiles?: (files: File[]) => void;
|
|
38
76
|
/**
|
|
@@ -65,13 +103,25 @@ export interface SChatInputProps extends Omit<TextareaHTMLAttributes<HTMLTextAre
|
|
|
65
103
|
*
|
|
66
104
|
* 첨부·입력·전송을 한 줄로 세우고, 필요하면 그 아래 보조 액션(상담 종료 등)을 붙인다.
|
|
67
105
|
* Enter 로 보내고 Shift+Enter 로 줄을 바꾼다 — 한글 조합 중의 Enter 는 보내지 않는다.
|
|
68
|
-
*
|
|
69
|
-
* 글 없이도 보낼 수 있다.
|
|
106
|
+
* 첨부 버튼으로 고른 파일은 `onAttachFiles`, 붙여넣은 파일은 `onPasteFiles` 로 넘기고, 첨부가
|
|
107
|
+
* 쌓여 있으면(`hasAttachments`) 글 없이도 보낼 수 있다.
|
|
70
108
|
*
|
|
71
109
|
* **글이 길어지면 입력창이 자란다** — `maxRows` 줄까지 늘어나고, 거기 닿으면 그 안에서
|
|
72
110
|
* 스크롤한다. 상한이 없으면 대화가 화면 밖으로 밀려난다.
|
|
73
111
|
*
|
|
74
112
|
* **응답을 기다리는 동안에는 `busy` 를 켠다** — 전송 버튼이 정지 버튼으로 바뀌고 Enter 전송이
|
|
75
113
|
* 잠겨, 답이 오는 중에 또 보내는 일이 막힌다.
|
|
114
|
+
*
|
|
115
|
+
* **잠금 규칙** — 무엇을 막을지에 따라 하나만 켠다. 함께 켜면 표의 위쪽이 이긴다.
|
|
116
|
+
*
|
|
117
|
+
* | prop | 입력 | 첨부(파일 선택·붙여넣기) | 전송(버튼·Enter) | 정지 | 쓰는 자리 |
|
|
118
|
+
* | --- | --- | --- | --- | --- | --- |
|
|
119
|
+
* | `disabled` | 잠금 | 잠금 | 잠금 | 잠금 | 대화가 끝났다 |
|
|
120
|
+
* | `busy` | 열림 | 그대로 | 정지 버튼으로 바뀜 | 열림 | 응답을 기다린다 |
|
|
121
|
+
* | `sendDisabled` | 열림 | 그대로 | 잠금 | — | 첨부가 올라가는 중이다 |
|
|
122
|
+
* | `attachDisabled` | 열림 | 잠금 | 그대로 | — | 첨부 수가 상한에 닿았다 |
|
|
123
|
+
*
|
|
124
|
+
* 첨부 잠금은 나머지와 따로 움직인다 — `busy`·`sendDisabled` 와 함께 켜도 첨부만 더
|
|
125
|
+
* 잠길 뿐이다. 전송은 이와 별개로 글도 첨부(`hasAttachments`)도 없으면 잠긴다.
|
|
76
126
|
*/
|
|
77
127
|
export declare const SChatInput: import("react").ForwardRefExoticComponent<SChatInputProps & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
| `placeholder?` | `string` | — | |
|
|
34
34
|
| `selectable?` | `[string, string]` | — | 선택 가능 범위 [시작, 종료] |
|
|
35
35
|
| `disabled?` | `boolean` | `false` | |
|
|
36
|
+
| `showWeekday?` | `boolean` | `false` | 트리거에 보이는 날짜 뒤에 요일을 붙인다 — `2026-10-19 월요일`. 표시만 바뀌고 `value`·`onValueChange` 의 형식(`YYYY-MM-DD`)은 그대로다. `mode="date"` 에서만 동작한다 (월·연도에는 요일이 없다). 붙는 글자(띄어쓰기 + 요일 3자)만큼 내장 폭 하한·상한이 넓어진다. |
|
|
36
37
|
| `clearable?` | `boolean` | `false` | 선택값 지우기 버튼. 값이 있을 때만 나타나고, 누르면 `onValueChange` 로 `null` 이 온다. **필수 입력 필드에는 켜지 않는다** — 지우면 다시 고르기 전까지 폼이 통과하지 못한다. `STimePicker` · `STimeRangePicker` · `SSelect` 의 `clearable` 과 같은 규칙이다. |
|
|
37
38
|
| `width?` | `SFieldWidth` | — | 컨트롤 너비 — 폭 등급(`'xs' | 'sm' | 'md' | 'lg' | 'xl'`) · 숫자=px · CSS 길이. 등급은 `--cmp-field-width-*` 토큰으로 풀리므로 토큰이 바뀌면 화면이 따라간다. 값 길이에 상한이 없으면 `"100%"` 로 두어 행 전체를 쓴다. |
|
|
38
39
|
| `maxWidth?` | `SFieldWidth` | — | 컨트롤 최대 너비 — 폭 등급 · 숫자=px · CSS 길이. 지정하지 않으면 값 길이(`YYYY-MM-DD`)에 맞춘 내장 상한(`size='md'` → `lg`, `'sm'` → `md`)이 걸려, `width="100%"` 를 받아도 행 전체로 늘어나지 않는다. 팝오버처럼 폭이 이미 좁게 정해진 자리에서 그 폭을 그대로 채워야 하면 `width="100%"` 와 함께 `maxWidth="100%"` 를 준다. `0` 은 상한을 아예 걸지 않는다 — 부모보다 넓어지는 것까지 허용해야 할 때만 쓴다. |
|
|
@@ -24,6 +24,14 @@ export interface SDatePickerProps {
|
|
|
24
24
|
/** 선택 가능 범위 [시작, 종료] */
|
|
25
25
|
selectable?: [string, string];
|
|
26
26
|
disabled?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* 트리거에 보이는 날짜 뒤에 요일을 붙인다 — `2026-10-19 월요일`.
|
|
29
|
+
*
|
|
30
|
+
* 표시만 바뀌고 `value`·`onValueChange` 의 형식(`YYYY-MM-DD`)은 그대로다.
|
|
31
|
+
* `mode="date"` 에서만 동작한다 (월·연도에는 요일이 없다).
|
|
32
|
+
* 붙는 글자(띄어쓰기 + 요일 3자)만큼 내장 폭 하한·상한이 넓어진다.
|
|
33
|
+
*/
|
|
34
|
+
showWeekday?: boolean;
|
|
27
35
|
/**
|
|
28
36
|
* 선택값 지우기 버튼. 값이 있을 때만 나타나고, 누르면 `onValueChange` 로 `null` 이 온다.
|
|
29
37
|
*
|
|
@@ -109,4 +117,4 @@ export interface SDatePickerMonthListboxProps {
|
|
|
109
117
|
* 자체 트리거/팝오버 없이 연도+월 리스트만 필요한 커스텀 조합에 재사용한다. */
|
|
110
118
|
export declare function SDatePickerMonthListbox({ value, anchorYear, selectable, onValueChange, onMonthSelect, className, style, }: SDatePickerMonthListboxProps): import("react").JSX.Element;
|
|
111
119
|
/** SDatePicker — sd-date-picker 포팅. SField + SPopover(SCalendar). */
|
|
112
|
-
export declare function SDatePicker({ value, onValueChange, onViewChange, mode, size, placeholder, selectable, disabled, clearable, width, maxWidth, name, rules, status, label, labelPosition, subLabel, labelWidth, icon, iconColor, labelTooltip, labelTooltipProps, addonLabel, addonAlign, hint, error, errorMessage, className, style, }: SDatePickerProps): import("react").JSX.Element;
|
|
120
|
+
export declare function SDatePicker({ value, onValueChange, onViewChange, mode, size, placeholder, selectable, disabled, showWeekday, clearable, width, maxWidth, name, rules, status, label, labelPosition, subLabel, labelWidth, icon, iconColor, labelTooltip, labelTooltipProps, addonLabel, addonAlign, hint, error, errorMessage, className, style, }: SDatePickerProps): import("react").JSX.Element;
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
| `selectable?` | `[string, string]` | — | |
|
|
15
15
|
| `maxRange?` | `number` | — | 최대 선택 일수 |
|
|
16
16
|
| `showTimePicker?` | `boolean` | `false` | 시간(시:분) 선택 푸터 사용 여부. true이면 value는 "YYYY-MM-DD HH:mm" 형식이 되고, 캘린더 하단에 시작·종료 시간 입력이 표시된다. |
|
|
17
|
+
| `showWeekday?` | `boolean` | `false` | 트리거에 보이는 시작·종료 날짜 뒤에 요일을 붙인다 — `2026-10-19 월요일 ~ 2026-10-25 일요일`. `showTimePicker` 와 함께 쓰면 요일이 날짜와 시간 사이에 온다 (`2026-10-19 월요일 09:00`). 표시만 바뀌고 `value`·`onValueChange` 의 형식은 그대로다. 붙는 글자(띄어쓰기 + 요일 3자, 양쪽)만큼 내장 폭 하한·상한이 넓어진다. |
|
|
17
18
|
| `disabled?` | `boolean` | `false` | |
|
|
18
19
|
| `clearable?` | `boolean` | `false` | 선택값 지우기 버튼. 값이 있을 때만 나타나고, 누르면 `onValueChange` 로 `null` 이 온다. **필수 입력 필드에는 켜지 않는다** — 지우면 다시 고르기 전까지 폼이 통과하지 못한다. `SDatePicker` · `STimePicker` · `SSelect` 의 `clearable` 과 같은 규칙이다. |
|
|
19
20
|
| `width?` | `SFieldWidth` | — | 컨트롤 너비 — 폭 등급(`'xs' | 'sm' | 'md' | 'lg' | 'xl'`) · 숫자=px · CSS 길이. 등급은 `--cmp-field-width-*` 토큰으로 풀리므로 토큰이 바뀌면 화면이 따라간다. 값 길이에 상한이 없으면 `"100%"` 로 두어 행 전체를 쓴다. |
|
|
@@ -26,6 +26,14 @@ export interface SDateRangePickerProps {
|
|
|
26
26
|
* true이면 value는 "YYYY-MM-DD HH:mm" 형식이 되고, 캘린더 하단에 시작·종료 시간 입력이 표시된다.
|
|
27
27
|
*/
|
|
28
28
|
showTimePicker?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* 트리거에 보이는 시작·종료 날짜 뒤에 요일을 붙인다 — `2026-10-19 월요일 ~ 2026-10-25 일요일`.
|
|
31
|
+
* `showTimePicker` 와 함께 쓰면 요일이 날짜와 시간 사이에 온다 (`2026-10-19 월요일 09:00`).
|
|
32
|
+
*
|
|
33
|
+
* 표시만 바뀌고 `value`·`onValueChange` 의 형식은 그대로다.
|
|
34
|
+
* 붙는 글자(띄어쓰기 + 요일 3자, 양쪽)만큼 내장 폭 하한·상한이 넓어진다.
|
|
35
|
+
*/
|
|
36
|
+
showWeekday?: boolean;
|
|
29
37
|
disabled?: boolean;
|
|
30
38
|
/**
|
|
31
39
|
* 선택값 지우기 버튼. 값이 있을 때만 나타나고, 누르면 `onValueChange` 로 `null` 이 온다.
|
|
@@ -98,4 +106,4 @@ export interface SRangeCalendarProps {
|
|
|
98
106
|
* 캘린더 그리드만 필요한 커스텀 조합(예: 다른 트리거에 팝오버로 얹는 경우)에 재사용한다. */
|
|
99
107
|
export declare function RangeCalendar({ value, selectable, maxRange, showTimePicker, onSelect, onPendingStartChange, onViewChange, }: SRangeCalendarProps): import("react").JSX.Element;
|
|
100
108
|
/** SDateRangePicker — sd-date-range-picker 포팅. SField + SPopover(범위 캘린더). */
|
|
101
|
-
export declare function SDateRangePicker({ value, onValueChange, onViewChange, size, placeholder, selectable, maxRange, showTimePicker, disabled, clearable, width, maxWidth, name, rules, status, label, labelPosition, subLabel, labelWidth, icon, iconColor, labelTooltip, labelTooltipProps, addonLabel, addonAlign, hint, error, errorMessage, className, style, }: SDateRangePickerProps): import("react").JSX.Element;
|
|
109
|
+
export declare function SDateRangePicker({ value, onValueChange, onViewChange, size, placeholder, selectable, maxRange, showTimePicker, showWeekday, disabled, clearable, width, maxWidth, name, rules, status, label, labelPosition, subLabel, labelWidth, icon, iconColor, labelTooltip, labelTooltipProps, addonLabel, addonAlign, hint, error, errorMessage, className, style, }: SDateRangePickerProps): import("react").JSX.Element;
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
| `depth?` | `1 \| 2 \| 3` | `1` | 중첩 단계. Figma 기준 1~3단계. `SExpansionList` 안에서는 주지 않아도 중첩에서 정해진다 — 직접 주면 그 값이 우선한다. |
|
|
15
15
|
| `leading?` | `ReactNode \| SExpansionItemRenderProp` | — | 타이틀 앞에 표시할 아이콘/콘텐츠 |
|
|
16
16
|
| `trailing?` | `ReactNode` | — | 타이틀 뒤에 표시할 태그/콘텐츠 |
|
|
17
|
+
| `headerAction?` | `ReactNode` | — | 제목 줄 오른쪽 끝에 놓는 컨트롤 슬롯 — ⋯ 메뉴·아이콘 버튼처럼 **누르는 것**이 오는 자리다. 제목 줄은 통째로 여닫는 `<button>` 이라 `title`·`trailing` 에 컨트롤을 넣으면 버튼 안에 버튼이 중첩되고, 누를 때마다 항목이 함께 여닫힌다. 이 슬롯은 그 버튼 **밖**에 그려지므로 눌러도 여닫히지 않고, Tab 으로 따로 닿는다. 태그·숫자처럼 보기만 하는 것은 `trailing` 에 둔다. 항목이 `disabled` 여도 슬롯은 잠그지 않는다 — 잠글지는 넣은 컨트롤에 앱이 정한다. |
|
|
17
18
|
| `bodyPadding?` | `boolean` | `true` | body 내부 패딩 사용 여부. `SExpansionList` 안에서 본문이 목록(`SListItem`·`SExpansionItem` 만, 또는 `SExpansionList`)이면 기본으로 꺼진다. |
|
|
18
19
|
| `bordered?` | `boolean` | `false` | 외곽 테두리 사용 여부 |
|
|
19
20
|
| `expanded?` | `boolean` | — | |
|
|
@@ -23,6 +23,16 @@ export interface SExpansionItemProps extends Omit<HTMLAttributes<HTMLDivElement>
|
|
|
23
23
|
leading?: ReactNode | SExpansionItemRenderProp;
|
|
24
24
|
/** 타이틀 뒤에 표시할 태그/콘텐츠 */
|
|
25
25
|
trailing?: ReactNode;
|
|
26
|
+
/**
|
|
27
|
+
* 제목 줄 오른쪽 끝에 놓는 컨트롤 슬롯 — ⋯ 메뉴·아이콘 버튼처럼 **누르는 것**이 오는 자리다.
|
|
28
|
+
*
|
|
29
|
+
* 제목 줄은 통째로 여닫는 `<button>` 이라 `title`·`trailing` 에 컨트롤을 넣으면 버튼 안에 버튼이
|
|
30
|
+
* 중첩되고, 누를 때마다 항목이 함께 여닫힌다. 이 슬롯은 그 버튼 **밖**에 그려지므로 눌러도
|
|
31
|
+
* 여닫히지 않고, Tab 으로 따로 닿는다. 태그·숫자처럼 보기만 하는 것은 `trailing` 에 둔다.
|
|
32
|
+
*
|
|
33
|
+
* 항목이 `disabled` 여도 슬롯은 잠그지 않는다 — 잠글지는 넣은 컨트롤에 앱이 정한다.
|
|
34
|
+
*/
|
|
35
|
+
headerAction?: ReactNode;
|
|
26
36
|
/**
|
|
27
37
|
* body 내부 패딩 사용 여부.
|
|
28
38
|
* `SExpansionList` 안에서 본문이 목록(`SListItem`·`SExpansionItem` 만, 또는 `SExpansionList`)이면 기본으로 꺼진다.
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
| `ariaExpanded?` | `boolean` | — | disclosure 버튼일 때 펼침 상태 (aria-expanded) |
|
|
17
17
|
| `tooltipText?` | `string` | — | 호버 시 표시할 툴팁 텍스트 |
|
|
18
18
|
| `disabled?` | `boolean` | `false` | 비활성 |
|
|
19
|
+
| `href?` | `string` | — | 이동할 주소. **주면 `<button>` 대신 `<a>` 로 그린다** — 가운데 클릭·⌘클릭·주소 복사가 링크처럼 듣는다. 눌러서 다른 화면·문서로 가는 버튼이면 `onClick` 에서 `location` 을 바꾸지 말고 이것을 준다. 비활성이면 주소를 떼어 눌러도 가지 않는다. |
|
|
20
|
+
| `target?` | `string` | — | `href` 를 여는 곳. `'_blank'` 면 `rel="noopener noreferrer"` 를 함께 붙인다 |
|
|
19
21
|
| `anchorClassName?` | `string` | — | tooltip anchor wrapper 클래스. tooltipText가 있을 때 위치 조정용으로 사용합니다. |
|
|
20
22
|
| `anchorStyle?` | `CSSProperties` | — | tooltip anchor wrapper 스타일. tooltipText가 있을 때 위치 조정용으로 사용합니다. |
|
|
21
23
|
| `className?` | `string` | — | |
|
|
@@ -25,7 +27,7 @@
|
|
|
25
27
|
|
|
26
28
|
| Event | Type | Description |
|
|
27
29
|
|-------|------|-------------|
|
|
28
|
-
| `onClick` | `(e: MouseEvent<HTMLButtonElement>) => void` | 클릭 (sdClick) |
|
|
30
|
+
| `onClick` | `(e: MouseEvent<HTMLButtonElement \| HTMLAnchorElement>) => void` | 클릭 (sdClick). `href` 와 함께 주면 이동 전에 불린다 |
|
|
29
31
|
|
|
30
32
|
## Types
|
|
31
33
|
|
|
@@ -2,6 +2,8 @@ import { type CSSProperties, type MouseEvent } from 'react';
|
|
|
2
2
|
import { type SIconName } from '../SIcon';
|
|
3
3
|
export type SGhostButtonSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg';
|
|
4
4
|
export type SGhostButtonIntent = 'default' | 'danger' | 'action' | 'subAction' | 'complete' | 'inverse';
|
|
5
|
+
/** `href` 가 없으면 `<button>`, 있으면 `<a>` 로 그린다 */
|
|
6
|
+
type GhostButtonElement = HTMLButtonElement | HTMLAnchorElement;
|
|
5
7
|
export interface SGhostButtonProps {
|
|
6
8
|
/** 표시할 아이콘명 (필수) */
|
|
7
9
|
icon: SIconName;
|
|
@@ -19,8 +21,17 @@ export interface SGhostButtonProps {
|
|
|
19
21
|
tooltipText?: string;
|
|
20
22
|
/** 비활성 */
|
|
21
23
|
disabled?: boolean;
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
+
/**
|
|
25
|
+
* 이동할 주소. **주면 `<button>` 대신 `<a>` 로 그린다** — 가운데 클릭·⌘클릭·주소 복사가 링크처럼 듣는다.
|
|
26
|
+
*
|
|
27
|
+
* 눌러서 다른 화면·문서로 가는 버튼이면 `onClick` 에서 `location` 을 바꾸지 말고 이것을 준다.
|
|
28
|
+
* 비활성이면 주소를 떼어 눌러도 가지 않는다.
|
|
29
|
+
*/
|
|
30
|
+
href?: string;
|
|
31
|
+
/** `href` 를 여는 곳. `'_blank'` 면 `rel="noopener noreferrer"` 를 함께 붙인다 */
|
|
32
|
+
target?: string;
|
|
33
|
+
/** 클릭 (sdClick). `href` 와 함께 주면 이동 전에 불린다 */
|
|
34
|
+
onClick?: (e: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;
|
|
24
35
|
/** tooltip anchor wrapper 클래스. tooltipText가 있을 때 위치 조정용으로 사용합니다. */
|
|
25
36
|
anchorClassName?: string;
|
|
26
37
|
/** tooltip anchor wrapper 스타일. tooltipText가 있을 때 위치 조정용으로 사용합니다. */
|
|
@@ -32,7 +43,11 @@ export interface SGhostButtonProps {
|
|
|
32
43
|
* SGhostButton — sd-ghost-button 포팅. 아이콘 전용 투명 버튼.
|
|
33
44
|
* hover 시 intent 색 오버레이(5%), focus-visible 링, 옵션 툴팁(회색 STag).
|
|
34
45
|
*
|
|
46
|
+
* `href` 를 주면 같은 모양의 링크(`<a>`)로 그린다.
|
|
47
|
+
*
|
|
35
48
|
* ref 는 버튼 요소로 그대로 간다 — 이 버튼에 붙여 띄우는 층(SGnb 런처의 서비스 목록 등)이
|
|
36
49
|
* 버튼을 앵커로 삼아야 한다. 툴팁을 두른 형태에서도 앵커는 래퍼가 아니라 버튼이다.
|
|
50
|
+
* 링크로 그리면 ref 는 `<a>` 로 간다.
|
|
37
51
|
*/
|
|
38
|
-
export declare const SGhostButton: import("react").ForwardRefExoticComponent<SGhostButtonProps & import("react").RefAttributes<
|
|
52
|
+
export declare const SGhostButton: import("react").ForwardRefExoticComponent<SGhostButtonProps & import("react").RefAttributes<GhostButtonElement>>;
|
|
53
|
+
export {};
|