sellmate-design-system-react 9.0.0-beta.0 → 9.0.0-beta.10

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 (59) hide show
  1. package/AGENTS.md +153 -45
  2. package/README.md +63 -0
  3. package/dist/components/SChipFilter/README.md +2 -1
  4. package/dist/components/SChipFilter/SChipFilter.d.ts +13 -6
  5. package/dist/components/SCircleProgress/README.md +3 -0
  6. package/dist/components/SCircleProgress/SCircleProgress.d.ts +7 -1
  7. package/dist/components/SDatePicker/README.md +41 -3
  8. package/dist/components/SDatePicker/SDatePicker.d.ts +36 -3
  9. package/dist/components/SDatePicker/index.d.ts +1 -1
  10. package/dist/components/SField/README.md +3 -0
  11. package/dist/components/SField/SField.d.ts +12 -0
  12. package/dist/components/SGhostButton/README.md +2 -0
  13. package/dist/components/SGnb/gnb.config.d.ts +2 -0
  14. package/dist/components/SIcon/README.md +4 -0
  15. package/dist/components/SImage/README.md +44 -0
  16. package/dist/components/SImage/SImage.d.ts +41 -0
  17. package/dist/components/SImage/index.d.ts +1 -0
  18. package/dist/components/SKeyValueTable/README.md +1 -0
  19. package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +8 -1
  20. package/dist/components/SList/README.md +0 -1
  21. package/dist/components/SList/SList.d.ts +0 -2
  22. package/dist/components/SPage/README.md +2 -0
  23. package/dist/components/SPage/SPage.d.ts +17 -1
  24. package/dist/components/SPage/index.d.ts +1 -1
  25. package/dist/components/SPage/page.config.d.ts +8 -0
  26. package/dist/components/SSearchInput/README.md +48 -0
  27. package/dist/components/SSearchInput/SSearchInput.d.ts +46 -0
  28. package/dist/components/SSearchInput/index.d.ts +1 -0
  29. package/dist/components/SSectionHeaderCard/README.md +10 -23
  30. package/dist/components/SSectionHeaderCard/SSectionHeaderCard.d.ts +21 -14
  31. package/dist/components/SSectionHeaderCard/index.d.ts +1 -1
  32. package/dist/components/SSelect/README.md +2 -0
  33. package/dist/components/STable/README.md +1 -0
  34. package/dist/components/STable/STable.d.ts +20 -0
  35. package/dist/components/STabs/README.md +0 -1
  36. package/dist/components/STabs/STabs.d.ts +2 -4
  37. package/dist/components/STabs/index.d.ts +1 -1
  38. package/dist/components/STabs/tabs.config.d.ts +3 -4
  39. package/dist/components/STimePicker/timepicker.config.d.ts +5 -0
  40. package/dist/components/SToggle/README.md +1 -0
  41. package/dist/components/SToggle/SToggle.d.ts +4 -1
  42. package/dist/components/STree/README.md +3 -0
  43. package/dist/components/STree/STree.d.ts +8 -0
  44. package/dist/components/STree/index.d.ts +1 -1
  45. package/dist/index.cjs +1545 -359
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.ts +2 -0
  48. package/dist/index.js +1540 -360
  49. package/dist/index.js.map +1 -1
  50. package/dist/lib/truncated-value-tooltip.d.ts +18 -0
  51. package/dist/llms-full.txt +300 -69
  52. package/dist/llms.txt +157 -48
  53. package/dist/styles.css +201 -32
  54. package/dist/theme.css +34 -11
  55. package/eslint/index.mjs +5 -0
  56. package/eslint/rules/field-width-grade.d.mts +41 -0
  57. package/eslint/rules/field-width-grade.mjs +294 -0
  58. package/eslint/scale.gen.mjs +1 -1
  59. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { type CSSProperties } from 'react';
2
- export type SCircleProgressType = 'primary' | 'inverse' | 'error' | 'complete';
2
+ export type SCircleProgressType = 'primary' | 'inverse' | 'error' | 'complete' | 'neutral';
3
3
  export interface SCircleProgressProps {
4
4
  /** 진행률 (0–100) */
5
5
  value?: number;
@@ -7,6 +7,12 @@ export interface SCircleProgressProps {
7
7
  type?: SCircleProgressType;
8
8
  /** 불확정(스피너) 모드 — value 무시 */
9
9
  indeterminate?: boolean;
10
+ /**
11
+ * 링의 지름. 숫자는 px 로 해석한다.
12
+ * 부모 크기에 비례시키려면 컨테이너 쿼리 단위(`'45cqh'`)를 쓴다 — 퍼센트는 부모가
13
+ * inline-flex 라 기준 폭이 정해지지 않아 해석되지 않는다.
14
+ */
15
+ size?: number | string;
10
16
  /** 하단 레이블 */
11
17
  label?: string;
12
18
  /** true면 퍼센트를 원 아래가 아닌 원 가운데에 표시 */
@@ -2,15 +2,35 @@
2
2
 
3
3
  > 자동 생성 문서 — `npm run docs:gen`. 소스: 각 컴포넌트의 Props/Handle 인터페이스 + import 의존성.
4
4
 
5
+ ### SDatePickerMonthListbox
6
+
7
+ #### Props
8
+
9
+ | Prop | Type | Default | Description |
10
+ |------|------|---------|-------------|
11
+ | `value?` | `string \| null` | — | 선택 월 (YYYY-MM) |
12
+ | `anchorYear?` | `number` | — | 연도 리스트가 처음 열릴 때 중앙에 둘 연도. 기본값은 올해 |
13
+ | `selectable?` | `[string, string]` | — | 선택 가능 범위 [시작, 종료] |
14
+ | `className?` | `string` | — | |
15
+ | `style?` | `CSSProperties` | — | |
16
+
17
+ #### Events
18
+
19
+ | Event | Type | Description |
20
+ |-------|------|-------------|
21
+ | `onValueChange` | `(value: string) => void` | |
22
+ | `onMonthSelect` | `(value: string) => void` | 월 컬럼에서 월을 선택했을 때 호출 |
23
+
5
24
  ### SDatePicker
6
25
 
7
26
  #### Props
8
27
 
9
28
  | Prop | Type | Default | Description |
10
29
  |------|------|---------|-------------|
11
- | `value?` | `string \| null` | — | 선택 날짜 (YYYY-MM-DD) |
30
+ | `value?` | `string \| null` | — | 선택 값 (date: YYYY-MM-DD, month: YYYY-MM, year: YYYY) |
31
+ | `mode?` | `SDatePickerMode` | `'date'` | 선택 모드 |
12
32
  | `size?` | `SDatePickerSize` | `'sm'` | |
13
- | `placeholder?` | `string` | `'YYYY-MM-DD'` | |
33
+ | `placeholder?` | `string` | — | |
14
34
  | `selectable?` | `[string, string]` | — | 선택 가능 범위 [시작, 종료] |
15
35
  | `disabled?` | `boolean` | `false` | |
16
36
  | `width?` | `number \| string` | — | |
@@ -35,9 +55,27 @@
35
55
 
36
56
  | Event | Type | Description |
37
57
  |-------|------|-------------|
38
- | `onValueChange` | `(date: string) => void` | 선택 변경 (sdUpdate) |
58
+ | `onValueChange` | `(value: string) => void` | 선택 변경 (sdUpdate) |
39
59
  | `onViewChange` | `(view: { year: number; month: number }) => void` | 보이는 연·월 변경 (sdViewChange) |
40
60
 
61
+ ### SDatePickerYearListbox
62
+
63
+ #### Props
64
+
65
+ | Prop | Type | Default | Description |
66
+ |------|------|---------|-------------|
67
+ | `value?` | `string \| null` | — | 선택 연도 (YYYY) |
68
+ | `anchorYear?` | `number` | — | 리스트가 처음 열릴 때 중앙에 둘 연도. 기본값은 올해 |
69
+ | `selectable?` | `[string, string]` | — | 선택 가능 범위 [시작, 종료] |
70
+ | `className?` | `string` | — | |
71
+ | `style?` | `CSSProperties` | — | |
72
+
73
+ #### Events
74
+
75
+ | Event | Type | Description |
76
+ |-------|------|-------------|
77
+ | `onValueChange` | `(year: string) => void` | |
78
+
41
79
  ## Dependencies
42
80
 
43
81
  ### Used by
@@ -5,16 +5,19 @@ import { type SColor } from '../../lib/color';
5
5
  import { type Rule } from '../../lib/form';
6
6
  import { type STooltipProps } from '../STooltip';
7
7
  export type SDatePickerSize = SFieldSize;
8
+ export type SDatePickerMode = 'date' | 'month' | 'year';
8
9
  export interface SDatePickerProps {
9
- /** 선택 날짜 (YYYY-MM-DD) */
10
+ /** 선택 값 (date: YYYY-MM-DD, month: YYYY-MM, year: YYYY) */
10
11
  value?: string | null;
11
12
  /** 선택 변경 (sdUpdate) */
12
- onValueChange?: (date: string) => void;
13
+ onValueChange?: (value: string) => void;
13
14
  /** 보이는 연·월 변경 (sdViewChange) */
14
15
  onViewChange?: (view: {
15
16
  year: number;
16
17
  month: number;
17
18
  }) => void;
19
+ /** 선택 모드 */
20
+ mode?: SDatePickerMode;
18
21
  size?: SDatePickerSize;
19
22
  placeholder?: string;
20
23
  /** 선택 가능 범위 [시작, 종료] */
@@ -38,5 +41,35 @@ export interface SDatePickerProps {
38
41
  className?: string;
39
42
  style?: CSSProperties;
40
43
  }
44
+ export interface SDatePickerYearListboxProps {
45
+ /** 선택 연도 (YYYY) */
46
+ value?: string | null;
47
+ /** 리스트가 처음 열릴 때 중앙에 둘 연도. 기본값은 올해 */
48
+ anchorYear?: number;
49
+ /** 선택 가능 범위 [시작, 종료] */
50
+ selectable?: [string, string];
51
+ onValueChange?: (year: string) => void;
52
+ className?: string;
53
+ style?: CSSProperties;
54
+ }
55
+ /** SDatePickerYearListbox — SDatePicker의 연도 선택 listbox 조각.
56
+ * 자체 트리거/팝오버 없이 연도 리스트만 필요한 커스텀 조합에 재사용한다. */
57
+ export declare function SDatePickerYearListbox({ value, anchorYear, selectable, onValueChange, className, style, }: SDatePickerYearListboxProps): import("react").JSX.Element;
58
+ export interface SDatePickerMonthListboxProps {
59
+ /** 선택 월 (YYYY-MM) */
60
+ value?: string | null;
61
+ /** 연도 리스트가 처음 열릴 때 중앙에 둘 연도. 기본값은 올해 */
62
+ anchorYear?: number;
63
+ /** 선택 가능 범위 [시작, 종료] */
64
+ selectable?: [string, string];
65
+ onValueChange?: (value: string) => void;
66
+ /** 월 컬럼에서 월을 선택했을 때 호출 */
67
+ onMonthSelect?: (value: string) => void;
68
+ className?: string;
69
+ style?: CSSProperties;
70
+ }
71
+ /** SDatePickerMonthListbox — SDatePicker의 월 선택 listbox 조각.
72
+ * 자체 트리거/팝오버 없이 연도+월 리스트만 필요한 커스텀 조합에 재사용한다. */
73
+ export declare function SDatePickerMonthListbox({ value, anchorYear, selectable, onValueChange, onMonthSelect, className, style, }: SDatePickerMonthListboxProps): import("react").JSX.Element;
41
74
  /** SDatePicker — sd-date-picker 포팅. SField + SPopover(SCalendar). */
42
- export declare function SDatePicker({ value, onValueChange, onViewChange, size, placeholder, selectable, disabled, width, name, rules, status, label, labelWidth, icon, iconColor, labelTooltip, labelTooltipProps, addonLabel, addonAlign, hint, error, errorMessage, className, style, }: SDatePickerProps): import("react").JSX.Element;
75
+ export declare function SDatePicker({ value, onValueChange, onViewChange, mode, size, placeholder, selectable, disabled, width, name, rules, status, label, labelWidth, icon, iconColor, labelTooltip, labelTooltipProps, addonLabel, addonAlign, hint, error, errorMessage, className, style, }: SDatePickerProps): import("react").JSX.Element;
@@ -1 +1 @@
1
- export { SDatePicker, type SDatePickerProps, type SDatePickerSize } from './SDatePicker';
1
+ export { SDatePicker, SDatePickerMonthListbox, SDatePickerYearListbox, type SDatePickerMode, type SDatePickerMonthListboxProps, type SDatePickerProps, type SDatePickerSize, type SDatePickerYearListboxProps, } from './SDatePicker';
@@ -30,6 +30,7 @@
30
30
  | `readOnly?` | `boolean` | `false` | 읽기 전용 (회색 배경) |
31
31
  | `width?` | `number \| string` | — | 컨트롤 너비 (숫자=px). 지정하면 필드가 부모 폭을 다 먹지 않고 (레이블 + width) 만큼만 차지한다. 다른 요소와 나란히 놓으려면 부모를 flex 로 두면 된다. |
32
32
  | `minWidth?` | `number \| string` | — | 컨트롤 최소 너비 (숫자=px). 하한선만 지정하며 필드는 계속 부모 폭을 채운다 |
33
+ | `maxWidth?` | `number \| string` | — | 컨트롤 최대 너비 (숫자=px). 상한선만 지정하며 필드는 그 아래에서 부모 폭을 채운다. `width` 와 달리 hug 로 전환하지 않는다 — 부모가 좁으면 같이 좁아지고, 넓어도 여기서 멈춘다. 값 길이가 정해진 컨트롤(날짜·시간)이 `width="100%"` 를 받아 행 전체로 늘어나는 것을 막는 데 쓴다. **라벨은 상한에 들어가지 않는다** — 라벨은 컨트롤의 형제라 이 상한 밖이다. `addonLabel` 은 테두리 박스 안이라 상한을 나눠 먹으므로, `labelWidth`(= addon 폭)만큼 상한을 자동으로 늘린다. addon 이 있는데 `labelWidth` 가 없으면 폭을 알 수 없어 상한을 걸지 않는다 — 컨트롤이 잘리는 것보다 넓은 편이 낫다. |
33
34
  | `multiline?` | `boolean` | `false` | 멀티라인(textarea) — 컨트롤 높이를 고정하지 않고 min-height만 적용 |
34
35
  | `borderless?` | `boolean` | `false` | 테두리 박스 제거 (inline 컨트롤용) — border/배경/hover·focus 강조만 사라지고 label·hint·errorMessage 등 나머지 필드 구성은 그대로 동작한다. |
35
36
  | `children?` | `ReactNode` | — | 실제 컨트롤 (input/select 등) — 테두리 없이 렌더, 테두리는 SField가 제공 |
@@ -60,6 +61,7 @@
60
61
  - [SFilePicker](../SFilePicker)
61
62
  - [SInput](../SInput)
62
63
  - [SNumberInput](../SNumberInput)
64
+ - [SSearchInput](../SSearchInput)
63
65
  - [SSelect](../SSelect)
64
66
  - [STextarea](../STextarea)
65
67
  - [STimePicker](../STimePicker)
@@ -83,6 +85,7 @@ graph TD;
83
85
  SFilePicker --> SField
84
86
  SInput --> SField
85
87
  SNumberInput --> SField
88
+ SSearchInput --> SField
86
89
  SSelect --> SField
87
90
  STextarea --> SField
88
91
  STimePicker --> SField
@@ -63,6 +63,18 @@ export interface SFieldProps {
63
63
  width?: number | string;
64
64
  /** 컨트롤 최소 너비 (숫자=px). 하한선만 지정하며 필드는 계속 부모 폭을 채운다 */
65
65
  minWidth?: number | string;
66
+ /**
67
+ * 컨트롤 최대 너비 (숫자=px). 상한선만 지정하며 필드는 그 아래에서 부모 폭을 채운다.
68
+ *
69
+ * `width` 와 달리 hug 로 전환하지 않는다 — 부모가 좁으면 같이 좁아지고, 넓어도 여기서 멈춘다.
70
+ * 값 길이가 정해진 컨트롤(날짜·시간)이 `width="100%"` 를 받아 행 전체로 늘어나는 것을 막는 데 쓴다.
71
+ *
72
+ * **라벨은 상한에 들어가지 않는다** — 라벨은 컨트롤의 형제라 이 상한 밖이다.
73
+ * `addonLabel` 은 테두리 박스 안이라 상한을 나눠 먹으므로, `labelWidth`(= addon 폭)만큼
74
+ * 상한을 자동으로 늘린다. addon 이 있는데 `labelWidth` 가 없으면 폭을 알 수 없어 상한을
75
+ * 걸지 않는다 — 컨트롤이 잘리는 것보다 넓은 편이 낫다.
76
+ */
77
+ maxWidth?: number | string;
66
78
  /** 멀티라인(textarea) — 컨트롤 높이를 고정하지 않고 min-height만 적용 */
67
79
  multiline?: boolean;
68
80
  /**
@@ -44,6 +44,7 @@
44
44
  - [SOverlayHeader](../SOverlayHeader)
45
45
  - [SPage](../SPage)
46
46
  - [SPopover](../SPopover)
47
+ - [SSearchInput](../SSearchInput)
47
48
  - [SSelect](../SSelect)
48
49
  - [STimePicker](../STimePicker)
49
50
  - [STimeRangePicker](../STimeRangePicker)
@@ -75,6 +76,7 @@ graph TD;
75
76
  SOverlayHeader --> SGhostButton
76
77
  SPage --> SGhostButton
77
78
  SPopover --> SGhostButton
79
+ SSearchInput --> SGhostButton
78
80
  SSelect --> SGhostButton
79
81
  STimePicker --> SGhostButton
80
82
  STimeRangePicker --> SGhostButton
@@ -48,6 +48,8 @@ export declare const GNB_MENU: Record<SGnbType, {
48
48
  depth1FontWeight: number;
49
49
  itemFontSize: number;
50
50
  itemLineHeight: number;
51
+ itemFontWeight: number;
52
+ itemFontWeightSelected: number;
51
53
  }>;
52
54
  /**
53
55
  * 색상(color 축). light → --cmp-gnb-light-* 색, dark → --cmp-gnb-dark-* 색
@@ -36,12 +36,14 @@
36
36
  - [SGhostButton](../SGhostButton)
37
37
  - [SGnb](../SGnb)
38
38
  - [SGuide](../SGuide)
39
+ - [SImage](../SImage)
39
40
  - [SKeyValueTable](../SKeyValueTable)
40
41
  - [SListItem](../SListItem)
41
42
  - [SLoadingModal](../SLoadingModal)
42
43
  - [SNumberInput](../SNumberInput)
43
44
  - [SPagination](../SPagination)
44
45
  - [SPopover](../SPopover)
46
+ - [SSearchInput](../SSearchInput)
45
47
  - [SSectionHeaderCard](../SSectionHeaderCard)
46
48
  - [SSelect](../SSelect)
47
49
  - [SStepper](../SStepper)
@@ -73,12 +75,14 @@ graph TD;
73
75
  SGhostButton --> SIcon
74
76
  SGnb --> SIcon
75
77
  SGuide --> SIcon
78
+ SImage --> SIcon
76
79
  SKeyValueTable --> SIcon
77
80
  SListItem --> SIcon
78
81
  SLoadingModal --> SIcon
79
82
  SNumberInput --> SIcon
80
83
  SPagination --> SIcon
81
84
  SPopover --> SIcon
85
+ SSearchInput --> SIcon
82
86
  SSectionHeaderCard --> SIcon
83
87
  SSelect --> SIcon
84
88
  SStepper --> SIcon
@@ -0,0 +1,44 @@
1
+ # SImage
2
+
3
+ > 자동 생성 문서 — `npm run docs:gen`. 소스: 각 컴포넌트의 Props/Handle 인터페이스 + import 의존성.
4
+
5
+ ### SImage
6
+
7
+ #### Props
8
+
9
+ | Prop | Type | Default | Description |
10
+ |------|------|---------|-------------|
11
+ | `src?` | `string` | — | 이미지 경로. 없으면 빈 이미지 아이콘이 나온다 |
12
+ | `alt?` | `string` | `''` | 대체 텍스트 |
13
+ | `ratio?` | `number` | `1` | 가로세로 비율. 소비자가 높이를 직접 주면 그쪽이 이긴다 |
14
+ | `fit?` | `SImageFit` | `'cover'` | 이미지가 상자를 채우는 방식 (object-fit) |
15
+ | `position?` | `string` | `'50% 50%'` | 이미지 정렬 위치 (object-position) |
16
+ | `loading?` | `'lazy' \| 'eager'` | `'lazy'` | 브라우저 로딩 방식 |
17
+ | `loadingShowDelay?` | `number` | `0` | 스피너를 띄우기까지 기다리는 시간(ms). 이 시간 안에 로드되면 스피너를 아예 그리지 않는다 — 캐시된 이미지에서 스피너가 한 프레임 번쩍이는 것을 막는다. |
18
+ | `noSpinner?` | `boolean` | `false` | 로딩 중에도 스피너를 그리지 않는다 |
19
+ | `loadingSlot?` | `ReactNode` | — | 로딩 중 표시를 직접 지정한다 (기본: 스피너) |
20
+ | `errorSlot?` | `ReactNode` | — | 실패·빈 상태 표시를 직접 지정한다 (기본: 빈 이미지 아이콘) |
21
+ | `imgProps?` | `ImgHTMLAttributes<HTMLImageElement>` | — | 안쪽 `<img>` 로 넘길 네이티브 속성 (srcSet · sizes · crossOrigin · draggable 등) |
22
+
23
+ #### Events
24
+
25
+ | Event | Type | Description |
26
+ |-------|------|-------------|
27
+ | `onLoad` | `(src: string) => void` | 로드 완료. 로드된 src 를 넘긴다 |
28
+ | `onError` | `(event: SyntheticEvent<HTMLImageElement>) => void` | 로드 실패 |
29
+
30
+ ## Dependencies
31
+
32
+ ### Depends on
33
+
34
+ - [SCircleProgress](../SCircleProgress)
35
+ - [SIcon](../SIcon)
36
+
37
+ ### Graph
38
+
39
+ ```mermaid
40
+ graph TD;
41
+ SImage --> SCircleProgress
42
+ SImage --> SIcon
43
+ style SImage fill:#f9f,stroke:#333,stroke-width:4px
44
+ ```
@@ -0,0 +1,41 @@
1
+ import { type HTMLAttributes, type ImgHTMLAttributes, type ReactNode, type SyntheticEvent } from 'react';
2
+ export declare const IMAGE_FITS: readonly ["cover", "contain", "fill", "none", "scale-down"];
3
+ export type SImageFit = (typeof IMAGE_FITS)[number];
4
+ export interface SImageProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onLoad' | 'onError'> {
5
+ /** 이미지 경로. 없으면 빈 이미지 아이콘이 나온다 */
6
+ src?: string;
7
+ /** 대체 텍스트 */
8
+ alt?: string;
9
+ /** 가로세로 비율. 소비자가 높이를 직접 주면 그쪽이 이긴다 */
10
+ ratio?: number;
11
+ /** 이미지가 상자를 채우는 방식 (object-fit) */
12
+ fit?: SImageFit;
13
+ /** 이미지 정렬 위치 (object-position) */
14
+ position?: string;
15
+ /** 브라우저 로딩 방식 */
16
+ loading?: 'lazy' | 'eager';
17
+ /**
18
+ * 스피너를 띄우기까지 기다리는 시간(ms). 이 시간 안에 로드되면 스피너를 아예 그리지 않는다 —
19
+ * 캐시된 이미지에서 스피너가 한 프레임 번쩍이는 것을 막는다.
20
+ */
21
+ loadingShowDelay?: number;
22
+ /** 로딩 중에도 스피너를 그리지 않는다 */
23
+ noSpinner?: boolean;
24
+ /** 로딩 중 표시를 직접 지정한다 (기본: 스피너) */
25
+ loadingSlot?: ReactNode;
26
+ /** 실패·빈 상태 표시를 직접 지정한다 (기본: 빈 이미지 아이콘) */
27
+ errorSlot?: ReactNode;
28
+ /** 안쪽 `<img>` 로 넘길 네이티브 속성 (srcSet · sizes · crossOrigin · draggable 등) */
29
+ imgProps?: ImgHTMLAttributes<HTMLImageElement>;
30
+ /** 로드 완료. 로드된 src 를 넘긴다 */
31
+ onLoad?: (src: string) => void;
32
+ /** 로드 실패 */
33
+ onError?: (event: SyntheticEvent<HTMLImageElement>) => void;
34
+ }
35
+ /**
36
+ * SImage — 이미지 로딩·실패 상태를 스스로 표현하는 이미지 상자.
37
+ *
38
+ * 로딩 중에는 스피너, `src` 가 없거나 로드에 실패하면 빈 이미지 아이콘을 컨테이너 높이에
39
+ * 비례한 크기로 가운데에 그린다.
40
+ */
41
+ export declare const SImage: import("react").ForwardRefExoticComponent<SImageProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ export { SImage, IMAGE_FITS, type SImageProps, type SImageFit } from './SImage';
@@ -12,6 +12,7 @@
12
12
  | `values?` | `Record<string, unknown>` | `{}` | field name을 key로 하는 값 객체 (`{ [name]: value }`). 지정 시 해당 field의 값으로 사용되며, field별 `options.value`보다 우선합니다. `onChange`의 `detail.values`와 함께 controlled 패턴으로 사용합니다. |
13
13
  | `search?` | `boolean` | `false` | 우측 검색 패널 |
14
14
  | `radius?` | `'default' \| 'useTop' \| 'full'` | `'default'` | border-radius 제어 |
15
+ | `bordered?` | `boolean` | `true` | 바깥 테두리. 기본은 `true`. `SSectionHeaderCard` 의 `padding="none"` 안에 넣어 카드 가장자리까지 채울 때 `false` 로 끈다 — 카드가 이미 바깥 테두리를 그리므로, 켜 두면 1px 두 개가 나란히 놓여 그 변만 2px 로 보인다. |
15
16
  | `className?` | `string` | — | |
16
17
  | `style?` | `CSSProperties` | — | |
17
18
 
@@ -104,6 +104,13 @@ export interface SKeyValueTableProps {
104
104
  search?: boolean;
105
105
  /** border-radius 제어 */
106
106
  radius?: 'default' | 'useTop' | 'full';
107
+ /**
108
+ * 바깥 테두리. 기본은 `true`.
109
+ *
110
+ * `SSectionHeaderCard` 의 `padding="none"` 안에 넣어 카드 가장자리까지 채울 때 `false` 로 끈다 —
111
+ * 카드가 이미 바깥 테두리를 그리므로, 켜 두면 1px 두 개가 나란히 놓여 그 변만 2px 로 보인다.
112
+ */
113
+ bordered?: boolean;
107
114
  /** 값 변경 (sdChange) */
108
115
  onChange?: (detail: SKeyValueChangeDetail) => void;
109
116
  /** 검색 클릭 (sdSearch) */
@@ -112,5 +119,5 @@ export interface SKeyValueTableProps {
112
119
  style?: CSSProperties;
113
120
  }
114
121
  /** SKeyValueTable — sd-key-value-table 포팅. th/td 폼 레이아웃 + 필드 렌더러. */
115
- export declare function SKeyValueTable({ fields, values, search, radius, onChange, onSearch, className, style, }: SKeyValueTableProps): import("react").JSX.Element | null;
122
+ export declare function SKeyValueTable({ fields, values, search, radius, bordered, onChange, onSearch, className, style, }: SKeyValueTableProps): import("react").JSX.Element | null;
116
123
  export {};
@@ -11,7 +11,6 @@
11
11
  | `children?` | `ReactNode` | — | 리스트 컨테이너 내부에 렌더링할 내용 |
12
12
  | `useGap?` | `boolean` | `false` | 리스트 아이템 사이 gap 토큰 적용 여부 |
13
13
  | `usePadding?` | `boolean` | `false` | 리스트 컨테이너 padding 토큰 적용 여부 |
14
- | `separator?` | `boolean` | `false` | 아이템 하단 구분선 표시 여부. 테두리를 가진 아이템(`bordered`)에는 쓰지 않는다 |
15
14
 
16
15
  ## Dependencies
17
16
 
@@ -6,7 +6,5 @@ export interface SListProps extends HTMLAttributes<HTMLDivElement> {
6
6
  useGap?: boolean;
7
7
  /** 리스트 컨테이너 padding 토큰 적용 여부 */
8
8
  usePadding?: boolean;
9
- /** 아이템 하단 구분선 표시 여부. 테두리를 가진 아이템(`bordered`)에는 쓰지 않는다 */
10
- separator?: boolean;
11
9
  }
12
10
  export declare const SList: import("react").ForwardRefExoticComponent<SListProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -28,6 +28,8 @@
28
28
  |------|------|---------|-------------|
29
29
  | `background?` | `SPageBackground` | `'frame'` | 페이지 배경 표면. frame=흰 콘텐츠 면, neutral=옅은 회색 면, screen=앱 바탕. 스크롤바 처리도 여기 묶여 있다 — 셋 다 구분선+트랙 배경이고, 트랙 색만 neutral 에서 흰색이 된다. |
30
30
  | `scrollEndSpacing?` | `boolean` | `true` | 스크롤 끝 여백. 마지막 항목이 창 하단에 붙어 "여기서 끝"이 안 읽히는 것을 막는다. 기본으로 켜져 있고, 페이지네이션처럼 끝을 알려주는 것이 이미 있으면 끈다(목록 페이지). |
31
+ | `overlayScrollbar?` | `boolean` | `false` | true면 네이티브 스크롤바를 숨기고 SPage 위에 오버레이 스크롤바를 얹는다. 스크롤바가 레이아웃 폭을 차지하지 않아 내부 콘텐츠 폭이 줄어들지 않는다. |
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` 이 무시된다. |
31
33
  | `header?` | `SPageHeaderProps` | — | 페이지 타이틀 영역(pageHeader 포팅). 주면 스크롤·페이지 패딩 밖으로 빼내 상단에 고정 배치한다. `children` 은 항상 본문이다 — header 유무와 무관하게 같은 자리에 같은 뜻으로 들어간다. |
32
34
 
33
35
  ## Dependencies
@@ -1,5 +1,5 @@
1
1
  import { type HTMLAttributes } from 'react';
2
- import type { SPageBackground } from './page.config';
2
+ import type { SPageBackground, SPageContentHeight } from './page.config';
3
3
  import { type SPageHeaderProps } from './SPageHeader';
4
4
  export interface SPageProps extends HTMLAttributes<HTMLElement> {
5
5
  /**
@@ -12,6 +12,22 @@ export interface SPageProps extends HTMLAttributes<HTMLElement> {
12
12
  * 기본으로 켜져 있고, 페이지네이션처럼 끝을 알려주는 것이 이미 있으면 끈다(목록 페이지).
13
13
  */
14
14
  scrollEndSpacing?: boolean;
15
+ /**
16
+ * true면 네이티브 스크롤바를 숨기고 SPage 위에 오버레이 스크롤바를 얹는다.
17
+ * 스크롤바가 레이아웃 폭을 차지하지 않아 내부 콘텐츠 폭이 줄어들지 않는다.
18
+ */
19
+ overlayScrollbar?: boolean;
20
+ /**
21
+ * 본문 높이 모드. 기본은 `auto` — 콘텐츠가 흐르고 넘치면 페이지가 스크롤한다.
22
+ *
23
+ * `fill` 은 본문이 남은 높이를 정확히 채우고 페이지는 스크롤하지 않는다. 표가 자기 안에서
24
+ * 스크롤하고 페이지네이션이 하단에 고정되는 목록 화면용이다. 본문 루트에 `h-full` 이 먹으므로
25
+ * `<div className="flex h-full min-h-0 flex-col">` + `<STable className="min-h-0 flex-1" />`
26
+ * 구성이 성립한다.
27
+ *
28
+ * `fill` 에서는 페이지가 스크롤하지 않으므로 `scrollEndSpacing` 이 무시된다.
29
+ */
30
+ contentHeight?: SPageContentHeight;
15
31
  /**
16
32
  * 페이지 타이틀 영역(pageHeader 포팅). 주면 스크롤·페이지 패딩 밖으로 빼내 상단에 고정 배치한다.
17
33
  * `children` 은 항상 본문이다 — header 유무와 무관하게 같은 자리에 같은 뜻으로 들어간다.
@@ -1,3 +1,3 @@
1
1
  export { SPage, type SPageProps } from './SPage';
2
- export { PAGE_BACKGROUNDS, type SPageBackground } from './page.config';
2
+ export { PAGE_BACKGROUNDS, type SPageBackground, PAGE_CONTENT_HEIGHTS, type SPageContentHeight, } from './page.config';
3
3
  export { type SPageHeaderProps } from './SPageHeader';
@@ -6,3 +6,11 @@
6
6
  */
7
7
  export declare const PAGE_BACKGROUNDS: readonly ["frame", "neutral", "screen"];
8
8
  export type SPageBackground = (typeof PAGE_BACKGROUNDS)[number];
9
+ /**
10
+ * 본문 높이 모드 — 페이지가 스크롤할지, 본문이 남은 높이를 채울지.
11
+ * - auto: 콘텐츠가 흐르고, 넘치면 페이지가 스크롤한다
12
+ * - fill: 본문이 남은 높이를 정확히 채우고 페이지는 스크롤하지 않는다.
13
+ * 표가 자기 안에서 스크롤하고 페이지네이션이 하단에 고정되는 목록 화면용.
14
+ */
15
+ export declare const PAGE_CONTENT_HEIGHTS: readonly ["auto", "fill"];
16
+ export type SPageContentHeight = (typeof PAGE_CONTENT_HEIGHTS)[number];
@@ -0,0 +1,48 @@
1
+ # SSearchInput
2
+
3
+ > 자동 생성 문서 — `npm run docs:gen`. 소스: 각 컴포넌트의 Props/Handle 인터페이스 + import 의존성.
4
+
5
+ ### SSearchInput
6
+
7
+ #### Props
8
+
9
+ | Prop | Type | Default | Description |
10
+ |------|------|---------|-------------|
11
+ | `value?` | `string \| number` | — | 값 (제어) |
12
+ | `size?` | `SSearchInputSize` | `'sm'` | 크기 |
13
+ | `placeholder?` | `string` | `'결과 내 검색'` | 플레이스홀더 |
14
+ | `clearable?` | `boolean` | `false` | 지우기 버튼 — 값이 있을 때만 나타난다 |
15
+ | `disabled?` | `boolean` | `false` | 비활성 |
16
+ | `width?` | `number \| string` | — | 컨트롤 너비 (숫자=px). 미지정 시 부모 폭을 채운다 |
17
+ | `focused?` | `boolean` | — | 포커스 상태 (제어/반영) |
18
+ | `hovered?` | `boolean` | — | 호버 상태 (제어/반영) |
19
+ | `inputClass?` | `string` | — | 내부 input 요소 className |
20
+ | `inputStyle?` | `CSSProperties` | — | 내부 input 요소 style |
21
+ | `className?` | `string` | — | |
22
+ | `style?` | `CSSProperties` | — | |
23
+
24
+ #### Events
25
+
26
+ | Event | Type | Description |
27
+ |-------|------|-------------|
28
+ | `onValueChange` | `(value: string) => void` | 값 변경 — 문자열 전달 |
29
+ | `onChange` | `InputHTMLAttributes<HTMLInputElement>['onChange']` | 네이티브 onChange (form-agnostic 연동용, RHF 등) |
30
+ | `onSearch` | `(value: string) => void` | 검색 실행 — Enter 키에서 현재 값과 함께 호출된다. 한글 조합 중의 Enter(IME 확정)는 검색으로 치지 않는다. |
31
+
32
+ ## Dependencies
33
+
34
+ ### Depends on
35
+
36
+ - [SField](../SField)
37
+ - [SGhostButton](../SGhostButton)
38
+ - [SIcon](../SIcon)
39
+
40
+ ### Graph
41
+
42
+ ```mermaid
43
+ graph TD;
44
+ SSearchInput --> SField
45
+ SSearchInput --> SGhostButton
46
+ SSearchInput --> SIcon
47
+ style SSearchInput fill:#f9f,stroke:#333,stroke-width:4px
48
+ ```
@@ -0,0 +1,46 @@
1
+ import { type CSSProperties, type InputHTMLAttributes } from 'react';
2
+ import { type SFieldSize } from '../SField';
3
+ export type SSearchInputSize = SFieldSize;
4
+ export interface SSearchInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'value' | 'onChange' | 'type' | 'prefix' | 'suffix'> {
5
+ /** 값 (제어) */
6
+ value?: string | number;
7
+ /** 값 변경 — 문자열 전달 */
8
+ onValueChange?: (value: string) => void;
9
+ /** 네이티브 onChange (form-agnostic 연동용, RHF 등) */
10
+ onChange?: InputHTMLAttributes<HTMLInputElement>['onChange'];
11
+ /**
12
+ * 검색 실행 — Enter 키에서 현재 값과 함께 호출된다.
13
+ * 한글 조합 중의 Enter(IME 확정)는 검색으로 치지 않는다.
14
+ */
15
+ onSearch?: (value: string) => void;
16
+ /** 크기 */
17
+ size?: SSearchInputSize;
18
+ /** 플레이스홀더 */
19
+ placeholder?: string;
20
+ /** 지우기 버튼 — 값이 있을 때만 나타난다 */
21
+ clearable?: boolean;
22
+ /** 비활성 */
23
+ disabled?: boolean;
24
+ /** 컨트롤 너비 (숫자=px). 미지정 시 부모 폭을 채운다 */
25
+ width?: number | string;
26
+ /** 포커스 상태 (제어/반영) */
27
+ focused?: boolean;
28
+ /** 호버 상태 (제어/반영) */
29
+ hovered?: boolean;
30
+ /** 내부 input 요소 className */
31
+ inputClass?: string;
32
+ /** 내부 input 요소 style */
33
+ inputStyle?: CSSProperties;
34
+ className?: string;
35
+ style?: CSSProperties;
36
+ }
37
+ /**
38
+ * SSearchInput — 목록·결과를 검색어로 좁히는 한 줄 입력.
39
+ *
40
+ * 테두리 박스(border/radius/배경 + hover·focus 강조)는 `SField` 가 소유하고,
41
+ * 이 컴포넌트는 그 안의 돋보기 아이콘 + input 만 그린다.
42
+ * 좌측 아이콘은 **장식**이라 클릭 대상이 아니다 — 검색 실행은 Enter(`onSearch`) 다.
43
+ *
44
+ * 라벨·검증·에러 메시지가 필요한 폼 필드라면 `SInput` 을 쓴다.
45
+ */
46
+ export declare const SSearchInput: import("react").ForwardRefExoticComponent<SSearchInputProps & import("react").RefAttributes<HTMLInputElement>>;
@@ -0,0 +1 @@
1
+ export { SSearchInput, type SSearchInputProps, type SSearchInputSize } from './SSearchInput';
@@ -2,37 +2,24 @@
2
2
 
3
3
  > 자동 생성 문서 — `npm run docs:gen`. 소스: 각 컴포넌트의 Props/Handle 인터페이스 + import 의존성.
4
4
 
5
- ### SSectionHeaderCardBody
6
-
7
- #### Props
8
-
9
- | Prop | Type | Default | Description |
10
- |------|------|---------|-------------|
11
- | `children?` | `SSectionHeaderCardBodyChildren` | — | 바디 슬롯. 특정 컴포넌트 타입으로 제한하지 않습니다. |
12
- | `padding?` | `SSectionHeaderCardBodyPadding` | `'default'` | 안쪽 여백. 기본은 `default`. 성격이 다른 요소가 세 종류 이상 섞인 영역에만 `wide`, 표를 가장자리까지 채울 때만 `none`. |
13
-
14
- ### SSectionHeaderCardHeader
5
+ ### SSectionHeaderCard
15
6
 
16
7
  #### Props
17
8
 
18
9
  | Prop | Type | Default | Description |
19
10
  |------|------|---------|-------------|
20
- | `title` | `ReactNode` | — | 헤더 제목 |
21
- | `titleSize?` | `SSectionHeaderCardTitleSize` | `'xs'` | 제목 크기 |
22
- | `marker?` | `boolean` | `false` | 제목 앞 점 표시 여부 |
23
- | `required?` | `boolean` | `false` | 제목 뒤 필수 별 표시 여부 |
11
+ | `title?` | `ReactNode` | — | 헤더 제목 |
12
+ | `titleSize?` | `SSectionHeaderCardTitleSize` | — | 제목 크기 |
13
+ | `marker?` | `boolean` | — | 제목 앞 점 표시 여부 |
14
+ | `required?` | `boolean` | — | 제목 뒤 필수 별 표시 여부 |
24
15
  | `helpText?` | `string[]` | — | 도움말 툴팁 메시지 |
25
16
  | `subtitle?` | `ReactNode` | — | 부제 |
26
17
  | `slot?` | `ReactNode` | — | 헤더 우측 슬롯 |
27
- | `thickness?` | `SSectionHeaderCardThickness` | `false` | 상단 border 색상 타입. false면 표시하지 않습니다. |
28
-
29
- ### SSectionHeaderCard
30
-
31
- #### Props
32
-
33
- | Prop | Type | Default | Description |
34
- |------|------|---------|-------------|
35
- | `children?` | `SSectionHeaderCardChildren` | — | SSectionHeaderCard 슬롯. 특정 컴포넌트 타입으로 제한하지 않습니다. |
18
+ | `thickness?` | `SSectionHeaderCardThickness` | — | 상단 border 색상 타입. false면 표시하지 않습니다. |
19
+ | `headerClassName?` | `string` | — | 헤더 영역 클래스 |
20
+ | `padding?` | `SSectionHeaderCardBodyPadding` | — | 바디 안쪽 여백. 기본은 `default`. 성격이 다른 요소가 세 종류 이상 섞인 영역에만 `wide`, 표를 가장자리까지 채울 때만 `none`. |
21
+ | `background?` | `SSectionHeaderCardBodyBackground` | — | 본문 배경. 기본은 `frame` — 카드가 깐 흰 면을 그대로 쓴다. `neutral` 은 바탕을 한 단계 눌러앉혀, 흰 면 덩어리(표·리스트)가 여럿일 때 그것들이 **"면 위에 놓인 객체"로 읽히게** 한다. 위계를 한 단계 더 주고 싶을 때 고르는 선택지이며, **기본값이 틀린 것은 아니다** — 표·리스트는 테두리·라운드·헤더 줄과 간격을 이미 갖고 있어 흰 바탕에서도 경계가 읽힌다. 깔아도 **효과가 없는** 자리가 있다 — 덩어리가 가장자리까지 차는 경우(`padding="none"` 으로 표를 채우면 바탕이 완전히 가려진다), 덩어리에 회색 면이 섞인 경우(그 덩어리가 바탕에 묻힌다), 맨 텍스트나 폼 컨트롤만 있는 본문(떠오를 흰 면이 없다). |
22
+ | `children?` | `SSectionHeaderCardChildren` | — | 바디 콘텐츠. 특정 컴포넌트 타입으로 제한하지 않습니다. |
36
23
 
37
24
  ## Dependencies
38
25