sellmate-design-system-react 9.0.0-beta.35 → 9.0.0-beta.37
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 +46 -17
- package/dist/components/SCallout/README.md +2 -2
- package/dist/components/SCallout/SCallout.d.ts +9 -4
- package/dist/components/SLayout/README.md +5 -0
- package/dist/components/SLayout/SLayout.d.ts +4 -0
- package/dist/components/SLoadingContainer/loading.d.ts +18 -2
- package/dist/components/SPage/README.md +7 -3
- package/dist/components/SPage/SPage.d.ts +3 -9
- package/dist/components/SPage/SPageHeader.d.ts +18 -11
- package/dist/components/SPage/index.d.ts +1 -1
- package/dist/components/SPage/page-column.d.ts +25 -0
- package/dist/index.cjs +244 -173
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +244 -174
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +58 -22
- package/dist/llms.txt +46 -17
- package/dist/styles.css +41 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
| **입력 (폼)** | `SForm` `SField` `SInput` `SSearchInput` `SNumberInput` `STextarea` `SEditor` `SSelect` `SCheckbox` `SRadio` `SRadioGroup` `SRadioButton` `SRadioCard` `SRadioCardGroup` `SChip` `SChipInput` `SBarcodeInput` `SFilePicker` |
|
|
31
31
|
| **날짜·시간** | `SCalendar` `SCalendarBoard`(한 달치 일정 판) `SDatePicker` `SDatePickerYearListbox` `SDatePickerMonthListbox` `SDateRangePicker` `STimePicker` `STimeRangePicker` |
|
|
32
32
|
| **표·목록** | `STable` `STableBar` `SChipFilter` `SKeyValueTable` `SList` `SListItem` `SExpansionList` `SDraggableList` `SDraggableItem` `STree` |
|
|
33
|
-
| **레이아웃** | `SLayout` `SGnb` `SGnbSystem` `SAccountListBox`(계정 행을 눌러 뜨는 계정 패널) `SPage`(제목
|
|
33
|
+
| **레이아웃** | `SLayout` `SGnb` `SGnbSystem` `SAccountListBox`(계정 행을 눌러 뜨는 계정 패널) `SPage` `SPageHeader`(페이지 제목 영역 — `SLayout` 안에서 `SPage` 앞에 둔다) `SSectionHeaderCard` `SCard` `SDivider` `SSplitter` `SScrollArea` `SExpansionItem` |
|
|
34
34
|
| **내비게이션** | `STabs` `SPagination` `SStepper` |
|
|
35
35
|
| **표시·상태** | `STag` `SBadge` `SIcon` `SImage` `SCallout` `SGuide` |
|
|
36
36
|
| **진행·로딩** | `SLinearProgress` `SCircleProgress` `SLoadingContainer` `SLoadingModal` |
|
|
@@ -150,7 +150,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
150
150
|
|
|
151
151
|
| 층 | 무엇인가 | 컴포넌트 |
|
|
152
152
|
| --- | --- | --- |
|
|
153
|
-
| **셸** | 앱 전체 뼈대. 페이지가 바뀌어도 남는다 | `SLayout` `SGnb` `SGnbSystem`(GNB 맨 아래 판 · 전폭 상단바 오른쪽 끝) `SPage`(
|
|
153
|
+
| **셸** | 앱 전체 뼈대. 페이지가 바뀌어도 남는다 | `SLayout` `SGnb` `SGnbSystem`(GNB 맨 아래 판 · 전폭 상단바 오른쪽 끝) `SPage` `SPageHeader`(`SLayout` 안에서 `SPage` 앞에 둔다) |
|
|
154
154
|
| **블록** | `SPage` 의 직계 자식. 페이지를 세로로 쌓는 단위 | `SSectionHeaderCard` `SCard` `SForm` `SSplitter` `SScrollArea` `SCalendarBoard` `STable` `STableBar` `SChipFilter` `SKeyValueTable` `SList` `SExpansionList` `SDraggableList` `STree` `SCallout` `STabs` `SStepper` `SPagination` `SDivider` |
|
|
155
155
|
| **요소** | 블록 **안에** 놓이는 컨트롤. 혼자 페이지에 서지 않는다 | `SButton` `SGhostButton` `SDropdownButton` `SSystemActionButton` `SField` `SInput` `SSearchInput` `SNumberInput` `STextarea` `SEditor` `SSelect` `SCheckbox` `SRadio` `SRadioGroup` `SRadioButton` `SRadioCard` `SRadioCardGroup` `SSwitch` `SToggle` `SChipInput` `SBarcodeInput` `SFilePicker` `SDatePicker` `SDatePickerYearListbox` `SDatePickerMonthListbox` `SDateRangePicker` `STimePicker` `STimeRangePicker` `SCalendar` `SListItem` `SExpansionItem` `SDraggableItem` `SImage` `SLinearProgress` `SCircleProgress` |
|
|
156
156
|
| **인라인** | 텍스트 흐름·셀·라벨 안에 섞인다. 혼자 블록이 되지 않는다 | `STag` `SBadge` `SIcon` `STextLink` `SChip` |
|
|
@@ -200,7 +200,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
200
200
|
블록 순서는 화면 종류와 무관하게 같다. **필요한 것만 남기되 순서를 바꾸지 않는다.**
|
|
201
201
|
|
|
202
202
|
```text
|
|
203
|
-
1. 페이지 제목 `
|
|
203
|
+
1. 페이지 제목 `SPageHeader` (SGnb 와 SPage 사이. 가이드·매뉴얼 링크는 slot, 액션 버튼은 오지 않는다 §4-2)
|
|
204
204
|
2. 상시 안내 SCallout
|
|
205
205
|
3. 필터 SKeyValueTable · SChipFilter (§3-7-11)
|
|
206
206
|
4. 툴바 STableBar (건수 요약 + 액션)
|
|
@@ -228,7 +228,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
228
228
|
|
|
229
229
|
| 층 (§2-0) | 역할 | 클래스 | 크기 |
|
|
230
230
|
| --- | --- | --- | --- |
|
|
231
|
-
| 셸 | 페이지 제목 (`
|
|
231
|
+
| 셸 | 페이지 제목 (`SPageHeader` 의 `title`) | `typo-heading-lg` | 18px |
|
|
232
232
|
| 블록 | 섹션 제목 | `typo-heading-sm` | 14px |
|
|
233
233
|
| 블록 내부 | 하위 제목 (섹션 안을 더 나눌 때) | `typo-heading-xs` | 12px |
|
|
234
234
|
| — | 본문 | `typo-body-sm-default` | 12px |
|
|
@@ -236,7 +236,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
236
236
|
|
|
237
237
|
페이지 제목만 18px 로 크게 두고 그 아래는 14 / 12 로 촘촘하게 간다. 중간 크기(16px)는 기본 골격에서 쓰지 않는다.
|
|
238
238
|
|
|
239
|
-
- **페이지·섹션 제목의 타이포를 직접 주지 않는다.** `
|
|
239
|
+
- **페이지·섹션 제목의 타이포를 직접 주지 않는다.** `SPageHeader` 의 `title`, `SSectionHeaderCard` 의 `header.title` 이 이미 넣는다 — 그 위에 `typo-heading-lg`/`typo-heading-sm` 을 또 씌우지 않는다.
|
|
240
240
|
- **하위 제목이 필요하면 먼저 섹션을 나눌 수 없는지 본다.** 한 섹션 안에서 제목이 두 단으로 갈린다는 것은 대개 섹션이 둘이라는 뜻이다 (§3-7-8).
|
|
241
241
|
- 본문 안에서 한 단어를 강조할 때는 `typo-body-sm-medium` 을 쓴다. `typo-body-sm-bold` 는 제목 성격의 짧은 라벨에만 쓴다. <!-- TODO(디자인): 강조 굵기 기준 확정 -->
|
|
242
242
|
|
|
@@ -539,7 +539,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
539
539
|
| 앱 상단바 오른쪽 끝에 알림 벨·계정 이름을 둔다 | `SGnbSystem` (`SGnb` 의 `system` 슬롯 — 직접 만들지 않는다) | §4-1 |
|
|
540
540
|
| 계정 이름을 눌러 이메일·권한·계정 설정·언어 변경·로그아웃을 띄운다 | `SAccountListBox` (`SGnbSystem` 의 `account.listBox` 로 넘긴다 — 직접 띄우지 않는다) | §4-1 |
|
|
541
541
|
| 페이지 본문을 담는다 (패딩·스크롤) | `SPage` | §4-1 |
|
|
542
|
-
| 페이지 제목(+ 서브 텍스트·뒤로가기·우측 슬롯)을 만든다 | `
|
|
542
|
+
| 페이지 제목(+ 서브 텍스트·뒤로가기·우측 슬롯)을 만든다 | `SPageHeader` (`SLayout` 안에서 `SPage` 앞에 둔다) | §4-1 |
|
|
543
543
|
| 제목 있는 섹션으로 묶는다 | `SSectionHeaderCard` | §3-7-8 |
|
|
544
544
|
| 제목 없이 흰 면으로만 묶는다 | `SCard` | §3-7-8 |
|
|
545
545
|
| 가로선으로 끊는다 | `SDivider` | §3-6 |
|
|
@@ -615,6 +615,14 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
615
615
|
| 특정 UI 요소에 대한 **온보딩·기능 안내** | `SGuide` |
|
|
616
616
|
| 로딩 중 화면 잠금 | `SLoadingModal` / 영역 로딩은 `SLoadingContainer` |
|
|
617
617
|
|
|
618
|
+
**`SCallout` 의 `type` 은 놓이는 면이 정한다.** 안내의 강도가 아니라 배경 대비의 문제다.
|
|
619
|
+
|
|
620
|
+
| `type` | 언제 |
|
|
621
|
+
| --- | --- |
|
|
622
|
+
| `default` | 흰 면 위 (`SPage background="frame"`) — 옅은 회색 면이라 페이지와 구분된다 |
|
|
623
|
+
| `white` | 회색 면 위 (`background="neutral"`·`"screen"`) — 그 위에서는 `default` 가 배경에 묻힌다 |
|
|
624
|
+
| `danger` | 경고. 좌측에 "주의사항" 타이틀이 붙으므로 단순 안내에는 쓰지 않는다 |
|
|
625
|
+
|
|
618
626
|
### 3-3. 플로팅/오버레이류
|
|
619
627
|
|
|
620
628
|
| 상황 | 사용 |
|
|
@@ -1576,7 +1584,7 @@ const [selectedId, setSelectedId] = useState<string>();
|
|
|
1576
1584
|
### 4-1. 앱 셸 (모든 페이지 공통)
|
|
1577
1585
|
|
|
1578
1586
|
```tsx
|
|
1579
|
-
import { SLayout, SGnb, SPage, type SGnbMenuItem, type SPageHeaderProps } from 'sellmate-design-system-react';
|
|
1587
|
+
import { SLayout, SGnb, SPage, SPageHeader, type SGnbMenuItem, type SPageHeaderProps } from 'sellmate-design-system-react';
|
|
1580
1588
|
|
|
1581
1589
|
const MENU: SGnbMenuItem[] = [
|
|
1582
1590
|
{ label: '주문', value: 'orders', icon: 'bill' },
|
|
@@ -1598,16 +1606,13 @@ export default function AppShell({
|
|
|
1598
1606
|
<SLayout type="box" header="fix">
|
|
1599
1607
|
{/* type/header/folded 는 SLayout 에만 준다 — SGnb 는 context 에서 읽는다 */}
|
|
1600
1608
|
<SGnb items={MENU} value={current} onValueChange={navigate} logo={<Logo />} />
|
|
1609
|
+
{/* 페이지 제목은 SPage 앞에 형제로 둔다 — SLayout 이 헤더부터 뒤를 한 열로 묶는다.
|
|
1610
|
+
header 는 페이지마다 달라 AppShell 이 그대로 받아 넘긴다 — 여기서 만들지 않는다 */}
|
|
1611
|
+
{header && <SPageHeader {...header} />}
|
|
1601
1612
|
{/* 콘텐츠 패딩은 SPage 가 토큰으로 넣는다 — p-sd-* 로 덮어쓰지 않는다 */}
|
|
1602
1613
|
{/* 높이 모드는 페이지가 정한다 — 대부분 contentHeight="fill" 이다 (§2-2) */}
|
|
1603
1614
|
{/* 스크롤 끝 여백도 SPage 가 넣는다. 페이지가 실제로 스크롤되는 화면에서만 켠다 */}
|
|
1604
|
-
|
|
1605
|
-
<SPage
|
|
1606
|
-
background="frame"
|
|
1607
|
-
scrollEndSpacing={scrollEndSpacing}
|
|
1608
|
-
contentHeight={contentHeight}
|
|
1609
|
-
header={header}
|
|
1610
|
-
>
|
|
1615
|
+
<SPage background="frame" scrollEndSpacing={scrollEndSpacing} contentHeight={contentHeight}>
|
|
1611
1616
|
{children}
|
|
1612
1617
|
</SPage>
|
|
1613
1618
|
</SLayout>
|
|
@@ -1615,14 +1620,38 @@ export default function AppShell({
|
|
|
1615
1620
|
}
|
|
1616
1621
|
```
|
|
1617
1622
|
|
|
1618
|
-
**페이지는 `AppShell` 을 직접 호출하며 자기 `header` 를 넘긴다** —
|
|
1623
|
+
**페이지는 `AppShell` 을 직접 호출하며 자기 `header` 를 넘긴다** — 셸은 앱에 하나뿐이므로, 페이지 제목이 페이지마다 다르다는 사실은 이렇게 프레임 컴포넌트를 통해 흘려보낸다(§4-2·§4-3·§4-4 참고).
|
|
1624
|
+
|
|
1625
|
+
**자식 순서는 `SGnb` → `SPageHeader` → `SPage` 다.** `SLayout` 은 `SPageHeader` 자식을 보면 **그 자식부터 뒤를** 하나의 페이지 열로 묶어 헤더를 페이지 위에 고정한다 — 스크롤도 페이지 패딩도 그 아래 `SPage` 안에서만 일어난다. 그래서 순서가 규칙이다: 헤더를 `SGnb` 앞에 두면 GNB 까지 페이지 열로 딸려 들어가고, `SPage` 의 `children` 안에 넣으면 본문 패딩 안으로 들어가 스크롤과 함께 밀려 올라간다.
|
|
1626
|
+
|
|
1627
|
+
**`scrolled` 를 직접 주지 않는다.** plain 헤더의 그림자는 같은 열의 `SPage` 가 올린 스크롤 상태로 켜진다 — 손으로 준 값은 그 자동 동작을 덮어써 스크롤과 어긋난 그림자를 남긴다.
|
|
1619
1628
|
|
|
1620
|
-
**페이지 헤더
|
|
1629
|
+
**페이지 헤더 사용 규칙 — 이 앱에서는 값이 아니라 값의 일관성이 규칙이다.**
|
|
1621
1630
|
|
|
1622
|
-
- **`fix` 는 앱 전체에서 하나로 고정한다.** 어떤 페이지는 `fix
|
|
1631
|
+
- **`fix` 는 앱 전체에서 하나로 고정한다.** 어떤 페이지는 `fix`(높이 고정 바), 다른 페이지는 기본형으로 섞어 쓰지 않는다. 프로젝트에서 하나를 고르면(예: 전부 `fix`) 모든 페이지 헤더가 그 값을 쓴다.
|
|
1623
1632
|
- **`slot`·`onBack` 도 페이지 성격이 실제로 다른 경우가 아니면 있는 대로 통일한다.** "목록 페이지엔 없고 상세·등록 페이지엔 있다"처럼 화면 종류에 따라 갈리는 것은 허용되지만, 같은 종류의 화면끼리는 임의로 넣었다 뺐다 하지 않는다.
|
|
1624
1633
|
- **`slot` 은 `ReactNode` 를 그대로 받지만, 원칙은 `size="sm"` 버튼 위주로만 채운다.** `STextLink`·복잡한 커스텀 마크업을 슬롯에 넣지 않는다 — 그 이상이 필요하면 페이지 헤더가 아니라 §4-2 의 `STableBar` 처럼 본문 쪽 액션 자리를 쓴다.
|
|
1625
1634
|
|
|
1635
|
+
**셸 밖의 단독 화면(로그인·온보딩 등)에서도 같은 제목 영역을 쓸 수 있다.** 이때는 페이지 열이 없으므로 `scrolled` 가 앱 몫이 된다.
|
|
1636
|
+
|
|
1637
|
+
```tsx
|
|
1638
|
+
import { SPageHeader } from 'sellmate-design-system-react';
|
|
1639
|
+
|
|
1640
|
+
const [scrolled, setScrolled] = useState(false);
|
|
1641
|
+
|
|
1642
|
+
{/* 헤더는 자기 흰 면을 스스로 칠한다 — 감싸는 쪽은 본문이 놓일 면만 정하면 된다 */}
|
|
1643
|
+
<div className="flex h-full min-h-0 flex-col bg-[var(--sys-color-bg-frame)]">
|
|
1644
|
+
<SPageHeader title="상품 목록" subText="판매 중인 상품을 관리합니다." scrolled={scrolled} />
|
|
1645
|
+
{/* 스크롤을 앱이 쥐므로 scrolled 도 앱이 넣는다 — 패딩은 SPage 가 없으니 여기서 준다 */}
|
|
1646
|
+
<div
|
|
1647
|
+
className="min-h-0 flex-1 overflow-auto p-sd-16"
|
|
1648
|
+
onScroll={e => setScrolled(e.currentTarget.scrollTop > 0)}
|
|
1649
|
+
>
|
|
1650
|
+
…본문…
|
|
1651
|
+
</div>
|
|
1652
|
+
</div>;
|
|
1653
|
+
```
|
|
1654
|
+
|
|
1626
1655
|
**GNB 폭을 사용자가 조절하게 하려면 `SGnb` 에 `resizable` 을 준다.** 메뉴 오른쪽 경계가 조절선이 되고, 레일 폭은 고정된 채 메뉴 컬럼만 늘고 준다. 범위는 컴포넌트가 정하므로 숫자를 직접 주지 않는다.
|
|
1627
1656
|
|
|
1628
1657
|
```tsx
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
| Prop | Type | Default | Description |
|
|
10
10
|
|------|------|---------|-------------|
|
|
11
|
-
| `type?` | `SCalloutType` | `'default'` | 콜아웃 타입 (색상·아이콘·타이틀 결정) |
|
|
11
|
+
| `type?` | `SCalloutType` | `'default'` | 콜아웃 타입 (색상·아이콘·타이틀 결정). - `default` — 옅은 회색 면. 흰 페이지(`background="frame"`) 위의 기본 안내. - `white` — 같은 안내인데 배경만 흰 면. 회색 면(`neutral`·`screen`) 위에서 default 가 묻힐 때. - `danger` — 좌측에 주의사항 타이틀이 붙는 경고. |
|
|
12
12
|
| `message?` | `SCalloutMessage[]` | `[]` | 표시할 메시지 목록 (배열 중첩으로 depth 표현). 각 문자열은 인라인 HTML(`<b>`, `<a>` 등)을 허용하며 sanitizeInlineHtml 로 살균 후 렌더된다. |
|
|
13
13
|
| `children?` | `ReactNode` | — | message 대신 직접 본문을 넣을 때 |
|
|
14
14
|
| `className?` | `string` | — | |
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
### SCalloutType
|
|
20
20
|
|
|
21
21
|
```ts
|
|
22
|
-
export type SCalloutType = 'default' | 'danger';
|
|
22
|
+
export type SCalloutType = 'default' | 'danger' | 'white';
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
### SCalloutMessage
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
|
-
export type SCalloutType = 'default' | 'danger';
|
|
2
|
+
export type SCalloutType = 'default' | 'danger' | 'white';
|
|
3
3
|
/** 중첩 메시지: 문자열 또는 (한 단계 더 들어간) 문자열 배열 */
|
|
4
4
|
export type SCalloutMessage = string | SCalloutMessage[];
|
|
5
5
|
export interface SCalloutProps {
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* 콜아웃 타입 (색상·아이콘·타이틀 결정).
|
|
8
|
+
* - `default` — 옅은 회색 면. 흰 페이지(`background="frame"`) 위의 기본 안내.
|
|
9
|
+
* - `white` — 같은 안내인데 배경만 흰 면. 회색 면(`neutral`·`screen`) 위에서 default 가 묻힐 때.
|
|
10
|
+
* - `danger` — 좌측에 주의사항 타이틀이 붙는 경고.
|
|
11
|
+
*/
|
|
7
12
|
type?: SCalloutType;
|
|
8
13
|
/**
|
|
9
14
|
* 표시할 메시지 목록 (배열 중첩으로 depth 표현).
|
|
@@ -17,8 +22,8 @@ export interface SCalloutProps {
|
|
|
17
22
|
}
|
|
18
23
|
/**
|
|
19
24
|
* SCallout — sd-callout 포팅.
|
|
20
|
-
* default/danger 타입, 중첩 리스트(불릿은 span으로 렌더), danger는 좌측 타이틀 표시.
|
|
21
|
-
* 색상은 `--cmp-callout-*` 토큰
|
|
25
|
+
* default/white/danger 타입, 중첩 리스트(불릿은 span으로 렌더), danger는 좌측 타이틀 표시.
|
|
26
|
+
* 색상은 `--cmp-callout-*` 토큰 참조(white 만 예외 — SURFACE 주석 참고).
|
|
22
27
|
* message 각 항목은 sanitizeInlineHtml 로 살균한 뒤 innerHTML 로 렌더한다 (원본 sd-callout 과 동일).
|
|
23
28
|
*/
|
|
24
29
|
export declare const SCallout: import("react").ForwardRefExoticComponent<SCalloutProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -43,10 +43,15 @@ export type SLayoutHeader = SGnbHeader;
|
|
|
43
43
|
- [SGnb](../SGnb)
|
|
44
44
|
- [SPage](../SPage)
|
|
45
45
|
|
|
46
|
+
### Depends on
|
|
47
|
+
|
|
48
|
+
- [SPage](../SPage)
|
|
49
|
+
|
|
46
50
|
### Graph
|
|
47
51
|
|
|
48
52
|
```mermaid
|
|
49
53
|
graph TD;
|
|
54
|
+
SLayout --> SPage
|
|
50
55
|
SGnb --> SLayout
|
|
51
56
|
SPage --> SLayout
|
|
52
57
|
style SLayout fill:#f9f,stroke:#333,stroke-width:4px
|
|
@@ -106,5 +106,9 @@ export interface SLayoutProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
106
106
|
* "header header" ← 전폭 상단바 (1행, 높이 = 등록된 topHeight)
|
|
107
107
|
* "nav page" ← 메뉴 열(등록된 columnWidth) | 페이지
|
|
108
108
|
* 접으면 nav 열을 0 으로 접어 페이지가 전폭을 쓴다.
|
|
109
|
+
*
|
|
110
|
+
* 자식 순서는 `SGnb` → (선택) `SPageHeader` → `SPage` 다. `SPageHeader` 를 두면 **그 자식부터 뒤가**
|
|
111
|
+
* 하나의 페이지 열로 묶여(page-column.tsx) 헤더가 페이지 위에 고정되고, 그 아래에서만 스크롤이 일어난다.
|
|
112
|
+
* 헤더를 두지 않으면 아무것도 감싸지 않는다 — `SPage` 가 예전처럼 프레임의 자식으로 남는다.
|
|
109
113
|
*/
|
|
110
114
|
export declare const SLayout: import("react").ForwardRefExoticComponent<SLayoutProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
/** 오버레이 뷰포트 — 스토어를 구독해 SLoadingContainer 를 렌더한다. 직접 배치도 가능. */
|
|
2
2
|
export declare function SLoadingViewport(): import("react").JSX.Element;
|
|
3
3
|
export declare const loading: {
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* 로딩 오버레이 표시. 겹쳐 부르면 그만큼 쌓이고 **마지막 하나가 걷힐 때** 닫힌다.
|
|
6
|
+
* 반환값은 이 호출 하나만 걷는 함수다(두 번 불러도 한 번만 걷힌다) — `hide()` 대신 이것을
|
|
7
|
+
* 쓰면 짝이 어긋나지 않는다.
|
|
8
|
+
*
|
|
9
|
+
* ⚠️ 메시지만 바꾸려면 `update()` 를 쓴다. `show()` 를 다시 부르면 하나 더 쌓여
|
|
10
|
+
* `hide()` 한 번으로는 닫히지 않는다.
|
|
11
|
+
*/
|
|
5
12
|
show(options?: {
|
|
6
13
|
message?: string;
|
|
14
|
+
}): () => void;
|
|
15
|
+
/** 표시 중인 메시지 갱신 — 쌓인 수는 그대로다 */
|
|
16
|
+
update(options: {
|
|
17
|
+
message?: string;
|
|
7
18
|
}): void;
|
|
8
|
-
/**
|
|
19
|
+
/** 가장 나중의 show 하나를 걷는다. 남은 것이 없을 때만 오버레이가 닫힌다 */
|
|
9
20
|
hide(): void;
|
|
21
|
+
/**
|
|
22
|
+
* 쌓인 것을 모두 걷고 즉시 닫는다. 화면 전환·에러 복구처럼 진행 중이던 작업의 짝을 더는
|
|
23
|
+
* 맞출 수 없을 때만 쓴다 — 평소에는 `hide()` 나 `show()` 가 준 함수로 하나씩 걷는다.
|
|
24
|
+
*/
|
|
25
|
+
hideAll(): void;
|
|
10
26
|
};
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
|------|------|---------|-------------|
|
|
11
11
|
| `title` | `string` | — | 타이틀 (필수) |
|
|
12
12
|
| `subText?` | `string` | — | 서브 텍스트. fix=true 면 타이틀 오른쪽에, fix=false(기본) 면 타이틀 아래에 놓인다. |
|
|
13
|
-
| `fix?` | `boolean` | `false` | true: 높이 56 고정 +
|
|
13
|
+
| `fix?` | `boolean` | `false` | true: 높이 56 고정 + 하단 구분선, 서브 텍스트가 타이틀과 같은 줄. false(기본): 최소 높이 66(상하 패딩 20/16 안에서 타이틀 한 줄 높이로 결정) + 구분선 없음, 서브 텍스트가 타이틀 아래로 내려간다. 배경은 두 베리에이션 모두 흰 면이다. |
|
|
14
14
|
| `slot?` | `ReactNode` | — | 오른쪽 끝 커스텀 슬롯. 가이드 링크·액션 버튼 등 페이지마다 다른 것이 온다. |
|
|
15
|
-
| `scrolled?` | `boolean` |
|
|
15
|
+
| `scrolled?` | `boolean` | — | 아래 콘텐츠가 스크롤을 시작했는지. fix=false 일 때만 의미가 있다: 스크롤이 시작되면 그림자(floating)가 들어가 스크롤되는 콘텐츠 위에 뜬 것처럼 보인다. 배경은 흰 면 그대로다 — scrolled 가 더하는 것은 그림자뿐이다. `SLayout` 안에 놓았으면 **주지 않는다** — 같은 열의 `SPage` 가 자기 스크롤 상태를 올려 자동으로 들어온다. 스크롤 컨테이너를 앱이 직접 쥔 단독 배치에서만 `onScroll` 에서 준다. |
|
|
16
16
|
|
|
17
17
|
#### Events
|
|
18
18
|
|
|
@@ -30,7 +30,6 @@
|
|
|
30
30
|
| `scrollEndSpacing?` | `boolean` | `false` | 스크롤 끝 여백. 마지막 항목이 창 하단에 붙어 "여기서 끝"이 안 읽히는 것을 막는다. **기본은 꺼져 있다.** 페이지 스크롤 자체가 예외이기 때문이다 — 대부분의 화면은 본문이 창을 꽉 채우고 스크롤은 각 영역 안에서 일어난다. 여백을 조건 없이 붙이면 내용이 화면에 거의 딱 맞는 페이지까지 그 여백 때문에 스크롤되게 만든다. 페이지가 실제로 스크롤되는 화면(`contentHeight="auto"` + 내용이 창보다 김)에서만 켠다. 페이지네이션처럼 끝을 알려주는 것이 이미 있으면 켜지 않는다. |
|
|
31
31
|
| `overlayScrollbar?` | `boolean` | `false` | true면 네이티브 스크롤바를 숨기고 SPage 위에 오버레이 스크롤바를 얹는다. 스크롤바가 레이아웃 폭을 차지하지 않아 내부 콘텐츠 폭이 줄어들지 않는다. |
|
|
32
32
|
| `contentHeight?` | `SPageContentHeight` | `'auto'` | 본문 높이 모드. 기본은 `auto` — 콘텐츠가 흐르고 넘치면 페이지가 스크롤한다. `fill` 은 본문이 남은 높이를 정확히 채우고 페이지는 스크롤하지 않는다. 표가 자기 안에서 스크롤하고 페이지네이션이 하단에 고정되는 목록 화면용이다. 본문 루트에 `h-full` 이 먹으므로 `<div className="flex h-full min-h-0 flex-col">` + `<STable className="min-h-0 flex-1" />` 구성이 성립한다. `fill` 에서는 페이지가 스크롤하지 않으므로 `scrollEndSpacing` 이 무시된다. |
|
|
33
|
-
| `header?` | `SPageHeaderProps` | — | 페이지 타이틀 영역(pageHeader 포팅). 주면 스크롤·페이지 패딩 밖으로 빼내 상단에 고정 배치한다. `children` 은 항상 본문이다 — header 유무와 무관하게 같은 자리에 같은 뜻으로 들어간다. |
|
|
34
33
|
|
|
35
34
|
## Types
|
|
36
35
|
|
|
@@ -72,6 +71,10 @@ export const PAGE_CONTENT_HEIGHTS = ['auto', 'fill'] as const;
|
|
|
72
71
|
|
|
73
72
|
## Dependencies
|
|
74
73
|
|
|
74
|
+
### Used by
|
|
75
|
+
|
|
76
|
+
- [SLayout](../SLayout)
|
|
77
|
+
|
|
75
78
|
### Depends on
|
|
76
79
|
|
|
77
80
|
- [SGhostButton](../SGhostButton)
|
|
@@ -83,5 +86,6 @@ export const PAGE_CONTENT_HEIGHTS = ['auto', 'fill'] as const;
|
|
|
83
86
|
graph TD;
|
|
84
87
|
SPage --> SGhostButton
|
|
85
88
|
SPage --> SLayout
|
|
89
|
+
SLayout --> SPage
|
|
86
90
|
style SPage fill:#f9f,stroke:#333,stroke-width:4px
|
|
87
91
|
```
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type HTMLAttributes } from 'react';
|
|
2
2
|
import type { SPageBackground, SPageContentHeight } from './page.config';
|
|
3
|
-
import { type SPageHeaderProps } from './SPageHeader';
|
|
4
3
|
export interface SPageProps extends HTMLAttributes<HTMLElement> {
|
|
5
4
|
/**
|
|
6
5
|
* 페이지 배경 표면. frame=흰 콘텐츠 면, neutral=옅은 회색 면, screen=앱 바탕.
|
|
@@ -34,11 +33,6 @@ export interface SPageProps extends HTMLAttributes<HTMLElement> {
|
|
|
34
33
|
* `fill` 에서는 페이지가 스크롤하지 않으므로 `scrollEndSpacing` 이 무시된다.
|
|
35
34
|
*/
|
|
36
35
|
contentHeight?: SPageContentHeight;
|
|
37
|
-
/**
|
|
38
|
-
* 페이지 타이틀 영역(pageHeader 포팅). 주면 스크롤·페이지 패딩 밖으로 빼내 상단에 고정 배치한다.
|
|
39
|
-
* `children` 은 항상 본문이다 — header 유무와 무관하게 같은 자리에 같은 뜻으로 들어간다.
|
|
40
|
-
*/
|
|
41
|
-
header?: SPageHeaderProps;
|
|
42
36
|
}
|
|
43
37
|
/**
|
|
44
38
|
* SPage — SLayout 안에서 남은 공간을 채우는 스크롤 콘텐츠 영역.
|
|
@@ -50,8 +44,8 @@ export interface SPageProps extends HTMLAttributes<HTMLElement> {
|
|
|
50
44
|
* - header="full": SLayout 이 깐 grid 의 "page" 영역 = 상단바 아래·메뉴 오른쪽 자리를 차지한다.
|
|
51
45
|
* 좌표가 아니라 이름으로 잡으므로 프레임의 열·행 구성이 바뀌어도 여기는 그대로다.
|
|
52
46
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
47
|
+
* **페이지 제목은 `SLayout` 안에서 앞에 놓은 `SPageHeader` 가 만든다.** 그때 SLayout 이 헤더와
|
|
48
|
+
* 이 페이지를 한 열로 묶으므로(page-column.tsx) 여기서는 자리를 잡지 않고, 대신 자기 스크롤
|
|
49
|
+
* 상태를 그 열에 올린다 — 헤더가 그 값으로 floating 그림자를 켠다.
|
|
56
50
|
*/
|
|
57
51
|
export declare const SPage: import("react").ForwardRefExoticComponent<SPageProps & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -5,9 +5,9 @@ export interface SPageHeaderProps extends Omit<HTMLAttributes<HTMLElement>, 'slo
|
|
|
5
5
|
/** 서브 텍스트. fix=true 면 타이틀 오른쪽에, fix=false(기본) 면 타이틀 아래에 놓인다. */
|
|
6
6
|
subText?: string;
|
|
7
7
|
/**
|
|
8
|
-
* true: 높이 56 고정 +
|
|
9
|
-
* false(기본): 최소 높이 66(상하 패딩 20/16 안에서 타이틀 한 줄 높이로 결정) +
|
|
10
|
-
* 서브 텍스트가 타이틀 아래로 내려간다.
|
|
8
|
+
* true: 높이 56 고정 + 하단 구분선, 서브 텍스트가 타이틀과 같은 줄.
|
|
9
|
+
* false(기본): 최소 높이 66(상하 패딩 20/16 안에서 타이틀 한 줄 높이로 결정) + 구분선 없음,
|
|
10
|
+
* 서브 텍스트가 타이틀 아래로 내려간다. 배경은 두 베리에이션 모두 흰 면이다.
|
|
11
11
|
*/
|
|
12
12
|
fix?: boolean;
|
|
13
13
|
/** 뒤로가기 클릭 핸들러. 지정하면 왼쪽에 뒤로가기 버튼이 나타난다. */
|
|
@@ -15,18 +15,25 @@ export interface SPageHeaderProps extends Omit<HTMLAttributes<HTMLElement>, 'slo
|
|
|
15
15
|
/** 오른쪽 끝 커스텀 슬롯. 가이드 링크·액션 버튼 등 페이지마다 다른 것이 온다. */
|
|
16
16
|
slot?: ReactNode;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
18
|
+
* 아래 콘텐츠가 스크롤을 시작했는지. fix=false 일 때만 의미가 있다: 스크롤이 시작되면
|
|
19
|
+
* 그림자(floating)가 들어가 스크롤되는 콘텐츠 위에 뜬 것처럼 보인다. 배경은 흰 면 그대로다 —
|
|
20
|
+
* scrolled 가 더하는 것은 그림자뿐이다.
|
|
21
|
+
*
|
|
22
|
+
* `SLayout` 안에 놓았으면 **주지 않는다** — 같은 열의 `SPage` 가 자기 스크롤 상태를 올려
|
|
23
|
+
* 자동으로 들어온다. 스크롤 컨테이너를 앱이 직접 쥔 단독 배치에서만 `onScroll` 에서 준다.
|
|
23
24
|
*/
|
|
24
25
|
scrolled?: boolean;
|
|
25
26
|
}
|
|
26
27
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* fix 로 bar(높이 고정·흰 배경) / plain(투명·최소 높이) 두 베리에이션을 고른다.
|
|
28
|
+
* 페이지 타이틀 영역(pageHeader 포팅).
|
|
29
|
+
* fix 로 bar(높이 고정·하단 구분선) / plain(최소 높이) 두 베리에이션을 고른다 — 배경은 둘 다 흰 면이다.
|
|
30
30
|
* 뒤로가기 버튼은 onBack 유무로 나타나며, 없을 때는 타이틀 쪽에 4px 여백이 대신 들어간다.
|
|
31
|
+
*
|
|
32
|
+
* **셸 안에서는 `SLayout` 의 자식으로 `SGnb` 와 `SPage` 사이에 놓는다.** SLayout 이 이 헤더부터
|
|
33
|
+
* 뒤를 하나의 페이지 열로 묶어(page-column.tsx) 스크롤·페이지 패딩 밖 상단에 고정하고,
|
|
34
|
+
* plain 일 때 `SPage` 가 올린 스크롤 상태를 열이 대신 물려준다.
|
|
35
|
+
*
|
|
36
|
+
* 셸 밖에 직접 놓을 수도 있다 — 스크롤 컨테이너를 앱이 쥐고 있는 단독 화면이다. 그때는 그림자만
|
|
37
|
+
* 앱 몫이 된다: 스크롤 컨테이너의 `onScroll` 에서 `scrolled` 를 넣어야 뜬다.
|
|
31
38
|
*/
|
|
32
39
|
export declare const SPageHeader: import("react").ForwardRefExoticComponent<SPageHeaderProps & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { SPage, type SPageProps } from './SPage';
|
|
2
2
|
export { PAGE_BACKGROUNDS, type SPageBackground, PAGE_CONTENT_HEIGHTS, type SPageContentHeight, } from './page.config';
|
|
3
|
-
export { type SPageHeaderProps } from './SPageHeader';
|
|
3
|
+
export { SPageHeader, type SPageHeaderProps } from './SPageHeader';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* 페이지 열이 `SPageHeader` 와 `SPage` 사이에서 중개하는 것.
|
|
4
|
+
*
|
|
5
|
+
* 둘은 형제라 서로를 볼 수 없는데, 헤더의 그림자는 페이지의 스크롤에서 나온다.
|
|
6
|
+
* 열이 그 사이에 서서 값을 옮긴다 — 아래(SPage)가 올리고 위(SPageHeader)가 읽는다.
|
|
7
|
+
*/
|
|
8
|
+
export interface SPageColumnValue {
|
|
9
|
+
/** 페이지가 스크롤을 시작했는지. `SPage` 가 올리고 `SPageHeader` 가 그림자로 쓴다. */
|
|
10
|
+
scrolled: boolean;
|
|
11
|
+
/** `SPage` 가 자기 스크롤 상태를 올린다. */
|
|
12
|
+
setScrolled: (scrolled: boolean) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare const SPageColumnContext: import("react").Context<SPageColumnValue | null>;
|
|
15
|
+
/**
|
|
16
|
+
* 페이지 열 — `SLayout` 이 `SPageHeader` 자식을 보면 그 자식부터 뒤를 이 열로 묶는다.
|
|
17
|
+
* 헤더는 위에 고정되고(자기 shrink-0) 그 아래 `SPage` 가 남은 높이를 먹는다.
|
|
18
|
+
*
|
|
19
|
+
* 자리(그리드 area)는 프레임이 정한다. 열 자체는 배경을 칠하지 않는다 — 헤더도 `SPage` 도
|
|
20
|
+
* 자기 면을 스스로 칠하므로 열의 배경은 어디에서도 드러나지 않는다.
|
|
21
|
+
*/
|
|
22
|
+
export declare function SPageColumn({ full, children }: {
|
|
23
|
+
full: boolean;
|
|
24
|
+
children: ReactNode;
|
|
25
|
+
}): import("react").JSX.Element;
|