sellmate-design-system-react 9.0.0-beta.40 → 9.0.0-beta.42
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 +41 -20
- package/dist/components/SBarcodeInput/README.md +3 -3
- package/dist/components/SBarcodeInput/SBarcodeInput.d.ts +3 -1
- package/dist/components/SChipInput/README.md +1 -1
- package/dist/components/SChipInput/SChipInput.d.ts +1 -1
- package/dist/components/SConfirmModal/README.md +3 -11
- package/dist/components/SConfirmModal/SConfirmModal.d.ts +16 -8
- package/dist/components/SConfirmModal/index.d.ts +1 -1
- package/dist/components/SDateRangePicker/README.md +2 -2
- package/dist/components/SDateRangePicker/SDateRangePicker.d.ts +4 -4
- package/dist/components/SEditor/EditorBody.d.ts +1 -1
- package/dist/components/SEditor/README.md +4 -4
- package/dist/components/SEditor/SEditor.d.ts +3 -3
- package/dist/components/SField/README.md +2 -2
- package/dist/components/SField/SField.d.ts +8 -2
- package/dist/components/SFilePicker/README.md +3 -3
- package/dist/components/SFilePicker/SFilePicker.d.ts +4 -4
- package/dist/components/SForm/README.md +1 -1
- package/dist/components/SForm/SForm.d.ts +2 -2
- package/dist/components/SGnb/README.md +7 -7
- package/dist/components/SGnb/SGnb.d.ts +9 -9
- package/dist/components/SGnb/gnb.config.d.ts +2 -2
- package/dist/components/SImage/README.md +1 -1
- package/dist/components/SImage/SImage.d.ts +2 -2
- package/dist/components/SInput/README.md +3 -3
- package/dist/components/SInput/SInput.d.ts +3 -3
- package/dist/components/SLayout/README.md +1 -1
- package/dist/components/SLayout/SLayout.d.ts +2 -2
- package/dist/components/SList/README.md +10 -2
- package/dist/components/SList/SList.d.ts +7 -3
- package/dist/components/SList/index.d.ts +1 -1
- package/dist/components/SLoadingModal/README.md +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.d.ts +2 -2
- package/dist/components/SModal/README.md +1 -1
- package/dist/components/SNumberInput/README.md +5 -5
- package/dist/components/SNumberInput/SNumberInput.d.ts +5 -3
- package/dist/components/SPage/README.md +42 -3
- package/dist/components/SPage/SPage.d.ts +16 -1
- package/dist/components/SPage/SPageHeader.d.ts +19 -8
- package/dist/components/SPage/index.d.ts +1 -1
- package/dist/components/SPage/page-column.d.ts +11 -2
- package/dist/components/SPage/page-width.d.ts +23 -0
- package/dist/components/SPage/page.config.d.ts +18 -0
- package/dist/components/SPopup/README.md +8 -2
- package/dist/components/SPopup/SPopup.d.ts +7 -3
- package/dist/components/SPopup/index.d.ts +1 -1
- package/dist/components/SSearchInput/README.md +3 -3
- package/dist/components/SSearchInput/SSearchInput.d.ts +3 -3
- package/dist/components/SSelect/README.md +5 -5
- package/dist/components/SSelect/SSelect.d.ts +14 -6
- package/dist/components/SSplitter/README.md +2 -2
- package/dist/components/SSplitter/SSplitter.d.ts +7 -3
- package/dist/components/SSwitch/README.md +0 -1
- package/dist/components/SSwitch/SSwitch.d.ts +1 -3
- package/dist/components/STable/README.md +8 -9
- package/dist/components/STable/STable.d.ts +9 -11
- package/dist/components/STabs/README.md +1 -1
- package/dist/components/STabs/STabs.d.ts +2 -2
- package/dist/components/STextLink/README.md +1 -1
- package/dist/components/STextLink/STextLink.d.ts +1 -1
- package/dist/components/STextarea/README.md +3 -3
- package/dist/components/STextarea/STextarea.d.ts +3 -3
- package/dist/components/STimePicker/README.md +1 -1
- package/dist/components/STimePicker/STimePicker.d.ts +4 -4
- package/dist/components/STimeRangePicker/README.md +1 -1
- package/dist/components/STimeRangePicker/STimeRangePicker.d.ts +4 -4
- package/dist/components/SToast/README.md +1 -1
- package/dist/components/SToast/SToast.d.ts +2 -2
- package/dist/components/STooltip/README.md +1 -1
- package/dist/components/STooltip/STooltip.d.ts +1 -1
- package/dist/components/STree/README.md +4 -4
- package/dist/components/STree/STree.d.ts +17 -5
- package/dist/index.cjs +365 -248
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +364 -249
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +170 -106
- package/dist/llms.txt +41 -20
- package/dist/styles.css +9 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -712,8 +712,8 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
712
712
|
|
|
713
713
|
- 작은 창이 아니라 **화면 하나가 통째로** 들어간다 — 검색 필터·테이블·페이지네이션이 그대로 있는 목록(`엑셀 파일 관리`), 헤더 카드·탭이 있는 상세(`이동 오더 상세`).
|
|
714
714
|
- 상세를 팝업으로 여는 이유는 **목록을 떠나지 않고 여러 건을 번갈아 보기** 위해서다. 단 상세가 **항상** 팝업인 것은 아니고, 데이터 양이 많을 때 팝업을 쓴다.
|
|
715
|
-
- 구조는 헤더(제목 중앙) + 본문이고 **푸터는 기본으로 없다**. 조회만 하는 팝업은 그대로 두고, **확정할 작업이 있을 때만 `
|
|
716
|
-
- **본문 패딩은 `SPopup` 이 토큰으로 넣는다. 직접 주지 않는다** (`p-sd-*` 로 덮어쓰면 토큰이 바뀌어도 안 따라간다). 표를 가장자리까지 채우는 등 콘텐츠가 여백을 직접 다뤄야 할 때만 `
|
|
715
|
+
- 구조는 헤더(제목 중앙) + 본문이고 **푸터는 기본으로 없다**. 조회만 하는 팝업은 그대로 두고, **확정할 작업이 있을 때만 `showFooter` 로 푸터를 켜서 `submitButton` 에 `저장`** 을 둔다.
|
|
716
|
+
- **본문 패딩은 `SPopup` 이 토큰으로 넣는다. 직접 주지 않는다** (`p-sd-*` 로 덮어쓰면 토큰이 바뀌어도 안 따라간다). 표를 가장자리까지 채우는 등 콘텐츠가 여백을 직접 다뤄야 할 때만 `padding="none"` 으로 끈다.
|
|
717
717
|
- 그 밖에는 팝업 안도 일반 페이지와 같은 규칙(§4)을 따른다: 블록 간격 `gap-sd-12`, 표는 `SKeyValueTable` / `STable`.
|
|
718
718
|
|
|
719
719
|
```tsx
|
|
@@ -1295,7 +1295,7 @@ const columns: STableColumn[] = [
|
|
|
1295
1295
|
- 모델은 항상 **첫 패널**(`SSplitter.Before`) 크기다. 사이드가 기준인 화면이면 사이드를 `Before` 에 둔다.
|
|
1296
1296
|
- 앱 셸의 GNB 폭은 `SGnb` 가 소유한다. `SLayout`/`SGnb` 를 `SSplitter` 로 감싸지 않는다 — **GNB 폭을 끌 수 있게 하려면 `SGnb` 에 `resizable` 을 준다**(§4-1).
|
|
1297
1297
|
|
|
1298
|
-
**Quasar `q-splitter` 에서 옮겨올 때** — `unit` · `limits` · `
|
|
1298
|
+
**Quasar `q-splitter` 에서 옮겨올 때** — `unit` · `limits` · `updateWhileDragging` 는 이름과 뜻이 같고, 나머지는 아래처럼 바뀐다. `updateWhileDragging` 를 주지 않으면 **드래그를 놓는 순간 한 번만** `onValueChange` 가 온다.
|
|
1299
1299
|
|
|
1300
1300
|
| q-splitter | SSplitter |
|
|
1301
1301
|
| --- | --- |
|
|
@@ -1450,12 +1450,12 @@ const [from, setFrom] = useState<string | null>(null);
|
|
|
1450
1450
|
- **항목 하나의 속성을 나열하는 것은 목록이 아니다.** `라벨: 값` 이 세로로 쌓이는 것은 `SKeyValueTable` 이다 (§4-4).
|
|
1451
1451
|
- `SList` 는 레이아웃만 담당한다. depth 별 단일 펼침이 필요하면 `SExpansionList` 다 (§3-7-7).
|
|
1452
1452
|
- **`SList` 의 자식은 `SListItem` 을 권장한다.** 다른 자식도 그대로 렌더되지만, 펼치는 항목은 `SExpansionList` + `SExpansionItem` 이, 끌어서 순서를 바꾸는 항목은 `SDraggableList` + `SDraggableItem` 이 여닫힘·정렬 동작까지 함께 관리하므로 그쪽을 쓴다 (§3-7-7).
|
|
1453
|
-
- **항목 사이 구분선은 리스트가 알아서 그린다.** `SListItem`·`SExpansionItem`·`SDraggableItem` 셋 다 스스로 구분선을 그리지 않는다. `SList`·`SExpansionList`·`SDraggableList` 가 자식 **사이에** 구분선을 넣으므로 아이템에 `border-b` 를 직접 붙이지 않고, 켜는 prop 도 따로 없다. 마지막 항목 아래에는 선이 남지 않는다. 테두리형(`bordered`)은 테두리가 구분 역할을 하므로 리스트가 구분선을 빼고, `
|
|
1453
|
+
- **항목 사이 구분선은 리스트가 알아서 그린다.** `SListItem`·`SExpansionItem`·`SDraggableItem` 셋 다 스스로 구분선을 그리지 않는다. `SList`·`SExpansionList`·`SDraggableList` 가 자식 **사이에** 구분선을 넣으므로 아이템에 `border-b` 를 직접 붙이지 않고, 켜는 prop 도 따로 없다. 마지막 항목 아래에는 선이 남지 않는다. 테두리형(`bordered`)은 테두리가 구분 역할을 하므로 리스트가 구분선을 빼고, `gap` 으로 띄운다 — `gap` 을 준 목록에도 구분선은 들어가지 않는다.
|
|
1454
1454
|
- **`SListItem` 은 기본이 표시 전용이다.** 눌러서 이동·선택하게 하려면 `clickable` 을 준다 — hover·`selected`·`interaction="chevron"` 표현이 전부 여기에 딸려 있어서, `clickable` 없이 `selected` 만 주면 선택 표시가 나오지 않는다. `SExpansionList` 는 자식 아이템을 알아서 클릭 가능하게 만들어 이 함정을 막아 준다 — 선택 상태 자체는 앱이 든다 (§3-7-7).
|
|
1455
1455
|
|
|
1456
1456
|
```tsx
|
|
1457
1457
|
✅ <SList><SListItem title="일반 문의" />…</SList> {/* 줄로 구분되는 목록 — 구분선은 자동 */}
|
|
1458
|
-
✅ <SList
|
|
1458
|
+
✅ <SList gap><SListItem title="일반 문의" bordered />…</SList> {/* 카드처럼 떨어진 목록 */}
|
|
1459
1459
|
✅ <SListItem title="일반 문의" clickable selected onClick={…} /> {/* 눌러서 고르는 목록 */}
|
|
1460
1460
|
❌ <SList><SListItem title="일반 문의" className="border-b" />…</SList> {/* 구분선을 직접 붙이지 않는다 */}
|
|
1461
1461
|
❌ <SList><><SListItem title="일반 문의" /><SListItem title="결제 문의" /></></SList> {/* Fragment 로 묶으면 그 안쪽은 구분되지 않는다 */}
|
|
@@ -1601,6 +1601,7 @@ export default function AppShell({
|
|
|
1601
1601
|
header?: SPageHeaderProps;
|
|
1602
1602
|
scrollEndSpacing?: boolean;
|
|
1603
1603
|
contentHeight?: SPageContentHeight;
|
|
1604
|
+
contentWidth?: SPageContentWidth;
|
|
1604
1605
|
}) {
|
|
1605
1606
|
return (
|
|
1606
1607
|
<SLayout type="box" header="fix">
|
|
@@ -1612,7 +1613,13 @@ export default function AppShell({
|
|
|
1612
1613
|
{/* 콘텐츠 패딩은 SPage 가 토큰으로 넣는다 — p-sd-* 로 덮어쓰지 않는다 */}
|
|
1613
1614
|
{/* 높이 모드는 페이지가 정한다 — 대부분 contentHeight="fill" 이다 (§2-2) */}
|
|
1614
1615
|
{/* 스크롤 끝 여백도 SPage 가 넣는다. 페이지가 실제로 스크롤되는 화면에서만 켠다 */}
|
|
1615
|
-
|
|
1616
|
+
{/* 가로 폭 모드도 페이지가 정한다 — 넓은 창에서 본문을 늘릴지 최소 폭으로 세울지 */}
|
|
1617
|
+
<SPage
|
|
1618
|
+
background="frame"
|
|
1619
|
+
scrollEndSpacing={scrollEndSpacing}
|
|
1620
|
+
contentHeight={contentHeight}
|
|
1621
|
+
contentWidth={contentWidth}
|
|
1622
|
+
>
|
|
1616
1623
|
{children}
|
|
1617
1624
|
</SPage>
|
|
1618
1625
|
</SLayout>
|
|
@@ -1628,7 +1635,7 @@ export default function AppShell({
|
|
|
1628
1635
|
|
|
1629
1636
|
**페이지 헤더 사용 규칙 — 이 앱에서는 값이 아니라 값의 일관성이 규칙이다.**
|
|
1630
1637
|
|
|
1631
|
-
- **`
|
|
1638
|
+
- **`variant` 는 필수이고, 앱 전체에서 하나로 고정한다.** 어떤 페이지는 `"bar"`(높이 고정 + 하단 구분선), 다른 페이지는 `"plain"`(최소 높이) 로 섞어 쓰지 않는다. 프로젝트에서 하나를 고르면(예: 전부 `"bar"`) 모든 페이지 헤더가 그 값을 쓴다. **기본값이 없는 것도 이 규칙 때문이다** — 기본값이 있으면 안 준 페이지만 조용히 다른 모양이 되어 메뉴를 옮길 때마다 제목 줄이 튄다. 셸을 한 번 감싸 쓰면 지정하는 자리는 `AppShell` 한 곳이다. `SLayout` 의 `header`(`"fix" | "full"`)와는 다른 축이다 — 그쪽은 상단바가 GNB 컬럼 안에 있는지 화면 전폭인지를 정한다.
|
|
1632
1639
|
- **`slot`·`onBack` 도 페이지 성격이 실제로 다른 경우가 아니면 있는 대로 통일한다.** "목록 페이지엔 없고 상세·등록 페이지엔 있다"처럼 화면 종류에 따라 갈리는 것은 허용되지만, 같은 종류의 화면끼리는 임의로 넣었다 뺐다 하지 않는다.
|
|
1633
1640
|
- **`slot` 은 `ReactNode` 를 그대로 받지만, 원칙은 `size="sm"` 버튼 위주로만 채운다.** `STextLink`·복잡한 커스텀 마크업을 슬롯에 넣지 않는다 — 그 이상이 필요하면 페이지 헤더가 아니라 §4-2 의 `STableBar` 처럼 본문 쪽 액션 자리를 쓴다.
|
|
1634
1641
|
|
|
@@ -1641,7 +1648,7 @@ const [scrolled, setScrolled] = useState(false);
|
|
|
1641
1648
|
|
|
1642
1649
|
{/* 헤더는 자기 흰 면을 스스로 칠한다 — 감싸는 쪽은 본문이 놓일 면만 정하면 된다 */}
|
|
1643
1650
|
<div className="flex h-full min-h-0 flex-col bg-[var(--sys-color-bg-frame)]">
|
|
1644
|
-
<SPageHeader title="상품 목록" subText="판매 중인 상품을 관리합니다." scrolled={scrolled} />
|
|
1651
|
+
<SPageHeader variant="plain" title="상품 목록" subText="판매 중인 상품을 관리합니다." scrolled={scrolled} />
|
|
1645
1652
|
{/* 스크롤을 앱이 쥐므로 scrolled 도 앱이 넣는다 — 패딩은 SPage 가 없으니 여기서 준다 */}
|
|
1646
1653
|
<div
|
|
1647
1654
|
className="min-h-0 flex-1 overflow-auto p-sd-16"
|
|
@@ -1678,7 +1685,20 @@ import { SModalOutlet } from 'sellmate-design-system-react';
|
|
|
1678
1685
|
|
|
1679
1686
|
**최소 너비는 `SLayout` 이 보장한다 — 앱이 `min-w-*` 를 직접 주지 않는다.** 창이 최소 너비(`SLAYOUT_MIN_WIDTH`, GNB 포함한 전체 기준)보다 좁아지면 GNB·상단바는 제자리에 남고 **`SPage` 안에만 가로 스크롤이 생긴다.** 문서(브라우저 창)에는 가로 스크롤이 생기지 않는다. 그래서 셸을 감싸는 요소에 `min-width` 나 `overflow-x` 를 걸지 않는다 — 걸면 창 전체가 스크롤되어 GNB 가 화면 밖으로 밀린다.
|
|
1680
1687
|
|
|
1681
|
-
|
|
1688
|
+
**창이 최소 너비보다 넓을 때 본문을 어떻게 세울지는 `SPage` 의 `contentWidth` 가 정한다 — 폭을 직접 계산하지 않는다.** 넓은 모니터에서 본문이 끝까지 늘어나 성기어지는 화면이 있으므로 세 가지 중 하나를 고른다.
|
|
1689
|
+
|
|
1690
|
+
| `contentWidth` | 넓은 창에서 | 쓰는 곳 |
|
|
1691
|
+
| --- | --- | --- |
|
|
1692
|
+
| `"full"` (기본) | 남는 폭을 본문이 다 쓴다 | 표·목록처럼 가로를 넓게 쓸수록 정보가 더 들어가는 화면 |
|
|
1693
|
+
| `"fixed"` | 최소 너비일 때의 본문 폭으로 고정, 왼쪽 정렬 (남는 폭은 오른쪽) | 시안 폭 그대로 세우되 왼쪽 기준을 유지할 화면 |
|
|
1694
|
+
| `"fixedCenter"` | 같은 폭으로 고정, 가운데 정렬 (남는 폭은 좌우) | 폼·상세처럼 가로를 넓게 써도 얻을 것이 없는 화면 |
|
|
1695
|
+
|
|
1696
|
+
- **고정 폭에 숫자를 쓰지 않는다.** `max-w-*` 나 `mx-auto` 로 흉내 내면 GNB 폭·접힘이 반영되지 않아 시안과 어긋난다. 고정 폭은 "창이 최소 너비일 때의 본문 폭"이고 `SPage` 가 GNB 상태까지 반영해 계산한다.
|
|
1697
|
+
- **창이 최소 너비보다 좁아지면 세 모드가 모두 같다** — 남는 폭이 없으므로 위 문단대로 `SPage` 안에만 가로 스크롤이 생긴다.
|
|
1698
|
+
- 같은 열의 `SPageHeader` 는 자동으로 같은 폭·정렬을 따른다 — 제목 줄에 별도로 주지 않는다. 헤더의 흰 면·구분선은 늘 전폭이다.
|
|
1699
|
+
- **같은 종류의 화면끼리는 값을 통일한다** (헤더 `fix` 와 같은 이유). 목록 페이지마다 `full`·`fixedCenter` 가 섞이면 메뉴를 옮길 때마다 본문 폭이 튄다.
|
|
1700
|
+
|
|
1701
|
+
**셸의 `SPage` 는 모든 페이지가 공유하므로, 페이지마다 달라지는 것은 페이지가 셸에 알려야 한다.** 위처럼 프레임 컴포넌트가 `contentHeight` · `scrollEndSpacing` · `contentWidth` 를 받아 그대로 넘긴다.
|
|
1682
1702
|
|
|
1683
1703
|
**대부분의 페이지는 `contentHeight="fill"` 이다** — 본문이 창을 꽉 채우고 스크롤은 각 영역 안에서 일어나는 것이 표준이다(§2-2). 블록의 높이가 정해져 있고 그 높이가 창보다 커서 페이지 자체가 스크롤돼야 하는 화면에서만 `contentHeight="auto"`(기본값) + `scrollEndSpacing` 을 켠다.
|
|
1684
1704
|
|
|
@@ -1714,14 +1734,14 @@ import { SModalOutlet } from 'sellmate-design-system-react';
|
|
|
1714
1734
|
</SLayout>
|
|
1715
1735
|
```
|
|
1716
1736
|
|
|
1717
|
-
**메뉴 목록과 함께 스크롤되면 안 되는 것은 `SGnb` 의 위아래 고정 슬롯에 둔다.** 레일과 메뉴에 각각 위(`railTop`·`menuTop`)와 아래(`railFooter`·`menuFooter`) 슬롯이 있다. 아이템이 많아 넘치면 **목록만 스크롤되고 이 슬롯들은 제자리에 남는다** — 메뉴 검색, 워크스페이스 전환, 계정 행처럼 항상 보여야 하는 것이 여기 온다. 레일 슬롯은 `
|
|
1737
|
+
**메뉴 목록과 함께 스크롤되면 안 되는 것은 `SGnb` 의 위아래 고정 슬롯에 둔다.** 레일과 메뉴에 각각 위(`railTop`·`menuTop`)와 아래(`railFooter`·`menuFooter`) 슬롯이 있다. 아이템이 많아 넘치면 **목록만 스크롤되고 이 슬롯들은 제자리에 남는다** — 메뉴 검색, 워크스페이스 전환, 계정 행처럼 항상 보여야 하는 것이 여기 온다. 레일 슬롯은 `showRail` 일 때만, 메뉴 슬롯은 깔 메뉴가 있을 때만 렌더된다.
|
|
1718
1738
|
|
|
1719
1739
|
**접으면 레일·메뉴가 통째로 빠져나가면서 그 슬롯들도 함께 사라진다.** 접힌 상태에서도 남겨야 할 것은 `foldedTop`·`foldedFooter` 로 따로 준다 — `header="fix"` 로 접혔을 때만 나타나며, 폭이 좁은 폴드 레일이므로 아이콘 버튼 하나 정도로 줄인다.
|
|
1720
1740
|
|
|
1721
1741
|
```tsx
|
|
1722
1742
|
{/* 접히면 menuTop·menuFooter 가 함께 빠지므로, 폴드 레일에 남길 것만 foldedTop 으로 따로 준다 */}
|
|
1723
1743
|
<SGnb
|
|
1724
|
-
items={MENU} value={current} onValueChange={navigate}
|
|
1744
|
+
items={MENU} value={current} onValueChange={navigate} showRail
|
|
1725
1745
|
menuTop={<SSearchInput value={keyword} onValueChange={setKeyword} placeholder="메뉴 검색" />}
|
|
1726
1746
|
menuFooter={<AccountRow />}
|
|
1727
1747
|
foldedTop={<SGhostButton icon="search" size="sm" ariaLabel="메뉴 검색" onClick={openSearch} />}
|
|
@@ -1784,7 +1804,7 @@ import { SModalOutlet } from 'sellmate-design-system-react';
|
|
|
1784
1804
|
- **닫힘은 `onTooltipDismiss` 로 받아 `tooltip` 을 비워 둔다.** 같은 값을 계속 넘기는 동안에는 다시 뜨지 않고, **비웠다 다시 넘기면 문구가 같아도 새 안내로 뜬다** — 새 알림마다 같은 안내를 다시 띄우는 화면이 막히지 않는다.
|
|
1785
1805
|
- 재노출 신호는 문구가 **없음 → 있음** 으로 바뀌는 것이다. 한 이벤트 핸들러 안에서 비웠다 곧바로 넣으면 렌더가 한 번으로 묶여 신호가 되지 않는다 — 닫을 때 비우고, 다시 필요할 때 넘긴다.
|
|
1786
1806
|
- 컴포넌트가 아는 범위는 그 자리가 서 있는 동안뿐이다(새로고침하거나 GNB 를 접어 알림이 다른 자리로 옮겨 서면 새로 마운트된다). **그 사용자에게 두 번 다시 보이지 않아야 하면 앱이 닫힘을 저장해 두고 `tooltip` 을 넘기지 않는다.**
|
|
1787
|
-
- **`header="fix"` + `
|
|
1807
|
+
- **`header="fix"` + `showRail` 에서 하위 메뉴가 없는 레일 아이템이 활성이면 메뉴 컬럼째 사라지므로 이 패널도 함께 빠진다.** 항상 보여야 하는 계정·알림이라면 그런 레일 리프를 두지 않는다 — 또는 `header="full"` 로 두면 상단바에 남는다(그런 레일 리프가 있으면 GNB 가 `header` 를 `full` 로 강제한다).
|
|
1788
1808
|
|
|
1789
1809
|
### 4-2. 목록 페이지 (필터 + 테이블)
|
|
1790
1810
|
|
|
@@ -1812,7 +1832,7 @@ import {
|
|
|
1812
1832
|
const filterFields: SKeyValueField[][] = [
|
|
1813
1833
|
[
|
|
1814
1834
|
{ name: 'status', label: '상태', type: 'select',
|
|
1815
|
-
options: { options: STATUS_OPTIONS,
|
|
1835
|
+
options: { options: STATUS_OPTIONS, valueAsPrimitive: true } },
|
|
1816
1836
|
{ name: 'keyword', label: '검색어', type: 'input',
|
|
1817
1837
|
options: { placeholder: '상품명 / 상품코드' } },
|
|
1818
1838
|
],
|
|
@@ -1844,6 +1864,7 @@ export default function ProductListPage() {
|
|
|
1844
1864
|
return (
|
|
1845
1865
|
<AppShell
|
|
1846
1866
|
header={{
|
|
1867
|
+
variant: 'bar',
|
|
1847
1868
|
title: '상품 목록',
|
|
1848
1869
|
// 이 페이지의 주요 액션이 아니라 부가 액션 — slot 은 sm 버튼으로만 채운다
|
|
1849
1870
|
slot: <SButton size="sm" color="neutral" outline label="이용 가이드" onClick={openGuide} />,
|
|
@@ -1886,7 +1907,7 @@ export default function ProductListPage() {
|
|
|
1886
1907
|
selected={selected}
|
|
1887
1908
|
onSelectedChange={setSelected}
|
|
1888
1909
|
pagination={{ currentPage, lastPage }}
|
|
1889
|
-
|
|
1910
|
+
loading={loading}
|
|
1890
1911
|
/>
|
|
1891
1912
|
</div>
|
|
1892
1913
|
</AppShell>
|
|
@@ -1902,7 +1923,7 @@ export default function ProductListPage() {
|
|
|
1902
1923
|
|
|
1903
1924
|
```tsx
|
|
1904
1925
|
// 좁게 시작하고, 사용자가 바꾸는 밀도는 표가 알아서 들고 간다
|
|
1905
|
-
<STable dense
|
|
1926
|
+
<STable dense showRowsPerPageSelect pagination={{ currentPage, lastPage }} />;
|
|
1906
1927
|
|
|
1907
1928
|
// 사용자가 고른 밀도를 다음 방문에도 남기려는 화면만 받아서 저장한다.
|
|
1908
1929
|
// 저장한 값은 시작 밀도로만 돌려준다 — 되돌려 넣지 않는다
|
|
@@ -1911,7 +1932,7 @@ const [initialDense] = useState(() => loadPref('list.dense', true));
|
|
|
1911
1932
|
<STable
|
|
1912
1933
|
dense={initialDense}
|
|
1913
1934
|
onDenseChange={next => savePref('list.dense', next)}
|
|
1914
|
-
|
|
1935
|
+
showRowsPerPageSelect
|
|
1915
1936
|
pagination={{ currentPage, lastPage }}
|
|
1916
1937
|
/>;
|
|
1917
1938
|
```
|
|
@@ -1959,7 +1980,7 @@ const fields: SKeyValueField[][] = [
|
|
|
1959
1980
|
],
|
|
1960
1981
|
[
|
|
1961
1982
|
{ name: 'category', label: '카테고리', required: true, type: 'select',
|
|
1962
|
-
options: { options: CATEGORY_OPTIONS,
|
|
1983
|
+
options: { options: CATEGORY_OPTIONS, valueAsPrimitive: true,
|
|
1963
1984
|
rules: [required('카테고리를 선택해 주세요.')] } },
|
|
1964
1985
|
{ name: 'price', label: '판매가', type: 'number-input' },
|
|
1965
1986
|
],
|
|
@@ -1974,9 +1995,9 @@ export default function ProductCreatePage() {
|
|
|
1974
1995
|
const [values, setValues] = useState<Record<string, unknown>>({});
|
|
1975
1996
|
|
|
1976
1997
|
return (
|
|
1977
|
-
<AppShell header={{ title: '상품 등록', onBack: goBack }}>
|
|
1998
|
+
<AppShell header={{ variant: 'bar', title: '상품 등록', onBack: goBack }}>
|
|
1978
1999
|
<div className="flex flex-col gap-sd-12">
|
|
1979
|
-
<SForm ref={formRef}
|
|
2000
|
+
<SForm ref={formRef} formClassName="flex flex-col gap-sd-12" onSubmit={save}>
|
|
1980
2001
|
<SKeyValueTable
|
|
1981
2002
|
fields={fields}
|
|
1982
2003
|
values={values}
|
|
@@ -2037,7 +2058,7 @@ const priceFields: SKeyValueField[][] = [
|
|
|
2037
2058
|
export default function ProductDetailPage() {
|
|
2038
2059
|
return (
|
|
2039
2060
|
// 목록에서 들어온 상세 페이지 — onBack 으로 뒤로가기를 준다
|
|
2040
|
-
<AppShell header={{
|
|
2061
|
+
<AppShell header={{ variant: 'bar', title: '클래식 셔츠', onBack: goList }}>
|
|
2041
2062
|
<div className="flex flex-col gap-sd-12">
|
|
2042
2063
|
<SSectionHeaderCard title="기본 정보" marker thickness="accent">
|
|
2043
2064
|
<SKeyValueTable fields={basicFields} values={product} />
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
| `readOnly?` | `boolean` | `false` | |
|
|
19
19
|
| `rules?` | `Rule[]` | — | |
|
|
20
20
|
| `status?` | `SFieldStatus` | — | |
|
|
21
|
-
| `focused?` | `boolean` | — |
|
|
22
|
-
| `hovered?` | `boolean` | — |
|
|
21
|
+
| `focused?` | `boolean` | — | 포커스 상태를 밖에서 지정한다 — 강조 테두리·링이 즉시 걸린다 (SField 로 그대로 넘어간다) |
|
|
22
|
+
| `hovered?` | `boolean` | — | 호버 상태를 밖에서 지정한다 — 강조는 `focused` 와 같다 (SField 로 그대로 넘어간다) |
|
|
23
23
|
| `prefix?` | `ReactNode` | — | 입력 앞 슬롯 |
|
|
24
24
|
| `suffix?` | `ReactNode` | — | 입력 뒤 슬롯 |
|
|
25
|
-
| `
|
|
25
|
+
| `inputClassName?` | `string` | — | |
|
|
26
26
|
| `inputStyle?` | `CSSProperties` | — | |
|
|
27
27
|
| `label?` | `string` | — | |
|
|
28
28
|
| `labelWidth?` | `number \| string` | — | |
|
|
@@ -21,13 +21,15 @@ export interface SBarcodeInputProps {
|
|
|
21
21
|
readOnly?: boolean;
|
|
22
22
|
rules?: Rule[];
|
|
23
23
|
status?: SFieldStatus;
|
|
24
|
+
/** 포커스 상태를 밖에서 지정한다 — 강조 테두리·링이 즉시 걸린다 (SField 로 그대로 넘어간다) */
|
|
24
25
|
focused?: boolean;
|
|
26
|
+
/** 호버 상태를 밖에서 지정한다 — 강조는 `focused` 와 같다 (SField 로 그대로 넘어간다) */
|
|
25
27
|
hovered?: boolean;
|
|
26
28
|
/** 입력 앞 슬롯 */
|
|
27
29
|
prefix?: ReactNode;
|
|
28
30
|
/** 입력 뒤 슬롯 */
|
|
29
31
|
suffix?: ReactNode;
|
|
30
|
-
|
|
32
|
+
inputClassName?: string;
|
|
31
33
|
inputStyle?: CSSProperties;
|
|
32
34
|
label?: string;
|
|
33
35
|
labelWidth?: number | string;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
| `name?` | `string` | — | |
|
|
18
18
|
| `rules?` | `Rule[]` | — | |
|
|
19
19
|
| `error?` | `boolean` | — | |
|
|
20
|
-
| `
|
|
20
|
+
| `showReset?` | `boolean` | `false` | 입력 초기화 버튼 표시 |
|
|
21
21
|
| `maxCount?` | `number` | — | 최대 칩 개수 |
|
|
22
22
|
| `metaPlacement?` | `SChipInputMetaPlacement` | `'end'` | 최대 개수·초기화 meta 위치 |
|
|
23
23
|
| `duplicateLabel?` | `string` | — | 중복 에러 메시지 항목명 |
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
| `persistent?` | `boolean` | `false` | 백드롭·ESC로 안 닫히고 흔들림 (sd-modal-container persistent). **기본값 false** — 확인 모달은 잃을 입력이 없어 백드롭·ESC로 닫힌다 |
|
|
13
13
|
| `type?` | `SConfirmModalType` | `'positive'` | 타입 (아이콘·메인버튼 색 결정) |
|
|
14
14
|
| `modalTitle?` | `string` | `''` | |
|
|
15
|
-
| `
|
|
15
|
+
| `titleClassName?` | `string` | — | 제목 엘리먼트에 추가할 클래스 (sd-confirm-modal titleClassName) |
|
|
16
16
|
| `topMessage?` | `string[]` | `[]` | 콘텐츠 박스 상단 메시지 목록 (각 항목이 한 줄, HTML 문자열 허용 — innerHTML 렌더링) |
|
|
17
17
|
| `bottomMessage?` | `string[]` | `[]` | 콘텐츠 박스 하단 메시지 목록 (각 항목이 한 줄, HTML 문자열 허용 — innerHTML 렌더링) |
|
|
18
18
|
| `tagLabel?` | `string` | — | tag 슬롯 기본 태그 레이블 (tagSlot 미지정 시) |
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
| `tagSlot?` | `ReactNode` | — | 콘텐츠 박스 tag 위치 커스텀 콘텐츠 (미지정 시 tagLabel 기반 STag) |
|
|
24
24
|
| `optionSlot?` | `ReactNode` | — | 콘텐츠 박스에서 태그 오른쪽 커스텀 콘텐츠 (미지정 시 slotLabel 텍스트) |
|
|
25
25
|
| `contentSlot?` | `ReactNode` | — | 콘텐츠 박스 바로 아래에 통으로 들어가는 커스텀 콘텐츠 (전체 폭) |
|
|
26
|
-
| `mainButtonLabel?` | `string` | `'확인'` | 메인
|
|
27
|
-
| `
|
|
26
|
+
| `mainButtonLabel?` | `string` | `'확인'` | 메인(확인) 버튼에 찍히는 글자 |
|
|
27
|
+
| `mainButtonOutline?` | `boolean` | — | 메인 버튼을 아웃라인(테두리)으로 세울지. 지정하지 않으면 `type` 이 정한다 — positive·negative 는 채운 버튼, default 는 아웃라인. **색은 여기서 고르지 않는다.** `type` 이 정한다(positive=primary / negative=danger / default=neutral) — 아이콘·제목이 말하는 것과 버튼 색이 어긋나면 읽는 사람이 헷갈리므로 그 조합은 타입에서 막는다. 글자는 `mainButtonLabel` 이다. `type="default"` 에 `false` 를 주면 테두리 없는 흰 버튼이 된다(neutral 은 solid·outline 이 같은 흰 면이고 테두리 유무만 다르다). 확인 버튼이 눌러야 할 것으로 안 읽히므로 권하지 않는다. |
|
|
28
28
|
| `subButtonLabel?` | `string` | — | 서브(취소) 버튼 |
|
|
29
29
|
|
|
30
30
|
#### Events
|
|
@@ -44,14 +44,6 @@
|
|
|
44
44
|
export type SConfirmModalType = 'positive' | 'negative' | 'default';
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
### SConfirmModalMainButton
|
|
48
|
-
|
|
49
|
-
```ts
|
|
50
|
-
/** 확인 버튼 프리셋 (sd-confirm-modal ConfirmModalMainButton) */
|
|
51
|
-
export type SConfirmModalMainButton =
|
|
52
|
-
'primary_md' | 'primary_outline_md' | 'danger_md' | 'danger_outline_md' | 'neutral_outline_md';
|
|
53
|
-
```
|
|
54
|
-
|
|
55
47
|
## Dependencies
|
|
56
48
|
|
|
57
49
|
### Used by
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import { type STagColor, type STagShape, type STagSize } from '../STag';
|
|
3
3
|
export type SConfirmModalType = 'positive' | 'negative' | 'default';
|
|
4
|
-
/** 확인 버튼 프리셋 (sd-confirm-modal ConfirmModalMainButton) */
|
|
5
|
-
export type SConfirmModalMainButton = 'primary_md' | 'primary_outline_md' | 'danger_md' | 'danger_outline_md' | 'neutral_outline_md';
|
|
6
4
|
export interface SConfirmModalProps {
|
|
7
5
|
open?: boolean;
|
|
8
6
|
onOpenChange?: (open: boolean) => void;
|
|
@@ -11,8 +9,8 @@ export interface SConfirmModalProps {
|
|
|
11
9
|
/** 타입 (아이콘·메인버튼 색 결정) */
|
|
12
10
|
type?: SConfirmModalType;
|
|
13
11
|
modalTitle?: string;
|
|
14
|
-
/** 제목 엘리먼트에 추가할 클래스 (sd-confirm-modal
|
|
15
|
-
|
|
12
|
+
/** 제목 엘리먼트에 추가할 클래스 (sd-confirm-modal titleClassName) */
|
|
13
|
+
titleClassName?: string;
|
|
16
14
|
/** 콘텐츠 박스 상단 메시지 목록 (각 항목이 한 줄, HTML 문자열 허용 — innerHTML 렌더링) */
|
|
17
15
|
topMessage?: string[];
|
|
18
16
|
/** 콘텐츠 박스 하단 메시지 목록 (각 항목이 한 줄, HTML 문자열 허용 — innerHTML 렌더링) */
|
|
@@ -31,10 +29,20 @@ export interface SConfirmModalProps {
|
|
|
31
29
|
optionSlot?: ReactNode;
|
|
32
30
|
/** 콘텐츠 박스 바로 아래에 통으로 들어가는 커스텀 콘텐츠 (전체 폭) */
|
|
33
31
|
contentSlot?: ReactNode;
|
|
34
|
-
/** 메인
|
|
32
|
+
/** 메인(확인) 버튼에 찍히는 글자 */
|
|
35
33
|
mainButtonLabel?: string;
|
|
36
|
-
/**
|
|
37
|
-
|
|
34
|
+
/**
|
|
35
|
+
* 메인 버튼을 아웃라인(테두리)으로 세울지. 지정하지 않으면 `type` 이 정한다 —
|
|
36
|
+
* positive·negative 는 채운 버튼, default 는 아웃라인.
|
|
37
|
+
*
|
|
38
|
+
* **색은 여기서 고르지 않는다.** `type` 이 정한다(positive=primary / negative=danger /
|
|
39
|
+
* default=neutral) — 아이콘·제목이 말하는 것과 버튼 색이 어긋나면 읽는 사람이 헷갈리므로
|
|
40
|
+
* 그 조합은 타입에서 막는다. 글자는 `mainButtonLabel` 이다.
|
|
41
|
+
*
|
|
42
|
+
* `type="default"` 에 `false` 를 주면 테두리 없는 흰 버튼이 된다(neutral 은 solid·outline 이
|
|
43
|
+
* 같은 흰 면이고 테두리 유무만 다르다). 확인 버튼이 눌러야 할 것으로 안 읽히므로 권하지 않는다.
|
|
44
|
+
*/
|
|
45
|
+
mainButtonOutline?: boolean;
|
|
38
46
|
/** 서브(취소) 버튼 */
|
|
39
47
|
subButtonLabel?: string;
|
|
40
48
|
/** 확인 버튼 클릭 (sdOk) */
|
|
@@ -44,4 +52,4 @@ export interface SConfirmModalProps {
|
|
|
44
52
|
onClose?: () => void;
|
|
45
53
|
}
|
|
46
54
|
/** SConfirmModal — sd-confirm-modal 포팅. 아이콘+제목+메시지+태그+확인/취소 버튼. */
|
|
47
|
-
export declare function SConfirmModal({ open, onOpenChange, persistent, type, modalTitle,
|
|
55
|
+
export declare function SConfirmModal({ open, onOpenChange, persistent, type, modalTitle, titleClassName, topMessage, bottomMessage, tagLabel, tagShape, tagSize, tagColor, slotLabel, tagSlot, optionSlot, contentSlot, mainButtonLabel, mainButtonOutline, subButtonLabel, onOk, onCancel, onClose, }: SConfirmModalProps): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { SConfirmModal, type
|
|
1
|
+
export { SConfirmModal, type SConfirmModalProps, type SConfirmModalType } from './SConfirmModal';
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
| `placeholder?` | `string` | `'YYYY-MM-DD ~ YYYY-MM-DD'` | |
|
|
14
14
|
| `selectable?` | `[string, string]` | — | |
|
|
15
15
|
| `maxRange?` | `number` | — | 최대 선택 일수 |
|
|
16
|
-
| `
|
|
16
|
+
| `showTimePicker?` | `boolean` | `false` | 시간(시:분) 선택 푸터 사용 여부. true이면 value는 "YYYY-MM-DD HH:mm" 형식이 되고, 캘린더 하단에 시작·종료 시간 입력이 표시된다. |
|
|
17
17
|
| `disabled?` | `boolean` | `false` | |
|
|
18
18
|
| `clearable?` | `boolean` | `false` | 선택값 지우기 버튼. 값이 있을 때만 나타나고, 누르면 `onValueChange` 로 `null` 이 온다. **필수 입력 필드에는 켜지 않는다** — 지우면 다시 고르기 전까지 폼이 통과하지 못한다. `SDatePicker` · `STimePicker` · `SSelect` 의 `clearable` 과 같은 규칙이다. |
|
|
19
19
|
| `width?` | `SFieldWidth` | — | 컨트롤 너비 — 폭 등급(`'xs' | 'sm' | 'md' | 'lg' | 'xl'`) · 숫자=px · CSS 길이. 등급은 `--cmp-field-width-*` 토큰으로 풀리므로 토큰이 바뀌면 화면이 따라간다. 값 길이에 상한이 없으면 `"100%"` 로 두어 행 전체를 쓴다. |
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
| `value` | `SDateRangeValue` | — | |
|
|
51
51
|
| `selectable?` | `[string, string]` | — | |
|
|
52
52
|
| `maxRange?` | `number` | — | |
|
|
53
|
-
| `
|
|
53
|
+
| `showTimePicker?` | `boolean` | `false` | |
|
|
54
54
|
|
|
55
55
|
#### Events
|
|
56
56
|
|
|
@@ -25,7 +25,7 @@ export interface SDateRangePickerProps {
|
|
|
25
25
|
* 시간(시:분) 선택 푸터 사용 여부.
|
|
26
26
|
* true이면 value는 "YYYY-MM-DD HH:mm" 형식이 되고, 캘린더 하단에 시작·종료 시간 입력이 표시된다.
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
showTimePicker?: boolean;
|
|
29
29
|
disabled?: boolean;
|
|
30
30
|
/**
|
|
31
31
|
* 선택값 지우기 버튼. 값이 있을 때만 나타나고, 누르면 `onValueChange` 로 `null` 이 온다.
|
|
@@ -61,7 +61,7 @@ export interface SRangeCalendarProps {
|
|
|
61
61
|
value: SDateRangeValue;
|
|
62
62
|
selectable?: [string, string];
|
|
63
63
|
maxRange?: number;
|
|
64
|
-
|
|
64
|
+
showTimePicker?: boolean;
|
|
65
65
|
onSelect: (r: [string, string]) => void;
|
|
66
66
|
/** 시작일만 선택된(종료일 대기) 상태를 상위로 전달 — 트리거에 `start ~` 프리뷰 표시용 */
|
|
67
67
|
onPendingStartChange?: (start: string | null) => void;
|
|
@@ -72,6 +72,6 @@ export interface SRangeCalendarProps {
|
|
|
72
72
|
}
|
|
73
73
|
/** RangeCalendar — SDateRangePicker의 캘린더 부분만 떼어낸 조각. 자체 트리거/팝오버 없이
|
|
74
74
|
* 캘린더 그리드만 필요한 커스텀 조합(예: 다른 트리거에 팝오버로 얹는 경우)에 재사용한다. */
|
|
75
|
-
export declare function RangeCalendar({ value, selectable, maxRange,
|
|
75
|
+
export declare function RangeCalendar({ value, selectable, maxRange, showTimePicker, onSelect, onPendingStartChange, onViewChange, }: SRangeCalendarProps): import("react").JSX.Element;
|
|
76
76
|
/** SDateRangePicker — sd-date-range-picker 포팅. SField + SPopover(범위 캘린더). */
|
|
77
|
-
export declare function SDateRangePicker({ value, onValueChange, onViewChange, size, placeholder, selectable, maxRange,
|
|
77
|
+
export declare function SDateRangePicker({ value, onValueChange, onViewChange, size, placeholder, selectable, maxRange, showTimePicker, disabled, clearable, width, name, rules, status, label, labelWidth, icon, iconColor, labelTooltip, labelTooltipProps, addonLabel, addonAlign, hint, error, errorMessage, className, style, }: SDateRangePickerProps): import("react").JSX.Element;
|
|
@@ -23,7 +23,7 @@ export interface EditorBodyProps {
|
|
|
23
23
|
/** 선택 영역 위에 뜨는 서식 판 — 편집할 수 있으면 언제나 뜬다 (SEditor 주석 참고) */
|
|
24
24
|
bubbleMenu: SEditorToolbarItem[];
|
|
25
25
|
onImageUpload?: (file: File) => Promise<string>;
|
|
26
|
-
|
|
26
|
+
editorClassName?: string;
|
|
27
27
|
editorStyle?: CSSProperties;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
| `maxHeight?` | `number \| string` | — | |
|
|
20
20
|
| `toolbar` | `SEditorToolbarItem[]` | — | |
|
|
21
21
|
| `bubbleMenu` | `SEditorToolbarItem[]` | — | 선택 영역 위에 뜨는 서식 판 — 편집할 수 있으면 언제나 뜬다 (SEditor 주석 참고) |
|
|
22
|
-
| `
|
|
22
|
+
| `editorClassName?` | `string` | — | |
|
|
23
23
|
| `editorStyle?` | `CSSProperties` | — | |
|
|
24
24
|
|
|
25
25
|
#### Events
|
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
| `simple?` | `boolean` | `false` | **글자에 거는 서식만** 남긴다 — 목록·정렬·인용·코드·링크·이미지·구분선이 빠진다. 막대와 버블 메뉴 양쪽에 함께 걸린다 (한쪽에만 남으면 아무것도 막지 못한다). 받은 글의 문단 구조까지 작성자를 따라가면 곤란한 자리 — 좁은 칸의 메모·사유·짧은 안내문 — 에 쓴다. 반대로 서식이 아예 필요 없다면 `SEditor` 가 아니라 `STextarea` 다. |
|
|
64
64
|
| `rules?` | `Rule[]` | — | 유효성 규칙 — blur 시 자동 검증 |
|
|
65
65
|
| `status?` | `SFieldStatus` | — | 필드 상태 ('default' | 'pass' | 'error') |
|
|
66
|
-
| `focused?` | `boolean` | — | 포커스
|
|
67
|
-
| `hovered?` | `boolean` | — | 호버
|
|
66
|
+
| `focused?` | `boolean` | — | 포커스 상태를 밖에서 지정한다 — 강조 테두리·링이 즉시 걸린다 (SField 로 그대로 넘어간다) |
|
|
67
|
+
| `hovered?` | `boolean` | — | 호버 상태를 밖에서 지정한다 — 강조는 `focused` 와 같다 (SField 로 그대로 넘어간다) |
|
|
68
68
|
| `name?` | `string` | — | 폼 전송용 name |
|
|
69
|
-
| `
|
|
69
|
+
| `editorClassName?` | `string` | — | 편집 영역 className |
|
|
70
70
|
| `editorStyle?` | `CSSProperties` | — | 편집 영역 style |
|
|
71
71
|
| `label?` | `string` | — | |
|
|
72
72
|
| `labelWidth?` | `number \| string` | — | |
|
|
@@ -54,14 +54,14 @@ export interface SEditorProps {
|
|
|
54
54
|
rules?: Rule[];
|
|
55
55
|
/** 필드 상태 ('default' | 'pass' | 'error') */
|
|
56
56
|
status?: SFieldStatus;
|
|
57
|
-
/** 포커스
|
|
57
|
+
/** 포커스 상태를 밖에서 지정한다 — 강조 테두리·링이 즉시 걸린다 (SField 로 그대로 넘어간다) */
|
|
58
58
|
focused?: boolean;
|
|
59
|
-
/** 호버
|
|
59
|
+
/** 호버 상태를 밖에서 지정한다 — 강조는 `focused` 와 같다 (SField 로 그대로 넘어간다) */
|
|
60
60
|
hovered?: boolean;
|
|
61
61
|
/** 폼 전송용 name */
|
|
62
62
|
name?: string;
|
|
63
63
|
/** 편집 영역 className */
|
|
64
|
-
|
|
64
|
+
editorClassName?: string;
|
|
65
65
|
/** 편집 영역 style */
|
|
66
66
|
editorStyle?: CSSProperties;
|
|
67
67
|
/** 포커스 진입 */
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
| `error?` | `boolean` | `false` | 에러 상태 |
|
|
23
23
|
| `errorMessage?` | `string` | `''` | 에러 메시지 |
|
|
24
24
|
| `status?` | `SFieldStatus` | — | 필드 상태 — 'error' | 'pass' | 'default'. 'pass'면 초록 테두리 |
|
|
25
|
-
| `focused?` | `boolean` | `false` | 포커스
|
|
26
|
-
| `hovered?` | `boolean` | `false` | 호버
|
|
25
|
+
| `focused?` | `boolean` | `false` | 포커스 상태를 밖에서 지정한다. 필드를 감싼 쪽이 포커스를 쥐고 있어(커스텀 트리거·복합 컨트롤) 필드 자신은 `:focus-within` 이 걸리지 않을 때 쓴다. 켜면 강조 테두리·링이 error/pass 보다 우선한다. |
|
|
26
|
+
| `hovered?` | `boolean` | `false` | 호버 상태를 밖에서 지정한다. `focused` 와 같은 이유로 쓰며, 강조도 같다 — 실제 `:hover` 와 구분되지 않는 모양이어야 밖에서 흉내 낸 것이 티가 나지 않는다. |
|
|
27
27
|
| `rules?` | `Rule[]` | — | 유효성 규칙 (검증은 컨트롤에서 수행, API 패리티) |
|
|
28
28
|
| `hint?` | `string` | `''` | 하단 힌트 |
|
|
29
29
|
| `disabled?` | `boolean` | `false` | 비활성 |
|
|
@@ -45,9 +45,15 @@ export interface SFieldProps {
|
|
|
45
45
|
errorMessage?: string;
|
|
46
46
|
/** 필드 상태 — 'error' | 'pass' | 'default'. 'pass'면 초록 테두리 */
|
|
47
47
|
status?: SFieldStatus;
|
|
48
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* 포커스 상태를 밖에서 지정한다. 필드를 감싼 쪽이 포커스를 쥐고 있어(커스텀 트리거·복합 컨트롤)
|
|
50
|
+
* 필드 자신은 `:focus-within` 이 걸리지 않을 때 쓴다. 켜면 강조 테두리·링이 error/pass 보다 우선한다.
|
|
51
|
+
*/
|
|
49
52
|
focused?: boolean;
|
|
50
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* 호버 상태를 밖에서 지정한다. `focused` 와 같은 이유로 쓰며, 강조도 같다 —
|
|
55
|
+
* 실제 `:hover` 와 구분되지 않는 모양이어야 밖에서 흉내 낸 것이 티가 나지 않는다.
|
|
56
|
+
*/
|
|
51
57
|
hovered?: boolean;
|
|
52
58
|
/** 유효성 규칙 (검증은 컨트롤에서 수행, API 패리티) */
|
|
53
59
|
rules?: Rule[];
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
| `value?` | `SFilePickerValue` | `null` | |
|
|
12
12
|
| `placeholder?` | `string` | `'Click to upload'` | |
|
|
13
13
|
| `disabled?` | `boolean` | `false` | |
|
|
14
|
-
| `focused?` | `boolean` | `false` | 포커스
|
|
15
|
-
| `hovered?` | `boolean` | `false` | 호버
|
|
14
|
+
| `focused?` | `boolean` | `false` | 포커스 상태를 밖에서 지정한다 — 강조 테두리·링이 즉시 걸린다 (SField 로 그대로 넘어간다) |
|
|
15
|
+
| `hovered?` | `boolean` | `false` | 호버 상태를 밖에서 지정한다 — 강조는 `focused` 와 같다 (SField 로 그대로 넘어간다) |
|
|
16
16
|
| `inline?` | `boolean` | `false` | 인라인 표시 — SField 테두리 박스만 사라지고 label/rules/hint 는 그대로 동작 |
|
|
17
17
|
| `multiple?` | `boolean` | `false` | |
|
|
18
|
-
| `
|
|
18
|
+
| `showMultipleListBox?` | `boolean` | `false` | multiple 파일 목록을 필드 아래 칩 대신, caret(▼) 클릭 시 열리는 리스트박스 카드로 표시 (바깥 클릭 시 닫힘) |
|
|
19
19
|
| `accept?` | `string` | — | |
|
|
20
20
|
| `maxFileSize?` | `number \| string` | — | |
|
|
21
21
|
| `maxTotalSize?` | `number \| string` | — | |
|
|
@@ -18,15 +18,15 @@ export interface SFilePickerProps {
|
|
|
18
18
|
}) => void;
|
|
19
19
|
placeholder?: string;
|
|
20
20
|
disabled?: boolean;
|
|
21
|
-
/** 포커스
|
|
21
|
+
/** 포커스 상태를 밖에서 지정한다 — 강조 테두리·링이 즉시 걸린다 (SField 로 그대로 넘어간다) */
|
|
22
22
|
focused?: boolean;
|
|
23
|
-
/** 호버
|
|
23
|
+
/** 호버 상태를 밖에서 지정한다 — 강조는 `focused` 와 같다 (SField 로 그대로 넘어간다) */
|
|
24
24
|
hovered?: boolean;
|
|
25
25
|
/** 인라인 표시 — SField 테두리 박스만 사라지고 label/rules/hint 는 그대로 동작 */
|
|
26
26
|
inline?: boolean;
|
|
27
27
|
multiple?: boolean;
|
|
28
28
|
/** multiple 파일 목록을 필드 아래 칩 대신, caret(▼) 클릭 시 열리는 리스트박스 카드로 표시 (바깥 클릭 시 닫힘) */
|
|
29
|
-
|
|
29
|
+
showMultipleListBox?: boolean;
|
|
30
30
|
accept?: string;
|
|
31
31
|
maxFileSize?: number | string;
|
|
32
32
|
maxTotalSize?: number | string;
|
|
@@ -56,4 +56,4 @@ export interface SFilePickerProps {
|
|
|
56
56
|
style?: CSSProperties;
|
|
57
57
|
}
|
|
58
58
|
/** SFilePicker — sd-file-picker 포팅. 단일/다중 파일 + 크기·개수 검증 + 칩 목록. */
|
|
59
|
-
export declare function SFilePicker({ value, onValueChange, onReject, placeholder, disabled, focused, hovered, inline, multiple,
|
|
59
|
+
export declare function SFilePicker({ value, onValueChange, onReject, placeholder, disabled, focused, hovered, inline, multiple, showMultipleListBox, accept, maxFileSize, maxTotalSize, maxFiles, name, rules, status, size, label, labelWidth, icon, iconColor, labelTooltip, labelTooltipProps, addonLabel, addonAlign, hint, error, errorMessage, width, className, style, }: SFilePickerProps): import("react").JSX.Element;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
| Prop | Type | Default | Description |
|
|
10
10
|
|------|------|---------|-------------|
|
|
11
|
-
| `
|
|
11
|
+
| `formClassName?` | `string` | — | form 엘리먼트에 추가할 클래스 (sd-form formClassName 대응) |
|
|
12
12
|
| `children?` | `ReactNode` | — | |
|
|
13
13
|
| `className?` | `string` | — | |
|
|
14
14
|
| `style?` | `CSSProperties` | — | |
|
|
@@ -15,8 +15,8 @@ export interface SFormHandle {
|
|
|
15
15
|
focusFirstInvalid: () => void;
|
|
16
16
|
}
|
|
17
17
|
export interface SFormProps {
|
|
18
|
-
/** form 엘리먼트에 추가할 클래스 (sd-form
|
|
19
|
-
|
|
18
|
+
/** form 엘리먼트에 추가할 클래스 (sd-form formClassName 대응) */
|
|
19
|
+
formClassName?: string;
|
|
20
20
|
/** 모든 필드 검증 통과 후 발생 (sd-form sdSubmit 대응) */
|
|
21
21
|
onSubmit?: () => void;
|
|
22
22
|
/** 검증 실패 시 실패한 필드 name 목록 전달 (sd-form sdValidationError 대응) */
|
|
@@ -9,16 +9,16 @@
|
|
|
9
9
|
| Prop | Type | Default | Description |
|
|
10
10
|
|------|------|---------|-------------|
|
|
11
11
|
| `type?` | `SGnbType` | — | 메뉴 스타일: box(라운드) / belt(풀폭 행). 미지정 시 SLayout 의 type 을 따른다. |
|
|
12
|
-
| `header?` | `SGnbHeader` | — | 상단바 구조: fix(GNB 폭 고정) / full(레이아웃 전폭). 미지정 시 SLayout 의 header 를 따른다. 단,
|
|
12
|
+
| `header?` | `SGnbHeader` | — | 상단바 구조: fix(GNB 폭 고정) / full(레이아웃 전폭). 미지정 시 SLayout 의 header 를 따른다. 단, showRail 이고 레일에 children 없는 아이템이 있으면 메뉴 폭이 출렁이므로 full 로 강제된다. |
|
|
13
13
|
| `color?` | `SGnbColor` | `'light'` | 색상 테마: light / dark |
|
|
14
|
-
| `items` | `SGnbMenuItem[]` | — | 메뉴 트리 (depth1 → depth2 → depth3).
|
|
15
|
-
| `
|
|
14
|
+
| `items` | `SGnbMenuItem[]` | — | 메뉴 트리 (depth1 → depth2 → depth3). showRail 이면 첫 depth 가 레일이 되고 그 children 이 depth1 이 된다. |
|
|
15
|
+
| `showRail?` | `boolean` | — | 좌측 레일 사용 여부. 켜면 items 의 첫 depth 가 아이콘+라벨 버튼의 세로 레일로 서고, 선택된 레일 아이템의 children 이 오른쪽 메뉴 패널에 깔린다. 미지정 시 SLayout 의 showRail 을 따른다. children 없는 레일 아이템이 활성이면 메뉴 패널은 렌더되지 않고 레일만 남는다. |
|
|
16
16
|
| `value?` | `string` | `''` | 현재 선택된 아이템 value |
|
|
17
17
|
| `folded?` | `boolean` | — | 접힘(레일) 상태. 미지정 시 SLayout 의 folded 를 따른다. |
|
|
18
18
|
| `logo?` | `ReactNode` | — | 상단바 로고 영역 (slot). header="full" 이면 폭이 140px 로 고정된다. |
|
|
19
19
|
| `topContent?` | `ReactNode` | — | 상단바 로고 오른쪽 슬롯 (검색·액션 등). 로고와 16px 띄고 남는 폭을 모두 차지하므로 안에서 자유롭게 정렬한다. 상단바가 전폭인 header="full" 에서만 렌더된다 (fix 는 상단바가 좁은 GNB 컬럼 안이라 놓을 자리가 없다). |
|
|
20
|
-
| `railTop?` | `ReactNode` | — | 레일 상단 고정 슬롯. 레일 아이템이 많아 넘치면 아이템 목록(ul)만 스크롤되고 이 슬롯은 레일 상단(상단바 바로 아래)에 붙어 고정된다.
|
|
21
|
-
| `railFooter?` | `ReactNode` | — | 레일 하단 고정 슬롯. 레일 아이템이 많아 넘치면 아이템 목록(ul)만 스크롤되고 이 슬롯은 레일 하단에 붙어 고정된다.
|
|
20
|
+
| `railTop?` | `ReactNode` | — | 레일 상단 고정 슬롯. 레일 아이템이 많아 넘치면 아이템 목록(ul)만 스크롤되고 이 슬롯은 레일 상단(상단바 바로 아래)에 붙어 고정된다. showRail 일 때만 렌더된다. |
|
|
21
|
+
| `railFooter?` | `ReactNode` | — | 레일 하단 고정 슬롯. 레일 아이템이 많아 넘치면 아이템 목록(ul)만 스크롤되고 이 슬롯은 레일 하단에 붙어 고정된다. showRail 일 때만 렌더된다. |
|
|
22
22
|
| `menuTop?` | `ReactNode` | — | 메뉴 상단 고정 슬롯. 메뉴 아이템이 많아 넘치면 메뉴 목록(ul)만 스크롤되고 이 슬롯은 메뉴 상단에 붙어 고정된다. 메뉴가 렌더될 때만(showMenu) 나타난다. |
|
|
23
23
|
| `menuFooter?` | `ReactNode` | — | 메뉴 하단 고정 슬롯. 메뉴 아이템이 많아 넘치면 메뉴 목록(ul)만 스크롤되고 이 슬롯은 메뉴 하단에 붙어 고정된다. 메뉴가 렌더될 때만(showMenu) 나타난다. |
|
|
24
24
|
| `foldedTop?` | `ReactNode` | — | 접힘(fix 레일) 상단 고정 슬롯. 접으면 본문이 빠져나가며 rail/menu top 도 사라지므로, 48px 폴드 레일 상단(상단바 바로 아래)에 붙는 별도 슬롯이다. header="fix" 로 접혔을 때만 나타난다. |
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
| `resizable?` | `boolean` | `false` | 메뉴 폭을 드래그로 조절할 수 있게 한다. 레일 폭은 고정이고 **메뉴 컬럼만** 늘고 준다. 조절선은 GNB 컬럼의 오른쪽 경계 전체다 — fix 는 상단바 높이까지, full 은 상단바가 전폭이라 본문 높이까지. 접혀 있거나 깔 메뉴가 없으면(레일 리프가 활성) 조절선이 나오지 않는다. |
|
|
27
27
|
| `menuWidth?` | `number` | — | 메뉴 폭(px). 주면 controlled — onMenuWidthChange 로 직접 갱신해야 움직인다 |
|
|
28
28
|
| `defaultMenuWidth?` | `number` | — | 메뉴 초기 폭(px). uncontrolled |
|
|
29
|
-
| `system?` | `ReactNode` | — | system 슬롯(`SGnbSystem`). 놓이는 자리와 형태는 `header` 가 정한다. - fix : GNB 맨 아래 세로 판. 펼치면 메뉴 컬럼 바닥에, 접히면 `foldedFooter` 아래 레일 바닥에 여백 없이 붙는다.
|
|
29
|
+
| `system?` | `ReactNode` | — | system 슬롯(`SGnbSystem`). 놓이는 자리와 형태는 `header` 가 정한다. - fix : GNB 맨 아래 세로 판. 펼치면 메뉴 컬럼 바닥에, 접히면 `foldedFooter` 아래 레일 바닥에 여백 없이 붙는다. showRail 에서 메뉴가 없는 레일 아이템이 활성이면 메뉴 컬럼째 사라지므로 이 슬롯도 함께 빠진다. - full: 전폭 상단바 오른쪽 끝에 가로 한 줄로 선다. 상단바는 접어도 남으므로 조각들도 늘 남는다. 색·형태는 GNB 가 내려주므로 SGnbSystem 에 다시 넘기지 않아도 된다. |
|
|
30
30
|
| `ariaLabel?` | `string` | `'global navigation'` | 메뉴 landmark(nav) 의 접근성 레이블. 한 화면에 nav 가 여럿일 때 구분한다. |
|
|
31
31
|
|
|
32
32
|
#### Events
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
|-------|------|-------------|
|
|
36
36
|
| `onValueChange` | `(value: string) => void` | 선택 변경 (sdUpdate) |
|
|
37
37
|
| `onRailChange` | `(value: string) => void` | 레일 선택 변경. 레일 아이템을 눌러 패널이 바뀔 때 알린다(선택 상태는 SGnb 가 자체 관리). |
|
|
38
|
-
| `
|
|
38
|
+
| `onFoldedChange` | `(folded: boolean) => void` | 접힘 토글 (sdFoldChange) |
|
|
39
39
|
| `onLauncherClick` | `() => void` | 앱런처(그리드) 버튼 클릭. 미지정 시 런처 버튼을 렌더하지 않는다. 접힘 레일(fix)에는 폴드 버튼만 남으므로 표시되지 않는다. |
|
|
40
40
|
| `onMenuWidthChange` | `(width: number) => void` | 메뉴 폭이 확정될 때(드래그를 놓거나 방향키 조작). 드래그하는 동안에는 오지 않는다 |
|
|
41
41
|
|