sellmate-design-system-react 8.1.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 (76) hide show
  1. package/AGENTS.md +279 -124
  2. package/README.md +101 -8
  3. package/dist/components/SChipFilter/README.md +70 -0
  4. package/dist/components/SChipFilter/SChipFilter.d.ts +167 -0
  5. package/dist/components/SChipFilter/index.d.ts +1 -0
  6. package/dist/components/SCircleProgress/README.md +3 -0
  7. package/dist/components/SCircleProgress/SCircleProgress.d.ts +7 -1
  8. package/dist/components/SDatePicker/README.md +43 -3
  9. package/dist/components/SDatePicker/SDatePicker.d.ts +36 -3
  10. package/dist/components/SDatePicker/index.d.ts +1 -1
  11. package/dist/components/SDateRangePicker/README.md +21 -0
  12. package/dist/components/SDateRangePicker/SDateRangePicker.d.ts +16 -0
  13. package/dist/components/SDateRangePicker/index.d.ts +1 -1
  14. package/dist/components/SField/README.md +3 -0
  15. package/dist/components/SField/SField.d.ts +12 -0
  16. package/dist/components/SGhostButton/README.md +6 -0
  17. package/dist/components/SGnb/gnb.config.d.ts +2 -0
  18. package/dist/components/SGuide/README.md +1 -1
  19. package/dist/components/SGuide/SGuide.d.ts +1 -1
  20. package/dist/components/SIcon/README.md +6 -0
  21. package/dist/components/SIcon/icons.gen.d.ts +1 -0
  22. package/dist/components/SImage/README.md +44 -0
  23. package/dist/components/SImage/SImage.d.ts +41 -0
  24. package/dist/components/SImage/index.d.ts +1 -0
  25. package/dist/components/SKeyValueTable/README.md +1 -0
  26. package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +8 -1
  27. package/dist/components/SListItem/README.md +2 -2
  28. package/dist/components/SListItem/SListItem.d.ts +2 -2
  29. package/dist/components/SPage/README.md +23 -0
  30. package/dist/components/SPage/SPage.d.ts +27 -1
  31. package/dist/components/SPage/SPageHeader.d.ts +32 -0
  32. package/dist/components/SPage/index.d.ts +2 -1
  33. package/dist/components/SPage/page.config.d.ts +8 -0
  34. package/dist/components/SPortal/README.md +1 -1
  35. package/dist/components/SPortal/SPortal.d.ts +7 -1
  36. package/dist/components/SRadio/README.md +2 -0
  37. package/dist/components/SRadioButton/README.md +13 -0
  38. package/dist/components/SSearchInput/README.md +48 -0
  39. package/dist/components/SSearchInput/SSearchInput.d.ts +46 -0
  40. package/dist/components/SSearchInput/index.d.ts +1 -0
  41. package/dist/components/SSectionHeaderCard/README.md +10 -23
  42. package/dist/components/SSectionHeaderCard/SSectionHeaderCard.d.ts +21 -14
  43. package/dist/components/SSectionHeaderCard/index.d.ts +1 -1
  44. package/dist/components/SSelect/README.md +4 -2
  45. package/dist/components/SSelect/SSelect.d.ts +2 -2
  46. package/dist/components/STable/README.md +1 -0
  47. package/dist/components/STable/STable.d.ts +20 -0
  48. package/dist/components/STabs/README.md +0 -1
  49. package/dist/components/STabs/STabs.d.ts +2 -4
  50. package/dist/components/STabs/index.d.ts +1 -1
  51. package/dist/components/STabs/tabs.config.d.ts +3 -4
  52. package/dist/components/STag/README.md +2 -0
  53. package/dist/components/STextLink/README.md +2 -0
  54. package/dist/components/STimePicker/timepicker.config.d.ts +5 -0
  55. package/dist/components/SToggle/README.md +1 -0
  56. package/dist/components/SToggle/SToggle.d.ts +4 -1
  57. package/dist/components/STooltip/README.md +2 -0
  58. package/dist/components/STree/README.md +3 -0
  59. package/dist/components/STree/STree.d.ts +8 -0
  60. package/dist/components/STree/index.d.ts +1 -1
  61. package/dist/index.cjs +2988 -393
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.d.ts +3 -0
  64. package/dist/index.js +2981 -394
  65. package/dist/index.js.map +1 -1
  66. package/dist/lib/floating-width.d.ts +22 -0
  67. package/dist/lib/truncated-value-tooltip.d.ts +18 -0
  68. package/dist/llms-full.txt +545 -152
  69. package/dist/llms.txt +283 -127
  70. package/dist/styles.css +397 -36
  71. package/dist/theme.css +34 -11
  72. package/eslint/index.mjs +5 -0
  73. package/eslint/rules/field-width-grade.d.mts +41 -0
  74. package/eslint/rules/field-width-grade.mjs +294 -0
  75. package/eslint/scale.gen.mjs +1 -1
  76. package/package.json +7 -4
package/README.md CHANGED
@@ -11,8 +11,11 @@ Sellmate 디자인 시스템의 React 컴포넌트 라이브러리 (React + Type
11
11
 
12
12
  ## 설치
13
13
 
14
+ > ⚠️ **이 패키지는 현재 베타입니다.** `beta` dist-tag 로만 배포되므로 태그를 붙여 설치해야 합니다.
15
+ > 태그 없이 설치하면 마지막 정식 버전(8.x)이 잡힙니다. 자세한 정책은 [버전 정책](#버전-정책) 참조.
16
+
14
17
  ```bash
15
- npm install sellmate-design-system-react
18
+ npm install sellmate-design-system-react@beta
16
19
  npx sellmate-ds init
17
20
  ```
18
21
 
@@ -183,6 +186,7 @@ export default [
183
186
  | `sellmate/component-group-gap` | warn | 같은 컴포넌트를 나열할 때의 그룹 간격 — 배열 방향에 따라 값이 다르다(체크박스 가로 24 / 세로 8) |
184
187
  | `sellmate/table-numeric-align` | warn | 수량 컬럼(금액·수량 등)에 `align: 'right'` 누락 — **`--fix` 로 자동 교정** |
185
188
  | `sellmate/require-locale-number` | warn | 수량 컬럼의 `toLocaleString()` 누락 — 세 자리 콤마 |
189
+ | `sellmate/field-width-grade` | warn | 필드 폭이 `maxLength`(스키마 상한)와 어긋남 — 등급 미지정 · 등급 밖 폭 · 상한 대비 과부족 |
186
190
  | `sellmate/no-arbitrary-class` | **off** | 토큰이 있는 속성(색·타이포·간격·모서리)의 임의 값 — `text-[14px]`, `bg-[#eee]`. 앱 고유 화면에는 정당한 사용이 많아 기본값은 끕니다 |
187
191
 
188
192
  `className` 뿐 아니라 `cn()`/`clsx()` 인자, 템플릿 리터럴, 객체 키 안까지 검사합니다.
@@ -234,6 +238,68 @@ export default [
234
238
  'sellmate/table-numeric-align': ['error', { allow: ['rank'] }],
235
239
  ```
236
240
 
241
+ ### 필드 폭 등급 (`field-width-grade`)
242
+
243
+ 필드 너비는 **`maxLength`(= 스키마 상한)로 정합니다.** 상한이 등급 안에 들어오면 그 등급으로 고정하고,
244
+ 등급 상한(`xl`)을 넘거나 상한이 아예 없으면 행 전체(`width="100%"` 또는 생략)로 둡니다.
245
+
246
+ | 등급 | 폭 | |
247
+ | ---- | ----- | ------------------------ |
248
+ | `xs` | 80px | 숫자 필드 전용 |
249
+ | `sm` | 120px | |
250
+ | `md` | 160px | |
251
+ | `lg` | 240px | |
252
+ | `xl` | 480px | 정책상 상한 |
253
+
254
+ ```tsx
255
+ // 상한이 등급 안에 들어온다 → 그 등급으로 고정
256
+ <SInput name="code" label="코드" maxLength={10} width={160} />
257
+
258
+ // 상한이 xl 로도 안 담긴다 → 행 전체
259
+ <SInput name="desc" label="설명" maxLength={100} width="100%" />
260
+
261
+ // 숫자 필드의 상한은 maxLength 가 아니라 max 다 (천단위 콤마도 폭을 먹는다)
262
+ <SNumberInput name="qty" label="수량" max={99} width={80} />
263
+ ```
264
+
265
+ 대상은 `SInput` · `SNumberInput` · `SBarcodeInput` 입니다. `STextarea` 는 여러 줄로 접혀 상한이 폭을
266
+ 정하지 않고, 셀렉트 계열은 상한 개념이 없어 목록 최장값으로 폭을 정하며, 날짜·시간 계열은 컴포넌트가
267
+ 자체 상한을 갖습니다.
268
+
269
+ **상한도 폭도 변수로 넘기면 검사하지 않습니다.** 정적으로 알 수 없는 것을 위반으로 보고하지 않습니다.
270
+
271
+ ```tsx
272
+ <SInput maxLength={LIMIT} width={fieldWidth} /> // 통과
273
+ <SInput maxLength={10} {...rest} /> // 통과 (spread 안에 width 가 있을 수 있다)
274
+ ```
275
+
276
+ #### 글자수 환산
277
+
278
+ 등급이 몇 글자를 담는지는 토큰 값(글꼴 크기 · 좌우 패딩 · 테두리 · 스테퍼)에서 계산합니다.
279
+ 한글은 전각이라 영숫자의 약 두 배를 먹으므로 **두 기준 사이에는 아무것도 보고하지 않습니다** —
280
+ 영숫자로 채워도 넘칠 때만 "좁다", 한글로 채워도 남을 때만 "넓다" 로 판정합니다.
281
+
282
+ | 등급 | `SInput` (sm) | `SInput` (md) | `SNumberInput` (sm) | `SNumberInput` (sm, `useButton`) |
283
+ | ---- | ------------- | ------------- | ------------------- | -------------------------------- |
284
+ | `xs` | — | — | 영숫자 8 | 영숫자 2 |
285
+ | `sm` | 영숫자 14 / 한글 7 | 영숫자 11 / 한글 6 | 영숫자 14 | 영숫자 8 |
286
+ | `md` | 영숫자 20 / 한글 11 | 영숫자 16 / 한글 9 | 영숫자 20 | 영숫자 14 |
287
+ | `lg` | 영숫자 32 / 한글 17 | 영숫자 26 / 한글 14 | 영숫자 32 | 영숫자 26 |
288
+ | `xl` | 영숫자 68 / 한글 37 | 영숫자 57 / 한글 31 | 영숫자 68 | 영숫자 62 |
289
+
290
+ `SNumberInput` 은 `useButton` 여부로 글자 자리가 크게 갈립니다 — 스테퍼가 없으면 좌우 패딩이
291
+ 두 배가 되고(기본값), 있으면 버튼 두 개와 간격이 폭을 먹습니다. 규칙은 JSX 의 `useButton` 을 읽어
292
+ 둘을 구분합니다.
293
+
294
+ 값이 팀 기준과 다르면 옵션으로 덮습니다.
295
+
296
+ ```js
297
+ 'sellmate/field-width-grade': ['warn', {
298
+ grades: { sm: 120, md: 160, lg: 240, xl: 480 },
299
+ charRatio: { narrow: 0.55, wide: 1 },
300
+ }],
301
+ ```
302
+
237
303
  ### 더 엄격하게 / 더 느슨하게
238
304
 
239
305
  `configs.strict` 는 전 규칙을 error 로 올리고, `<ul>` `<ol>` `<li>` `<svg>` `<label>` 까지 검사하며, 간격 유틸리티에 `sd-` 접두를 강제합니다(`requirePrefix`). 디자인 시스템 규칙을 처음부터 전면 적용하는 신규 프로젝트용입니다.
@@ -317,25 +383,52 @@ export default [...sellmate.configs.strict];
317
383
  - **단일 라이트 테마** — 다크모드는 지원하지 않습니다.
318
384
  - **타입 포함** — 모든 컴포넌트에 TypeScript 타입 정의(`.d.ts`)가 함께 제공됩니다.
319
385
 
386
+ ## 버전 정책
387
+
388
+ **현재 베타 단계입니다.** 컴포넌트 API 가 아직 자리를 잡는 중이라 `9.0.0-beta.N` 으로 나가고, `beta` dist-tag 로만 배포합니다.
389
+
390
+ - 베타 기간에는 breaking 이 또 나와도 `beta.N` 만 올라갑니다. 아직 아무도 `9.0.0` 을 받지 않았으므로 major 를 올릴 이유가 없습니다.
391
+ - 프리릴리스는 `^8` 같은 캐럿 범위에 절대 걸리지 않습니다. 기존 소비 앱이 조용히 깨지지 않습니다.
392
+ - 소비 앱은 `sellmate-design-system-react@beta` 로 명시적으로 받아야 합니다.
393
+
394
+ ### 정식 9.0.0 으로 언제 전환하나
395
+
396
+ 날짜가 아니라 상태로 판단합니다. 셋을 모두 만족할 때 전환합니다.
397
+
398
+ 1. **2주 연속 BREAKING 커밋 0** — 지금 major 를 만드는 건 전부 컴포넌트 API 재설계입니다. 이게 멎은 것이 API 가 자리 잡았다는 유일한 실증입니다.
399
+ 2. **소비 앱이 이 패키지만으로 프로덕션 화면을 다 그릴 수 있을 때** — `AGENTS.md` §0-1 인덱스에 없어서 소비 앱이 직접 만든 컴포넌트가 남아 있으면, 그게 나중에 들어오면서 또 API 를 흔듭니다.
400
+ 3. **토큰 스킴이 값만 바뀌는 단계일 때** — 토큰 JSON 의 키 구조가 바뀌는 동안은 `theme.css` 재생성이 breaking 을 계속 만듭니다.
401
+
402
+ 전환할 때 할 일은 두 가지입니다. `npm run version:stable -- --release-as 9.0.0` 으로 꼬리를 떼고, **`package.json` 의 `publishConfig.tag` 를 지웁니다**(= `latest`). 둘 중 하나만 하면 `prepublishOnly` 가드가 배포를 막습니다.
403
+
404
+ 정식 전환 후 major 인플레를 막는 실제 레버는 번호 체계가 아니라 **릴리스 묶음**입니다. breaking 을 나올 때마다 즉시 내지 말고 정해진 주기(격주·월 1회)에 모아서 내면 같은 변경량이 major 한 번으로 압축됩니다.
405
+
320
406
  ## 버전 업 / 릴리스
321
407
 
322
408
  Stencil 쪽 `lerna version` 과 동일하게 **Conventional Commits 기반**으로 버전을 올리고 `CHANGELOG.md` 를 누적합니다. 이 패키지는 lerna 관리 대상이 아니라 전용 스크립트를 씁니다.
323
409
 
324
410
  ```bash
325
- # 마지막 릴리스 이후 커밋으로 상승 폭을 자동 추론 → package.json/CHANGELOG 갱신 + 릴리스 커밋
326
- npm run version
411
+ # 베타 이어가기 상승 자동 추론 → package.json/CHANGELOG 갱신 + 릴리스 커밋
412
+ npm run version # 9.0.0-beta.0 → 9.0.0-beta.1
327
413
 
328
414
  # 실제로 바꾸지 않고 결과만 미리보기
329
415
  npm run version:dry
330
416
 
331
- # 루트에서도 실행 가능
332
- npm run version:rn # (design-system 루트)
417
+ # 정식 채널용 (베타 졸업 후에 씁니다)
418
+ npm run version:stable
419
+ npm run version:stable:dry
420
+
421
+ # 루트에서도 실행 가능 (design-system 루트)
422
+ npm run version:rn
423
+ npm run version:rn:stable
333
424
  ```
334
425
 
335
426
  - 마지막 `chore(release): react-native <ver>` 커밋 이후 `react-native/` 를 건드린 커밋을 모읍니다.
336
- - `BREAKING CHANGE → major`, `feat → minor`, 그 외(`fix` 등) `→ patch` 로 버전을 올립니다.
337
- - 주요 옵션: `--bump <major|minor|patch>` · `--release-as <x.y.z>` · `--pre-major`(0.x 유지) · `--tag` · `--no-commit` · `--dry-run` · `--force` (`node scripts/version.mjs --help`).
338
- - push하지 않습니다. 커밋/태그 확인 직접 push 하세요.
427
+ - `BREAKING CHANGE → major`, `feat → minor`, 그 외(`fix` 등) `→ patch` 로 버전을 올립니다. `--prerelease` 를 주면 이 상승 폭은 **정식 버전이 아직 없을 때만** core 에 반영됩니다(8.1.0 → 9.0.0-beta.0). 이미 프리릴리스면 `beta.N` 만 올라갑니다.
428
+ - 현재 버전이 프리릴리스인데 `--prerelease` `--release-as` 없으면 스크립트가 막습니다 베타를 실수로 정식으로 올리는 사고 방지입니다.
429
+ - **git 태그(`sellmate-design-system-react@<ver>`)npm scripts `--tag` 기본으로 주므로 자동으로 붙습니다.** 건너뛰려면 `npm run version -- --no-tag`.
430
+ - 주요 옵션: `--bump <major|minor|patch>` · `--release-as <x.y.z>`(프리릴리스 꼬리 허용) · `--prerelease [id]` · `--pre-major`(0.x 유지) · `--tag` / `--no-tag` · `--no-commit` · `--dry-run` · `--force` (`node scripts/version.mjs --help`).
431
+ - push 는 하지 않습니다. 커밋/태그 확인 후 직접 push 하세요 — 태그는 `git push origin <태그명>` 으로 따로 올려야 합니다.
339
432
 
340
433
  ## 라이선스
341
434
 
@@ -0,0 +1,70 @@
1
+ # SChipFilter
2
+
3
+ > 자동 생성 문서 — `npm run docs:gen`. 소스: 각 컴포넌트의 Props/Handle 인터페이스 + import 의존성.
4
+
5
+ ### SChipFilter
6
+
7
+ #### Props
8
+
9
+ | Prop | Type | Default | Description |
10
+ |------|------|---------|-------------|
11
+ | `fields?` | `SChipFilterField[] \| SChipFilterGroup[]` | — | 필터 정의 목록. 그룹으로 묶으려면 SChipFilterGroup[]을 넘긴다 — 그룹이 시작될 때마다 앞에 구분선이 자동으로 붙는다(showLabel·인접 그룹·인라인 date 필터와 중첩되지 않도록 처리됨). |
12
+ | `value?` | `SChipFilterValueMap` | — | 필터 값 맵 |
13
+ | `activeKeys?` | `string[]` | — | 노출 필터 key 목록. 지정하면 제어 컴포넌트로 동작 — "필터 추가"로 고른 필드를 이 배열에 직접 넣어줘야 칩이 나타난다(onActiveKeysChange에서 받은 keys로 갱신). 지정하지 않으면 필드별 defaultActive 값을 기준으로 컴포넌트가 내부 상태로 관리하는 비제어 방식으로 동작한다 |
14
+ | `label?` | `string` | `'검색 필터'` | 좌측 태그 텍스트 |
15
+ | `showLabel?` | `boolean` | `false` | 좌측 태그(label)·구분선 표시 여부 |
16
+ | `showReset?` | `boolean` | `true` | 검색 초기화 링크 표시 여부 |
17
+ | `disabled?` | `boolean` | `false` | 바 비활성 상태 |
18
+ | `className?` | `string` | — | |
19
+ | `style?` | `CSSProperties` | — | |
20
+
21
+ #### Events
22
+
23
+ | Event | Type | Description |
24
+ |-------|------|-------------|
25
+ | `onValueChange` | `(value: SChipFilterValueMap) => void` | 전체 값 변경 — 편집 중인 값이 바뀔 때마다(선택할 때마다) 호출된다. 실제 검색 실행은 onSearch를 쓴다 |
26
+ | `onFilterChange` | `(detail: SChipFilterChangeDetail) => void` | 개별 필터 값 변경 |
27
+ | `onSearch` | `(value: SChipFilterValueMap) => void` | 실제 검색을 실행할 시점 — 편집 팝오버의 "검색" 버튼을 누르거나 팝오버가 닫힐 때(바깥 클릭·Esc·다른 칩으로 전환 포함) 그 시점의 전체 값 맵과 함께 호출된다. 팝오버가 없는 필드(인라인 date 프리셋·custom, clearable ×, 검색 초기화)는 값이 바뀌는 즉시 호출된다. dirty 체크가 기본 적용되어 있어 — 마지막으로 실제 검색이 실행된 값 맵과 비교해 하나라도 달라진 게 없으면(예: 팝오버를 열었다 아무것도 안 바꾸고 닫는 경우) 호출되지 않는다. fields를 그룹으로 넘겼다면 rule을 만족하지 못한 그룹이 있는 동안엔 onSearch가 호출되지 않는다 — 해당 그룹의 경고 툴팁은 이 시점과 무관하게 값이 비어 있는 동안 항상 실시간으로 떠 있다(별도로 validate()를 호출할 필요 없음) |
28
+ | `onActiveKeysChange` | `(keys: string[]) => void` | 노출 필터 key 변경(칩 추가·제거) — 비제어 방식에서도 참고용으로 호출된다. activeKeys를 직접 제어할 때는 이 값을 그대로 activeKeys에 반영해야 한다 |
29
+ | `onReset` | `() => void` | "검색 초기화" 클릭 — 모든 필드가 기본값(또는 null)으로 리셋된 뒤 호출된다 |
30
+ | `onAddFilter` | `(key: string) => void` | "필터 추가" 목록에서 항목을 골랐을 때 — activeKeys를 직접 제어 중이면 이 콜백에서 (또는 onActiveKeysChange에서) key를 activeKeys에 추가해줘야 칩이 실제로 나타난다. activeKeys를 넘기지 않았다면(비제어) 별도 처리 없이도 컴포넌트가 알아서 칩을 노출한다 |
31
+
32
+ #### Methods (ref)
33
+
34
+ | Method | Type | Description |
35
+ |--------|------|-------------|
36
+ | `open` | `(key: string) => void` | 특정 필터 편집 팝오버를 엽니다. |
37
+ | `reset` | `() => void` | 모든 필터 값을 초기화합니다. |
38
+ | `validate` | `() => boolean` | fields를 그룹(SChipFilterGroup[])으로 넘겼을 때, 현재 값 기준으로 각 그룹의 rule을 만족하는지 반환합니다. 경고 툴팁은 이 호출과 무관하게 rule 위반 상태인 동안 항상 실시간으로 떠 있으므로, 이 메서드는 그 상태를 그대로 읽어오는 용도다(예: 검색 버튼을 눌러도 되는지 사전 확인) |
39
+
40
+ ## Dependencies
41
+
42
+ ### Depends on
43
+
44
+ - [SDatePicker](../SDatePicker)
45
+ - [SDateRangePicker](../SDateRangePicker)
46
+ - [SGhostButton](../SGhostButton)
47
+ - [SIcon](../SIcon)
48
+ - [SRadio](../SRadio)
49
+ - [SRadioButton](../SRadioButton)
50
+ - [SSelect](../SSelect)
51
+ - [STag](../STag)
52
+ - [STextLink](../STextLink)
53
+ - [STooltip](../STooltip)
54
+
55
+ ### Graph
56
+
57
+ ```mermaid
58
+ graph TD;
59
+ SChipFilter --> SDatePicker
60
+ SChipFilter --> SDateRangePicker
61
+ SChipFilter --> SGhostButton
62
+ SChipFilter --> SIcon
63
+ SChipFilter --> SRadio
64
+ SChipFilter --> SRadioButton
65
+ SChipFilter --> SSelect
66
+ SChipFilter --> STag
67
+ SChipFilter --> STextLink
68
+ SChipFilter --> STooltip
69
+ style SChipFilter fill:#f9f,stroke:#333,stroke-width:4px
70
+ ```
@@ -0,0 +1,167 @@
1
+ import { type CSSProperties, type ReactNode } from 'react';
2
+ import { type SDateRangeValue } from '../SDateRangePicker';
3
+ export type SChipFilterType = 'single' | 'multi' | 'keyword' | 'date' | 'period' | 'custom';
4
+ export type SChipFilterOptionValue = string | number;
5
+ export type SChipFilterMatchMode = 'contains' | 'exact' | 'excludes';
6
+ export type SChipFilterPeriodUnit = 'day' | 'month' | 'quarter' | 'half' | 'year' | 'custom';
7
+ export interface SChipFilterOption {
8
+ value: SChipFilterOptionValue;
9
+ label: string;
10
+ disabled?: boolean;
11
+ }
12
+ /** date/period 필드의 프리셋 라디오 항목 (오늘/지난 7일/일별/월별/사용자 지정 등) */
13
+ export interface SChipFilterDatePreset {
14
+ /** 프리셋 식별자 */
15
+ value: string;
16
+ /** 라벨 */
17
+ label: string;
18
+ /** true면 "사용자 지정" — 선택 시 날짜/기간 피커가 추가로 노출된다. resolve는 무시된다. */
19
+ custom?: boolean;
20
+ /** custom이 아닐 때 실제 값을 계산한다. 단일 날짜(string) 또는 기간([start,end]) 모두 가능 */
21
+ resolve?: () => string | SDateRangeValue;
22
+ }
23
+ /** keyword 필드에서 matchModes 활성 시 사용하는 값 형태 — 입력해 추가한 키워드 목록 */
24
+ export interface SChipFilterKeywordValue {
25
+ keywords: string[];
26
+ mode: SChipFilterMatchMode;
27
+ }
28
+ /** period 필드 값 — 선택 단위(unit)와 그 단위의 입력값(value)을 함께 보관한다 */
29
+ export interface SChipFilterPeriodValue {
30
+ unit: SChipFilterPeriodUnit;
31
+ value?: string | number | SDateRangeValue | null;
32
+ }
33
+ /** custom 필드가 자유롭게 담는 값. 형태를 강제하지 않는다 — render에서 직접 정의한 그대로 읽고 쓴다 */
34
+ export type SChipFilterCustomValue = Record<string, unknown>;
35
+ export type SChipFilterValue = SChipFilterOptionValue | SChipFilterOptionValue[] | SDateRangeValue | SChipFilterKeywordValue | SChipFilterPeriodValue | SChipFilterCustomValue | null | undefined;
36
+ export type SChipFilterValueMap = Record<string, SChipFilterValue>;
37
+ export interface SChipFilterField {
38
+ /** 필터 식별자 */
39
+ key: string;
40
+ /** 칩에 표시할 레이블 */
41
+ label: string;
42
+ /** 필터 타입 */
43
+ type: SChipFilterType;
44
+ /** single/multi/keyword 후보 목록 */
45
+ options?: SChipFilterOption[];
46
+ /** 필수 필터 표시. true면 값이 비어 있을 때 기본값(defaultValue 또는 타입별 내장 기본값)이
47
+ * 자동으로 채워지고, clearable은 현재 값이 기본값과 같을 땐 숨겨지며 클릭 시 기본값으로 되돌아간다 */
48
+ required?: boolean;
49
+ /** 고정 필터. true면 activeKeys/defaultActive와 무관하게 항상 노출되고 "필터 추가" 목록에는 나타나지 않는다 */
50
+ fix?: boolean;
51
+ /** 초기값 및 clearable 클릭 시 되돌아갈 값. required 여부와 무관하게 적용된다 — 값이 비어 있으면
52
+ * 마운트(또는 "필터 추가"로 활성화) 시 이 값이 자동으로 채워진다. required인데 지정하지 않으면
53
+ * 타입별 내장 기본값(single: 첫 번째 옵션, date: 오늘 날짜)을 대신 쓴다 */
54
+ defaultValue?: SChipFilterValue;
55
+ /** 경고 테두리 표시 */
56
+ warning?: boolean;
57
+ /** 비활성 상태 */
58
+ disabled?: boolean;
59
+ /** 처음부터 칩으로 노출할지 여부. false면 "필터 추가" 목록에만 나타나고, 거기서 고르기 전까지는
60
+ * 필터 바에 보이지 않는다. activeKeys를 직접 제어하는 경우엔 초기 activeKeys 구성에만 참고되고
61
+ * 이후엔 activeKeys가 우선한다 */
62
+ defaultActive?: boolean;
63
+ /** keyword 입력 placeholder */
64
+ placeholder?: string;
65
+ /** keyword 필드에 검색조건(포함/일치) 토글 표시 여부 */
66
+ matchModes?: boolean;
67
+ /** matchModes 활성 시 "미포함"까지 포함해 3개(포함/일치/미포함)로 노출할지. 기본 false — 기존처럼 2개(포함/일치)만 */
68
+ excludeMode?: boolean;
69
+ /** date 선택 가능 범위 */
70
+ selectable?: [string, string];
71
+ /** date 프리셋의 "사용자 지정" 기간 선택 시 최대 선택 일수 */
72
+ maxRange?: number;
73
+ /** date/period 필드의 프리셋 라디오 목록. date에서 지정하지 않으면 기존처럼 단일 캘린더 트리거로 동작하고,
74
+ * period에서 지정하지 않으면 일별·월별·분기별·반기별·연도별·사용자 지정 기본 목록을 쓴다 */
75
+ presets?: SChipFilterDatePreset[];
76
+ /** presets 사용 시 UI 형태 — true: 필터 바에 세그먼트 라디오로 인라인 노출(팝오버 없음),
77
+ * false(기본): 칩 클릭 시 팝오버 안에 세로 라디오 목록(+사용자 지정 선택 시 기간 피커) */
78
+ radioButton?: boolean;
79
+ /** type이 'custom'일 때 필터 바에 이 필드 자리에 놓일 노드를 직접 그린다. 칩+팝오버를 거치지 않고
80
+ * 반환한 노드가 그대로 바에 노출된다 — SSelect를 그대로 놓거나 SInput을 바로 노출하는 식으로
81
+ * 렌더 방식 자체를 완전히 자유롭게 구성한다. */
82
+ render?: (ctx: {
83
+ value: SChipFilterValue;
84
+ disabled?: boolean;
85
+ warning?: boolean;
86
+ onValueChange: (value: SChipFilterValue) => void;
87
+ }) => ReactNode;
88
+ }
89
+ export interface SChipFilterChangeDetail {
90
+ key: string;
91
+ value: SChipFilterValue;
92
+ values: SChipFilterValueMap;
93
+ }
94
+ /** 필터 그룹 검증 규칙 */
95
+ export type SChipFilterGroupRule = {
96
+ type: 'requireKey';
97
+ key: string;
98
+ } | {
99
+ type: 'requireAll';
100
+ } | {
101
+ type: 'requireAny';
102
+ dataGroupName?: string;
103
+ };
104
+ /** 필터를 그룹으로 묶어서 넘길 때의 단위. 그룹이 시작될 때마다 앞에 구분선이 붙는다. */
105
+ export interface SChipFilterGroup {
106
+ fields: SChipFilterField[];
107
+ /** 지정하면 이 규칙으로 그룹을 검증한다. values가 바뀔 때마다 즉시 재평가되는 실시간 검증이라 —
108
+ * 그룹이 rule을 만족하지 못하면 검색 시도 여부와 무관하게 그 즉시 그룹 중앙에 경고 툴팁이 뜬다.
109
+ * 지정 안 하면 검증하지 않는다. */
110
+ rule?: SChipFilterGroupRule;
111
+ /** rule을 만족하지 않을 때 그룹 중앙에 띄울 툴팁 메시지. 지정 안 하면 rule 종류에 따른 기본 문구를 쓴다 */
112
+ tooltipMessage?: string;
113
+ }
114
+ export interface SChipFilterHandle {
115
+ /** 특정 필터 편집 팝오버를 엽니다. */
116
+ open: (key: string) => void;
117
+ /** 모든 필터 값을 초기화합니다. */
118
+ reset: () => void;
119
+ /** fields를 그룹(SChipFilterGroup[])으로 넘겼을 때, 현재 값 기준으로 각 그룹의 rule을 만족하는지
120
+ * 반환합니다. 경고 툴팁은 이 호출과 무관하게 rule 위반 상태인 동안 항상 실시간으로 떠 있으므로,
121
+ * 이 메서드는 그 상태를 그대로 읽어오는 용도다(예: 검색 버튼을 눌러도 되는지 사전 확인) */
122
+ validate: () => boolean;
123
+ }
124
+ export interface SChipFilterProps {
125
+ /** 필터 정의 목록. 그룹으로 묶으려면 SChipFilterGroup[]을 넘긴다 — 그룹이 시작될 때마다 앞에
126
+ * 구분선이 자동으로 붙는다(showLabel·인접 그룹·인라인 date 필터와 중첩되지 않도록 처리됨). */
127
+ fields?: SChipFilterField[] | SChipFilterGroup[];
128
+ /** 필터 값 맵 */
129
+ value?: SChipFilterValueMap;
130
+ /** 전체 값 변경 — 편집 중인 값이 바뀔 때마다(선택할 때마다) 호출된다. 실제 검색 실행은 onSearch를 쓴다 */
131
+ onValueChange?: (value: SChipFilterValueMap) => void;
132
+ /** 개별 필터 값 변경 */
133
+ onFilterChange?: (detail: SChipFilterChangeDetail) => void;
134
+ /** 실제 검색을 실행할 시점 — 편집 팝오버의 "검색" 버튼을 누르거나 팝오버가 닫힐 때(바깥 클릭·Esc·다른
135
+ * 칩으로 전환 포함) 그 시점의 전체 값 맵과 함께 호출된다. 팝오버가 없는 필드(인라인 date 프리셋·custom,
136
+ * clearable ×, 검색 초기화)는 값이 바뀌는 즉시 호출된다. dirty 체크가 기본 적용되어 있어 — 마지막으로
137
+ * 실제 검색이 실행된 값 맵과 비교해 하나라도 달라진 게 없으면(예: 팝오버를 열었다 아무것도 안 바꾸고
138
+ * 닫는 경우) 호출되지 않는다. fields를 그룹으로 넘겼다면 rule을 만족하지 못한 그룹이 있는 동안엔
139
+ * onSearch가 호출되지 않는다 — 해당 그룹의 경고 툴팁은 이 시점과 무관하게 값이 비어 있는 동안 항상
140
+ * 실시간으로 떠 있다(별도로 validate()를 호출할 필요 없음) */
141
+ onSearch?: (value: SChipFilterValueMap) => void;
142
+ /** 노출 필터 key 목록. 지정하면 제어 컴포넌트로 동작 — "필터 추가"로 고른 필드를 이 배열에 직접
143
+ * 넣어줘야 칩이 나타난다(onActiveKeysChange에서 받은 keys로 갱신). 지정하지 않으면 필드별
144
+ * defaultActive 값을 기준으로 컴포넌트가 내부 상태로 관리하는 비제어 방식으로 동작한다 */
145
+ activeKeys?: string[];
146
+ /** 노출 필터 key 변경(칩 추가·제거) — 비제어 방식에서도 참고용으로 호출된다.
147
+ * activeKeys를 직접 제어할 때는 이 값을 그대로 activeKeys에 반영해야 한다 */
148
+ onActiveKeysChange?: (keys: string[]) => void;
149
+ /** "검색 초기화" 클릭 — 모든 필드가 기본값(또는 null)으로 리셋된 뒤 호출된다 */
150
+ onReset?: () => void;
151
+ /** "필터 추가" 목록에서 항목을 골랐을 때 — activeKeys를 직접 제어 중이면 이 콜백에서
152
+ * (또는 onActiveKeysChange에서) key를 activeKeys에 추가해줘야 칩이 실제로 나타난다.
153
+ * activeKeys를 넘기지 않았다면(비제어) 별도 처리 없이도 컴포넌트가 알아서 칩을 노출한다 */
154
+ onAddFilter?: (key: string) => void;
155
+ /** 좌측 태그 텍스트 */
156
+ label?: string;
157
+ /** 좌측 태그(label)·구분선 표시 여부 */
158
+ showLabel?: boolean;
159
+ /** 검색 초기화 링크 표시 여부 */
160
+ showReset?: boolean;
161
+ /** 바 비활성 상태 */
162
+ disabled?: boolean;
163
+ className?: string;
164
+ style?: CSSProperties;
165
+ }
166
+ /** SChipFilter — 검색 필터를 칩 바 형태로 구성하는 컴포넌트. */
167
+ export declare const SChipFilter: import("react").ForwardRefExoticComponent<SChipFilterProps & import("react").RefAttributes<SChipFilterHandle>>;
@@ -0,0 +1 @@
1
+ export { SChipFilter, type SChipFilterChangeDetail, type SChipFilterDatePreset, type SChipFilterField, type SChipFilterGroup, type SChipFilterGroupRule, type SChipFilterHandle, type SChipFilterKeywordValue, type SChipFilterMatchMode, type SChipFilterOption, type SChipFilterOptionValue, type SChipFilterProps, type SChipFilterType, type SChipFilterValue, type SChipFilterValueMap, } from './SChipFilter';
@@ -11,6 +11,7 @@
11
11
  | `value?` | `number` | `0` | 진행률 (0–100) |
12
12
  | `type?` | `SCircleProgressType` | `'primary'` | 색상 테마 |
13
13
  | `indeterminate?` | `boolean` | `false` | 불확정(스피너) 모드 — value 무시 |
14
+ | `size?` | `number \| string` | `DEFAULT_SIZE` | 링의 지름. 숫자는 px 로 해석한다. 부모 크기에 비례시키려면 컨테이너 쿼리 단위(`'45cqh'`)를 쓴다 — 퍼센트는 부모가 inline-flex 라 기준 폭이 정해지지 않아 해석되지 않는다. |
14
15
  | `label?` | `string` | — | 하단 레이블 |
15
16
  | `innerValue?` | `boolean` | `false` | true면 퍼센트를 원 아래가 아닌 원 가운데에 표시 |
16
17
  | `className?` | `string` | — | |
@@ -20,6 +21,7 @@
20
21
 
21
22
  ### Used by
22
23
 
24
+ - [SImage](../SImage)
23
25
  - [SLoadingContainer](../SLoadingContainer)
24
26
  - [SLoadingModal](../SLoadingModal)
25
27
  - [STable](../STable)
@@ -28,6 +30,7 @@
28
30
 
29
31
  ```mermaid
30
32
  graph TD;
33
+ SImage --> SCircleProgress
31
34
  SLoadingContainer --> SCircleProgress
32
35
  SLoadingModal --> SCircleProgress
33
36
  STable --> SCircleProgress
@@ -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,13 +55,32 @@
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
44
82
 
83
+ - [SChipFilter](../SChipFilter)
45
84
  - [SKeyValueTable](../SKeyValueTable)
46
85
 
47
86
  ### Depends on
@@ -57,6 +96,7 @@ graph TD;
57
96
  SDatePicker --> SCalendar
58
97
  SDatePicker --> SField
59
98
  SDatePicker --> SIcon
99
+ SChipFilter --> SDatePicker
60
100
  SKeyValueTable --> SDatePicker
61
101
  style SDatePicker fill:#f9f,stroke:#333,stroke-width:4px
62
102
  ```
@@ -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';
@@ -40,10 +40,30 @@
40
40
  | `onValueChange` | `(range: SDateRangeValue) => void` | 선택 변경 (sdUpdate) — [start, end] |
41
41
  | `onViewChange` | `(view: { year: number; month: number }) => void` | 보이는 연·월 변경 (sdViewChange) |
42
42
 
43
+ ### SRangeCalendar
44
+
45
+ #### Props
46
+
47
+ | Prop | Type | Default | Description |
48
+ |------|------|---------|-------------|
49
+ | `value` | `SDateRangeValue` | — | |
50
+ | `selectable?` | `[string, string]` | — | |
51
+ | `maxRange?` | `number` | — | |
52
+ | `useTimePicker?` | `boolean` | `false` | |
53
+
54
+ #### Events
55
+
56
+ | Event | Type | Description |
57
+ |-------|------|-------------|
58
+ | `onSelect` | `(r: [string, string]) => void` | |
59
+ | `onPendingStartChange` | `(start: string \| null) => void` | 시작일만 선택된(종료일 대기) 상태를 상위로 전달 — 트리거에 `start ~` 프리뷰 표시용 |
60
+ | `onViewChange` | `(view: { year: number; month: number }) => void` | |
61
+
43
62
  ## Dependencies
44
63
 
45
64
  ### Used by
46
65
 
66
+ - [SChipFilter](../SChipFilter)
47
67
  - [SKeyValueTable](../SKeyValueTable)
48
68
 
49
69
  ### Depends on
@@ -61,6 +81,7 @@ graph TD;
61
81
  SDateRangePicker --> SField
62
82
  SDateRangePicker --> SGhostButton
63
83
  SDateRangePicker --> SIcon
84
+ SChipFilter --> SDateRangePicker
64
85
  SKeyValueTable --> SDateRangePicker
65
86
  style SDateRangePicker fill:#f9f,stroke:#333,stroke-width:4px
66
87
  ```
@@ -44,5 +44,21 @@ export interface SDateRangePickerProps {
44
44
  className?: string;
45
45
  style?: CSSProperties;
46
46
  }
47
+ export interface SRangeCalendarProps {
48
+ value: SDateRangeValue;
49
+ selectable?: [string, string];
50
+ maxRange?: number;
51
+ useTimePicker?: boolean;
52
+ onSelect: (r: [string, string]) => void;
53
+ /** 시작일만 선택된(종료일 대기) 상태를 상위로 전달 — 트리거에 `start ~` 프리뷰 표시용 */
54
+ onPendingStartChange?: (start: string | null) => void;
55
+ onViewChange?: (view: {
56
+ year: number;
57
+ month: number;
58
+ }) => void;
59
+ }
60
+ /** RangeCalendar — SDateRangePicker의 캘린더 부분만 떼어낸 조각. 자체 트리거/팝오버 없이
61
+ * 캘린더 그리드만 필요한 커스텀 조합(예: 다른 트리거에 팝오버로 얹는 경우)에 재사용한다. */
62
+ export declare function RangeCalendar({ value, selectable, maxRange, useTimePicker, onSelect, onPendingStartChange, onViewChange, }: SRangeCalendarProps): import("react").JSX.Element;
47
63
  /** SDateRangePicker — sd-date-range-picker 포팅. SField + SPopover(범위 캘린더). */
48
64
  export declare function SDateRangePicker({ value, onValueChange, onViewChange, size, placeholder, selectable, maxRange, useTimePicker, disabled, width, name, rules, status, label, labelWidth, icon, iconColor, labelTooltip, labelTooltipProps, addonLabel, addonAlign, hint, error, errorMessage, className, style, }: SDateRangePickerProps): import("react").JSX.Element;
@@ -1 +1 @@
1
- export { SDateRangePicker, type SDateRangePickerProps, type SDateRangePickerSize, type SDateRangeValue, } from './SDateRangePicker';
1
+ export { RangeCalendar, SDateRangePicker, type SDateRangePickerProps, type SDateRangePickerSize, type SDateRangeValue, type SRangeCalendarProps, } from './SDateRangePicker';