sellmate-design-system-react 9.0.0-beta.62 → 9.0.0-beta.64

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.
Files changed (34) hide show
  1. package/AGENTS.md +486 -131
  2. package/dist/components/SCalendarBoard/CalendarDayCard.d.ts +11 -3
  3. package/dist/components/SCalendarBoard/CalendarEventButton.d.ts +7 -2
  4. package/dist/components/SCalendarBoard/CalendarMoreButton.d.ts +2 -1
  5. package/dist/components/SCalendarBoard/README.md +11 -2
  6. package/dist/components/SCalendarBoard/SCalendarBoard.d.ts +4 -1
  7. package/dist/components/SCalendarBoard/calendar-board-layout.d.ts +49 -0
  8. package/dist/components/SCalendarBoard/types.d.ts +10 -1
  9. package/dist/components/SPage/README.md +19 -0
  10. package/dist/components/SPage/SPage.d.ts +11 -2
  11. package/dist/components/SPage/index.d.ts +1 -1
  12. package/dist/components/SPage/page.config.d.ts +8 -0
  13. package/dist/docs/RecipeGallery.d.ts +13 -0
  14. package/dist/index.cjs +168 -56
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.js +168 -57
  17. package/dist/index.js.map +1 -1
  18. package/dist/llms-full.txt +516 -133
  19. package/dist/llms.txt +486 -131
  20. package/dist/recipes/AppShell.d.ts +21 -0
  21. package/dist/recipes/ExcelFilePopupPage.d.ts +5 -0
  22. package/dist/recipes/LoginPage.d.ts +6 -0
  23. package/dist/recipes/ProductCreatePage.d.ts +1 -0
  24. package/dist/recipes/ProductCreateSectionsPage.d.ts +5 -0
  25. package/dist/recipes/ProductDetailInlineEditPage.d.ts +9 -0
  26. package/dist/recipes/ProductDetailPage.d.ts +1 -0
  27. package/dist/recipes/ProductListChipFilterPage.d.ts +1 -0
  28. package/dist/recipes/ProductListPage.d.ts +1 -0
  29. package/dist/recipes/TransferOrderPopupPage.d.ts +2 -0
  30. package/dist/recipes/api.d.ts +91 -0
  31. package/dist/recipes/recipe-story.d.ts +33 -0
  32. package/dist/recipes/router.d.ts +9 -0
  33. package/dist/styles.css +26 -3
  34. package/package.json +3 -1
@@ -1,9 +1,10 @@
1
1
  import { type HTMLAttributes, type MouseEvent, type ReactNode } from 'react';
2
+ import type { CalendarBoardSegment } from './calendar-board-layout';
2
3
  import { type SCalendarBoardDayColor } from './calendarBoard.config';
3
4
  import type { SCalendarBoardEvent } from './types';
4
5
  /**
5
6
  * 달력의 날짜 한 칸 (SCalendarBoard 내부 조립 요소).
6
- * 위에 날짜 숫자, 아래에 일정 목록과 "N개 더보기" 가 쌓인다.
7
+ * 위에 날짜 숫자가 서고, 그 아래로 일정 막대가 줄 단위로 얹힌다.
7
8
  * `body` 를 받은 칸은 아래를 통째로 그것에 내준다 — 일정은 그리지 않는다.
8
9
  */
9
10
  export declare const CalendarDayCard: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & {
@@ -19,8 +20,13 @@ export declare const CalendarDayCard: import("react").ForwardRefExoticComponent<
19
20
  selectable: boolean;
20
21
  /** 칸 배경 */
21
22
  color: SCalendarBoardDayColor;
22
- /** 이 칸에 펼쳐 그릴 일정 */
23
- events: SCalendarBoardEvent[];
23
+ /**
24
+ * **이 칸에서 시작하는** 일정 막대. 여러 날에 걸친 일정은 시작 칸이 그리고 오른쪽 칸 위로 뻗는다 —
25
+ * 지나가는 칸은 자기 줄을 비워 두므로(배치 계산이 이미 잡아 둔다) 겹치지 않는다.
26
+ */
27
+ segments: CalendarBoardSegment[];
28
+ /** 이 날짜에 걸친 일정 수 — 하나라도 있으면 칸을 눌러 목록 판을 열 수 있다 */
29
+ dayEventCount: number;
24
30
  /**
25
31
  * 일정 자리를 대신 차지할 칸 본문 (SCalendarBoard 의 `dayContent`).
26
32
  * 주면 일정·"더보기" 를 그리지 않는다. `content` 는 HTMLAttributes 가 이미 쓰는 이름이라 피했다.
@@ -28,6 +34,8 @@ export declare const CalendarDayCard: import("react").ForwardRefExoticComponent<
28
34
  body?: ReactNode;
29
35
  /** 접혀 있는 일정 수. 0 이면 "더보기" 를 그리지 않는다 */
30
36
  hiddenCount: number;
37
+ /** "더보기" 가 앉는 줄. 접힌 것이 없는 주는 -1 */
38
+ moreLane: number;
31
39
  /** 이 칸의 일정 목록 판이 열려 있는지 */
32
40
  isOpen: boolean;
33
41
  moreLabel?: string;
@@ -1,4 +1,4 @@
1
- import { type MouseEvent } from 'react';
1
+ import { type CSSProperties, type MouseEvent } from 'react';
2
2
  import type { SCalendarBoardEvent } from './types';
3
3
  /**
4
4
  * 달력 칸/패널 안의 일정 한 줄 (SCalendarBoard 내부 조립 요소).
@@ -6,8 +6,13 @@ import type { SCalendarBoardEvent } from './types';
6
6
  * 점 → 레이블(강조) → 설명 → `/` → 값 순서로 한 줄에 눕는다.
7
7
  * 가운데 레이블 묶음만 줄어들고 값은 끝에 고정되므로, 좁은 칸에서도 금액이 잘리지 않는다.
8
8
  */
9
- export declare function CalendarEventButton({ event, onSelect, className, }: {
9
+ export declare function CalendarEventButton({ event, onSelect, flatStart, flatEnd, className, style, }: {
10
10
  event: SCalendarBoardEvent;
11
11
  onSelect?: (event: SCalendarBoardEvent, e: MouseEvent<HTMLButtonElement>) => void;
12
+ /** 왼쪽 끝이 잘린 조각 — 앞 주에서 이어지므로 모서리를 평평하게 한다 */
13
+ flatStart?: boolean;
14
+ /** 오른쪽 끝이 잘린 조각 — 다음 주로 이어진다 */
15
+ flatEnd?: boolean;
12
16
  className?: string;
17
+ style?: CSSProperties;
13
18
  }): import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- import { type MouseEvent } from 'react';
1
+ import { type CSSProperties, type MouseEvent } from 'react';
2
2
  /**
3
3
  * 칸에 다 담기지 않은 일정 수를 알리는 "N개 더보기" 줄 (SCalendarBoard 내부 조립 요소).
4
4
  * 개수는 강조색, 뒷말은 본문색으로 갈라 개수가 먼저 읽히게 한다.
@@ -9,4 +9,5 @@ export declare const CalendarMoreButton: import("react").ForwardRefExoticCompone
9
9
  label?: string;
10
10
  onClick?: (e: MouseEvent<HTMLButtonElement>) => void;
11
11
  className?: string;
12
+ style?: CSSProperties;
12
13
  } & import("react").RefAttributes<HTMLButtonElement>>;
@@ -14,7 +14,7 @@
14
14
  | `defaultMonth?` | `number` | — | 처음 보여줄 월 1-12 (비제어). 없으면 오늘 |
15
15
  | `selectable?` | `boolean` | `false` | 날짜 칸을 눌러 고를 수 있게 한다. 기본은 읽기 전용 판이다 — 켜야 칸에 커서·포커스·키보드(Enter·Space)가 붙고 `onValueChange` 가 온다. 일정 버튼과 "N개 더보기" 는 이 값과 무관하게 항상 눌린다. |
16
16
  | `value?` | `string \| null` | — | 선택 날짜 (YYYY-MM-DD). `selectable` 과 별개로 강조만 주고 싶을 때도 쓴다 |
17
- | `events?` | `SCalendarBoardEvent[]` | — | 날짜별 일정 목록. `date` 로 칸에 배분된다 |
17
+ | `events?` | `SCalendarBoardEvent[]` | — | 일정 목록. `date`(시작)로 칸에 배분되고, `endDate` 를 주면 그날까지 **하나의 막대로 이어져** 칸 경계를 넘어 그려진다. |
18
18
  | `dayColors?` | `Record<string, SCalendarBoardDayColor>` | — | 날짜별 칸 배경. 키는 `YYYY-MM-DD`, 없는 날짜는 `'default'` 다. 그날의 성격(마감·완료·휴무 등)을 칸 전체로 알릴 때 쓴다 — 일정 하나의 색은 `events[].color` 다. |
19
19
  | `dayContent?` | `Record<string, ReactNode>` | — | 날짜별 칸 본문. 키는 `YYYY-MM-DD`, 준 날짜는 **일정 자리를 통째로 이 내용이 차지한다** — 그날의 `events` 는 그리지 않고 목록 판도 열리지 않는다. 일정으로 표현되지 않는 것(재고 현황· 매출 요약 같은 그날치 요약)을 칸에 그대로 얹을 때 쓴다. |
20
20
  | `todayLabel?` | `string` | `'오늘'` | 헤더 오른쪽 "오늘" 버튼 레이블. 빈 문자열이면 버튼을 그리지 않는다 |
@@ -52,8 +52,17 @@ export interface SCalendarBoardView {
52
52
  export interface SCalendarBoardEvent {
53
53
  /** 고유 식별자. 없으면 목록 순서로 key 를 만든다 */
54
54
  id?: string;
55
- /** 날짜 (YYYY-MM-DD) */
55
+ /** 시작 날짜 (YYYY-MM-DD). 하루짜리 일정은 이것만 준다 */
56
56
  date: string;
57
+ /**
58
+ * 마지막 날 (YYYY-MM-DD, **그날 포함**). 주지 않거나 `date` 보다 앞서면 하루짜리로 본다.
59
+ *
60
+ * 여러 날에 걸친 일정은 칸 경계를 넘어 **하나의 막대로 이어져** 그려진다. 주 경계에서는 줄이
61
+ * 바뀌므로 조각이 나뉘고, 그렇게 잘린 쪽 모서리는 평평해져 "앞/뒤로 이어진다" 가 읽힌다.
62
+ *
63
+ * 막대가 걸친 날은 **모두** 그 일정을 가진 날로 친다 — 목록 판과 `onValueChange` 에 함께 온다.
64
+ */
65
+ endDate?: string;
57
66
  /**
58
67
  * 강조 레이블 (필수) — 예: `"[입고 예정]"`.
59
68
  * 일정이 무엇인지 한눈에 알리는 부분이라 비워 두지 않는다.
@@ -22,7 +22,10 @@ export interface SCalendarBoardProps {
22
22
  value?: string | null;
23
23
  /** 날짜 칸 선택 — 고른 날짜와 그 날짜의 일정이 함께 온다 (`selectable` 일 때만) */
24
24
  onValueChange?: (date: string, events: SCalendarBoardEvent[]) => void;
25
- /** 날짜별 일정 목록. `date` 로 칸에 배분된다 */
25
+ /**
26
+ * 일정 목록. `date`(시작)로 칸에 배분되고, `endDate` 를 주면 그날까지 **하나의 막대로 이어져**
27
+ * 칸 경계를 넘어 그려진다.
28
+ */
26
29
  events?: SCalendarBoardEvent[];
27
30
  /**
28
31
  * 날짜별 칸 배경. 키는 `YYYY-MM-DD`, 없는 날짜는 `'default'` 다.
@@ -0,0 +1,49 @@
1
+ /**
2
+ * 달력 판의 **일정 배치**를 계산한다 (순수 함수 — DOM 을 보지 않는다).
3
+ *
4
+ * 왜 필요한가: 일정이 하루짜리뿐이면 칸마다 자기 목록을 세로로 쌓으면 그만이다. 그런데 여러 날에
5
+ * 걸친 일정은 **칸 경계를 넘어 하나의 막대로 이어져야** 하므로, 칸 혼자서는 자기 줄을 정할 수 없다 —
6
+ * 같은 주의 다른 칸에 걸친 막대가 이미 그 줄을 쓰고 있을 수 있기 때문이다. 그래서 줄(lane) 배정은
7
+ * **주 단위**로 한 번에 푼다.
8
+ *
9
+ * 하루짜리 일정만 있는 판은 이 계산을 거쳐도 예전과 같은 화면이 된다 — 서로 다른 날의 일정은
10
+ * 겹치지 않아 전부 0번 줄부터 차곡차곡 앉기 때문이다.
11
+ */
12
+ import type { DayCell } from '../../lib/date';
13
+ import type { SCalendarBoardEvent } from './types';
14
+ /** 한 주 안에서 이어지는 막대 하나 — 일정 하나가 주 경계에서 잘리면 조각이 여럿 된다 */
15
+ export interface CalendarBoardSegment {
16
+ event: SCalendarBoardEvent;
17
+ /** React key */
18
+ key: string;
19
+ /** 격자 칸 배열에서의 시작 인덱스 */
20
+ startIndex: number;
21
+ /** 이어지는 칸 수 (1 이상) */
22
+ span: number;
23
+ /** 그 주 안에서 몇 번째 줄인지 (0부터) */
24
+ lane: number;
25
+ /** 왼쪽 끝이 일정의 **실제 시작**인지. 아니면 앞에서 이어진 것이라 그 모서리를 평평하게 한다 */
26
+ startsHere: boolean;
27
+ /** 오른쪽 끝이 일정의 **실제 끝**인지 */
28
+ endsHere: boolean;
29
+ }
30
+ export interface CalendarBoardLayout {
31
+ /** 칸별로, **그 칸에서 시작하는** 막대. 막대는 시작 칸이 그린다 */
32
+ segmentsByCell: CalendarBoardSegment[][];
33
+ /** 칸별로, 그 날짜에 걸친 일정 전부 — 목록 판과 콜백에 넘기는 값 */
34
+ eventsByCell: SCalendarBoardEvent[][];
35
+ /** 칸별로 줄 수를 넘겨 접힌 일정 수 */
36
+ hiddenCountByCell: number[];
37
+ /** 주별로 "N개 더보기" 가 앉는 줄. 접힌 것이 없는 주는 -1 */
38
+ moreLaneByWeek: number[];
39
+ }
40
+ /** 일정의 마지막 날. `endDate` 가 없거나 시작보다 앞서면 하루짜리로 본다 */
41
+ export declare function eventEndDate(event: SCalendarBoardEvent): string;
42
+ export declare function layoutCalendarBoard({ cells, events, rowCapacity, blockedDates, }: {
43
+ cells: readonly DayCell[];
44
+ events: readonly SCalendarBoardEvent[];
45
+ /** 칸 하나에 담기는 줄 수 */
46
+ rowCapacity: number;
47
+ /** 일정을 그리지 않는 날짜 (`dayContent` 를 받은 칸) */
48
+ blockedDates: ReadonlySet<string>;
49
+ }): CalendarBoardLayout;
@@ -4,8 +4,17 @@ import type { SCalendarBoardEventColor } from './calendarBoard.config';
4
4
  export interface SCalendarBoardEvent {
5
5
  /** 고유 식별자. 없으면 목록 순서로 key 를 만든다 */
6
6
  id?: string;
7
- /** 날짜 (YYYY-MM-DD) */
7
+ /** 시작 날짜 (YYYY-MM-DD). 하루짜리 일정은 이것만 준다 */
8
8
  date: string;
9
+ /**
10
+ * 마지막 날 (YYYY-MM-DD, **그날 포함**). 주지 않거나 `date` 보다 앞서면 하루짜리로 본다.
11
+ *
12
+ * 여러 날에 걸친 일정은 칸 경계를 넘어 **하나의 막대로 이어져** 그려진다. 주 경계에서는 줄이
13
+ * 바뀌므로 조각이 나뉘고, 그렇게 잘린 쪽 모서리는 평평해져 "앞/뒤로 이어진다" 가 읽힌다.
14
+ *
15
+ * 막대가 걸친 날은 **모두** 그 일정을 가진 날로 친다 — 목록 판과 `onValueChange` 에 함께 온다.
16
+ */
17
+ endDate?: string;
9
18
  /**
10
19
  * 강조 레이블 (필수) — 예: `"[입고 예정]"`.
11
20
  * 일정이 무엇인지 한눈에 알리는 부분이라 비워 두지 않는다.
@@ -28,6 +28,7 @@
28
28
  |------|------|---------|-------------|
29
29
  | `background?` | `SPageBackground` | `'frame'` | 페이지 배경 표면. frame=흰 콘텐츠 면, neutral=옅은 회색 면, screen=앱 바탕. 스크롤바 처리도 여기 묶여 있다 — 셋 다 구분선+트랙 배경이고, 트랙 색만 neutral 에서 흰색이 된다. |
30
30
  | `scrollEndSpacing?` | `boolean` | `false` | 스크롤 끝 여백. 마지막 항목이 창 하단에 붙어 "여기서 끝"이 안 읽히는 것을 막는다. **기본은 꺼져 있다.** 페이지 스크롤 자체가 예외이기 때문이다 — 대부분의 화면은 본문이 창을 꽉 채우고 스크롤은 각 영역 안에서 일어난다. 여백을 조건 없이 붙이면 내용이 화면에 거의 딱 맞는 페이지까지 그 여백 때문에 스크롤되게 만든다. 페이지가 실제로 스크롤되는 화면(`contentHeight="auto"` + 내용이 창보다 김)에서만 켠다. 페이지네이션처럼 끝을 알려주는 것이 이미 있으면 켜지 않는다. |
31
+ | `padding?` | `SPagePadding` | `'default'` | 본문 안쪽 여백. 기본은 `default` — `--cmp-pageBody-padding-default` 를 사방에 넣는다. `none` 은 필터 바처럼 **가장자리까지 차는 블록이 맨 위에 서는** 화면용이다. 패딩을 끄면 그 아래 블록이 `p-[var(--cmp-pageBody-padding-default)]` 로 같은 토큰의 여백을 직접 잡는다 — `p-sd-*` 로 적으면 토큰이 바뀌어도 따라가지 않는다. 사방 패딩만 끄고 `scrollEndSpacing` 은 그대로다. (`SPopup`·`SSectionHeaderCard` 의 `padding="none"` 과 같은 관용구) |
31
32
  | `overlayScrollbar?` | `boolean` | `false` | true면 네이티브 스크롤바를 숨기고 SPage 위에 오버레이 스크롤바를 얹는다. 스크롤바가 레이아웃 폭을 차지하지 않아 내부 콘텐츠 폭이 줄어들지 않는다. |
32
33
  | `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
34
  | `contentWidth?` | `SPageContentWidth` | `'full'` | 본문 가로 폭 모드. 기본은 `full` — 창이 넓어지면 본문도 같이 넓어진다(반응형). `fixed`·`fixedCenter` 는 본문을 **레이아웃 최소 폭일 때의 폭**으로 고정한다. 최소 폭 기준으로 그린 시안이 넓은 모니터에서 늘어나 성기어지는 것을 막는 모드다. 남는 폭은 `fixed` 면 오른쪽에, `fixedCenter` 면 좌우로 나뉘어 페이지 배경으로 남는다. 고정 폭은 GNB 폭·접힘을 반영해 저절로 따라오므로 앱이 숫자를 쓸 일은 없다. 창이 최소 폭보다 좁아지면 세 모드가 모두 같다 — 남는 폭이 없어 규칙이 꺼지고, 모자란 몫을 지금까지처럼 이 영역이 가로 스크롤로 삼킨다. 같은 열에 `SPageHeader` 가 있으면 헤더도 같은 폭·정렬을 따른다(제목과 본문의 좌우 끝이 맞는다). `SLayout` 밖에서는 기준이 될 최소 폭이 없으므로 무시된다. |
@@ -46,6 +47,12 @@ export type SPageHeaderVariant = (typeof PAGE_HEADER_VARIANTS)[number];
46
47
  export type SPageBackground = (typeof PAGE_BACKGROUNDS)[number];
47
48
  ```
48
49
 
50
+ ### SPagePadding
51
+
52
+ ```ts
53
+ export type SPagePadding = (typeof PAGE_PADDINGS)[number];
54
+ ```
55
+
49
56
  ### SPageContentHeight
50
57
 
51
58
  ```ts
@@ -82,6 +89,18 @@ export const PAGE_HEADER_VARIANTS = ['plain', 'bar'] as const;
82
89
  export const PAGE_BACKGROUNDS = ['frame', 'neutral', 'screen'] as const;
83
90
  ```
84
91
 
92
+ ### PAGE_PADDINGS
93
+
94
+ ```ts
95
+ /**
96
+ * 본문 안쪽 여백 모드.
97
+ * - default: SPage 가 --cmp-pageBody-padding-default 로 사방 패딩을 넣는다
98
+ * - none: 패딩을 끈다. 가장자리까지 차는 블록(필터 바 등)이 맨 위에 서고, 그 아래 블록이
99
+ * 같은 토큰으로 여백을 직접 잡는 화면용. SPopup·SSectionHeaderCard 의 padding="none" 과 같은 관용구.
100
+ */
101
+ export const PAGE_PADDINGS = ['default', 'none'] as const;
102
+ ```
103
+
85
104
  ### PAGE_CONTENT_HEIGHTS
86
105
 
87
106
  ```ts
@@ -1,5 +1,5 @@
1
1
  import { type HTMLAttributes } from 'react';
2
- import type { SPageBackground, SPageContentHeight, SPageContentWidth } from './page.config';
2
+ import type { SPageBackground, SPageContentHeight, SPageContentWidth, SPagePadding } from './page.config';
3
3
  export interface SPageProps extends HTMLAttributes<HTMLElement> {
4
4
  /**
5
5
  * 페이지 배경 표면. frame=흰 콘텐츠 면, neutral=옅은 회색 면, screen=앱 바탕.
@@ -17,6 +17,15 @@ export interface SPageProps extends HTMLAttributes<HTMLElement> {
17
17
  * 페이지네이션처럼 끝을 알려주는 것이 이미 있으면 켜지 않는다.
18
18
  */
19
19
  scrollEndSpacing?: boolean;
20
+ /**
21
+ * 본문 안쪽 여백. 기본은 `default` — `--cmp-pageBody-padding-default` 를 사방에 넣는다.
22
+ *
23
+ * `none` 은 필터 바처럼 **가장자리까지 차는 블록이 맨 위에 서는** 화면용이다. 패딩을 끄면
24
+ * 그 아래 블록이 `p-[var(--cmp-pageBody-padding-default)]` 로 같은 토큰의 여백을 직접 잡는다 —
25
+ * `p-sd-*` 로 적으면 토큰이 바뀌어도 따라가지 않는다. 사방 패딩만 끄고 `scrollEndSpacing` 은
26
+ * 그대로다. (`SPopup`·`SSectionHeaderCard` 의 `padding="none"` 과 같은 관용구)
27
+ */
28
+ padding?: SPagePadding;
20
29
  /**
21
30
  * true면 네이티브 스크롤바를 숨기고 SPage 위에 오버레이 스크롤바를 얹는다.
22
31
  * 스크롤바가 레이아웃 폭을 차지하지 않아 내부 콘텐츠 폭이 줄어들지 않는다.
@@ -53,7 +62,7 @@ export interface SPageProps extends HTMLAttributes<HTMLElement> {
53
62
  * SPage — SLayout 안에서 남은 공간을 채우는 스크롤 콘텐츠 영역.
54
63
  * 스크롤은 SLayout(overflow:hidden)이 잡아둔 경계 안에서 이 영역에만 생긴다.
55
64
  * 창이 SLayout 의 최소 폭보다 좁을 때 생기는 가로 스크롤도 여기 걸린다(문서는 스크롤되지 않는다).
56
- * 패딩은 className 으로, 배경은 background 로 정한다(className 으로도 덮어쓸 수 있다).
65
+ * 패딩은 padding 으로, 배경은 background 로 정한다(둘 다 className 으로도 덮어쓸 수 있다).
57
66
  *
58
67
  * - header="fix": flex 자식으로 남은 가로 공간을 채운다.
59
68
  * - header="full": SLayout 이 깐 grid 의 "page" 영역 = 상단바 아래·메뉴 오른쪽 자리를 차지한다.
@@ -1,3 +1,3 @@
1
1
  export { SPage, type SPageProps } from './SPage';
2
- export { PAGE_BACKGROUNDS, type SPageBackground, PAGE_CONTENT_HEIGHTS, type SPageContentHeight, PAGE_CONTENT_WIDTHS, type SPageContentWidth, PAGE_HEADER_VARIANTS, type SPageHeaderVariant, } from './page.config';
2
+ export { PAGE_BACKGROUNDS, type SPageBackground, PAGE_CONTENT_HEIGHTS, type SPageContentHeight, PAGE_CONTENT_WIDTHS, type SPageContentWidth, PAGE_PADDINGS, type SPagePadding, PAGE_HEADER_VARIANTS, type SPageHeaderVariant, } from './page.config';
3
3
  export { SPageHeader, type SPageHeaderProps } from './SPageHeader';
@@ -14,6 +14,14 @@ export type SPageBackground = (typeof PAGE_BACKGROUNDS)[number];
14
14
  */
15
15
  export declare const PAGE_CONTENT_HEIGHTS: readonly ["auto", "fill"];
16
16
  export type SPageContentHeight = (typeof PAGE_CONTENT_HEIGHTS)[number];
17
+ /**
18
+ * 본문 안쪽 여백 모드.
19
+ * - default: SPage 가 --cmp-pageBody-padding-default 로 사방 패딩을 넣는다
20
+ * - none: 패딩을 끈다. 가장자리까지 차는 블록(필터 바 등)이 맨 위에 서고, 그 아래 블록이
21
+ * 같은 토큰으로 여백을 직접 잡는 화면용. SPopup·SSectionHeaderCard 의 padding="none" 과 같은 관용구.
22
+ */
23
+ export declare const PAGE_PADDINGS: readonly ["default", "none"];
24
+ export type SPagePadding = (typeof PAGE_PADDINGS)[number];
17
25
  /**
18
26
  * 본문 가로 폭 모드 — 창이 레이아웃 최소 폭보다 **넓을 때** 본문이 어떻게 설지.
19
27
  * - full: 남는 폭을 본문이 다 쓴다 (반응형)
@@ -0,0 +1,13 @@
1
+ /**
2
+ * "페이지 레시피" 상단의 카드 그리드 — 레시피를 화면으로 먼저 보고 골라 들어가게 한다.
3
+ *
4
+ * 미리보기는 그림이 아니라 **레시피 파일 그 자체**를 축소해 렌더한 것이다. 그래서 레시피 코드가
5
+ * 바뀌면 카드도 함께 바뀌고, 따로 갱신할 자산이 없다. 규칙 설명은 이 아래에 AGENTS.md §4 가
6
+ * 그대로 렌더되므로 여기에는 쓰지 않는다.
7
+ *
8
+ * 레시피는 페이지 **안**의 골격이라 GNB·레이아웃은 그리지 않는다 — 셸 조합은 Layout Builder 의 몫이다.
9
+ *
10
+ * 새 레시피를 `src/recipes/` 에 만들면 여기에 한 줄을 더한다.
11
+ */
12
+ import type { ReactNode } from 'react';
13
+ export default function RecipeGallery(): ReactNode;