@hjmds/design-contracts 1.13.1 → 1.14.0

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 (117) hide show
  1. package/dist/agreement.d.ts +7 -1
  2. package/dist/agreement.d.ts.map +1 -1
  3. package/dist/agreement.js +14 -3
  4. package/dist/agreement.js.map +1 -1
  5. package/dist/behaviors.d.ts +1 -1
  6. package/dist/catalog.d.ts +4 -0
  7. package/dist/catalog.d.ts.map +1 -1
  8. package/dist/content-transition.d.ts +17 -0
  9. package/dist/content-transition.d.ts.map +1 -1
  10. package/dist/content-transition.js +21 -0
  11. package/dist/content-transition.js.map +1 -1
  12. package/dist/date-entry.d.ts +71 -0
  13. package/dist/date-entry.d.ts.map +1 -0
  14. package/dist/date-entry.js +78 -0
  15. package/dist/date-entry.js.map +1 -0
  16. package/dist/document-resource.d.ts +104 -0
  17. package/dist/document-resource.d.ts.map +1 -0
  18. package/dist/document-resource.js +77 -0
  19. package/dist/document-resource.js.map +1 -0
  20. package/dist/effect-surface.d.ts +6 -1
  21. package/dist/effect-surface.d.ts.map +1 -1
  22. package/dist/effect-surface.js +5 -2
  23. package/dist/effect-surface.js.map +1 -1
  24. package/dist/field-group.d.ts +47 -0
  25. package/dist/field-group.d.ts.map +1 -0
  26. package/dist/field-group.js +92 -0
  27. package/dist/field-group.js.map +1 -0
  28. package/dist/image.d.ts +17 -0
  29. package/dist/image.d.ts.map +1 -1
  30. package/dist/image.js +19 -0
  31. package/dist/image.js.map +1 -1
  32. package/dist/internal/effect-noise.d.ts +2 -0
  33. package/dist/internal/effect-noise.d.ts.map +1 -0
  34. package/dist/internal/effect-noise.js +4 -0
  35. package/dist/internal/effect-noise.js.map +1 -0
  36. package/dist/progressive-blur.d.ts +32 -0
  37. package/dist/progressive-blur.d.ts.map +1 -0
  38. package/dist/progressive-blur.js +28 -0
  39. package/dist/progressive-blur.js.map +1 -0
  40. package/dist/reference-controls.d.ts +32 -0
  41. package/dist/reference-controls.d.ts.map +1 -0
  42. package/dist/reference-controls.js +28 -0
  43. package/dist/reference-controls.js.map +1 -0
  44. package/dist/scroll-progress.d.ts +7 -1
  45. package/dist/scroll-progress.d.ts.map +1 -1
  46. package/dist/scroll-progress.js +21 -2
  47. package/dist/scroll-progress.js.map +1 -1
  48. package/dist/text-annotation.d.ts +43 -0
  49. package/dist/text-annotation.d.ts.map +1 -0
  50. package/dist/text-annotation.js +137 -0
  51. package/dist/text-annotation.js.map +1 -0
  52. package/dist/version.d.ts +1 -1
  53. package/dist/version.js +1 -1
  54. package/dist/version.js.map +1 -1
  55. package/docs/agreement.md +14 -0
  56. package/docs/dialog.md +16 -1
  57. package/docs/effect-surface.md +19 -3
  58. package/docs/generated/component-maturity.md +1 -1
  59. package/docs/generated/renderer-evidence.json +3 -3
  60. package/docs/generated/renderer-evidence.md +1 -1
  61. package/docs/generated/showcase-manifest.json +1 -1
  62. package/docs/image.md +17 -0
  63. package/docs/optional-adapters.md +25 -0
  64. package/docs/popover.md +15 -0
  65. package/docs/rating.md +6 -1
  66. package/docs/reference-controls.md +40 -0
  67. package/docs/task-list.md +15 -1
  68. package/docs/text-annotation.md +85 -0
  69. package/docs/usage/README.md +18 -1
  70. package/docs/usage/components/agreement.md +13 -3
  71. package/docs/usage/components/alert-dialog.md +7 -1
  72. package/docs/usage/components/avatar.md +33 -1
  73. package/docs/usage/components/card.md +7 -1
  74. package/docs/usage/components/carousel.md +5 -1
  75. package/docs/usage/components/chat-message.md +11 -1
  76. package/docs/usage/components/chip.md +5 -0
  77. package/docs/usage/components/content-transition.md +28 -4
  78. package/docs/usage/components/dialog.md +18 -1
  79. package/docs/usage/components/effect-surface.md +4 -2
  80. package/docs/usage/components/empty-state.md +10 -2
  81. package/docs/usage/components/field.md +23 -0
  82. package/docs/usage/components/form.md +6 -1
  83. package/docs/usage/components/image-comparison.md +82 -0
  84. package/docs/usage/components/image.md +81 -2
  85. package/docs/usage/components/keyboard-avoiding.md +6 -1
  86. package/docs/usage/components/link.md +3 -1
  87. package/docs/usage/components/list-row.md +3 -1
  88. package/docs/usage/components/list.md +6 -1
  89. package/docs/usage/components/message-composer.md +5 -0
  90. package/docs/usage/components/popover.md +7 -1
  91. package/docs/usage/components/progress.md +28 -0
  92. package/docs/usage/components/progressive-blur.md +113 -0
  93. package/docs/usage/components/rating.md +74 -0
  94. package/docs/usage/components/search-field.md +10 -0
  95. package/docs/usage/components/search-screen.md +5 -0
  96. package/docs/usage/components/segmented-control.md +17 -0
  97. package/docs/usage/components/statistic.md +11 -0
  98. package/docs/usage/components/tags-input.md +5 -0
  99. package/docs/usage/components/toast.md +5 -0
  100. package/docs/usage/components/upload-item.md +3 -1
  101. package/docs/usage/compositions/action-feedback.md +77 -0
  102. package/docs/usage/compositions/adaptive-content.md +81 -0
  103. package/docs/usage/compositions/context-toolbar.md +85 -0
  104. package/docs/usage/compositions/date-entry.md +108 -0
  105. package/docs/usage/compositions/document-resource.md +124 -0
  106. package/docs/usage/compositions/field-group.md +104 -0
  107. package/docs/usage/compositions/illustrated-outcome.md +91 -0
  108. package/docs/usage/compositions/live-list.md +104 -0
  109. package/docs/usage/compositions/optional-adapters.md +1 -1
  110. package/docs/usage/compositions/origin-dialog.md +108 -0
  111. package/docs/usage/compositions/selection-motion.md +73 -0
  112. package/docs/usage/compositions/texture-comparison.md +86 -0
  113. package/docs/usage/compositions/upload-recovery.md +80 -0
  114. package/docs/usage/compositions/video-dialog.md +100 -0
  115. package/docs/usage/screens/flow-onboarding.md +5 -3
  116. package/docs/usage/screens/product-bento.md +117 -0
  117. package/package.json +37 -1
@@ -0,0 +1,100 @@
1
+ # 영상 미리보기
2
+
3
+ - 단계: 구성
4
+ - 상태: 배포
5
+ - 지원: Web · Native
6
+ - 적용: 1.14.0
7
+ - 검토일: 2026-10-07
8
+ - 근거: `showcase/web/src/patterns/video-dialog-preview.tsx`, `showcase/native/src/video-dialog-preview.tsx`
9
+ - 스토리북: `배포/구성/정보 표시/영상 미리보기`
10
+
11
+ 승급: 2026-10-07 사용자 승인, [검토 결과](../../../../../docs/qa/2026-10-07-experiment-promotion-release.md). Storybook 분류이며 제품 적용 증거는 별도다.
12
+
13
+ ## 언제 쓰나
14
+
15
+ 현재 입력을 유지하면서 짧은 영상 설명을 확인할 때 쓴다. HJM Dialog가 모달·닫기·초점 복귀를
16
+ 소유하고 제품이 플레이어·자막·미디어 권한·재시도를 공급한다. 전체 화면 감상과 재생 목록은
17
+ 제품의 전용 미디어 화면을 사용한다. 기존 Dialog.children으로 충분하므로 새 wrapper를 만들지 않는다.
18
+
19
+ ## 구성 요소
20
+
21
+ | 컴포넌트 | 역할 | 지침 |
22
+ | --- | --- | --- |
23
+ | Dialog | 제목·닫기·모달 접근성·초점 복귀 | [대화상자](../components/dialog.md) |
24
+ | Button | 미리보기·재생·재시도 | [버튼](../components/button.md) |
25
+ | TextField | 바깥 초안 보존 | [텍스트 필드](../components/field.md) |
26
+ | 제품 영상 호스트 | 디코딩·재생·미디어 해제 | Web video / Native Expo Video 예시 |
27
+
28
+ ## 배치
29
+
30
+ ```text
31
+ 바깥: [영상 메모] [영상 미리보기]
32
+ Dialog: [제목 닫기]
33
+ [설명]
34
+ [16:9 플레이어 + 미디어 컨트롤]
35
+ [동등한 내용의 텍스트 설명]
36
+ [재생/일시 정지 또는 다시 시도]
37
+ [실제 재생 상태]
38
+ ```
39
+
40
+ | 영역 | 컴포넌트 | 위치 | 크기·간격 |
41
+ | --- | --- | --- | --- |
42
+ | 바깥 틀 | Stack | 모달 아래의 원래 화면 | gap lg=20px |
43
+ | 모달 | Dialog | 공통 overlay 위치 | size large, renderer recipe를 그대로 사용 |
44
+ | 영상 | 제품 Player | 제목·설명 아래 본문 | 폭 100%, aspectRatio 16/9 |
45
+ | 설명·복구 | Text / Button | 플레이어 아래 | Stack gap md=16px, 긴 문구는 줄바꿈 |
46
+
47
+ ## 흐름과 상태
48
+
49
+ 1. 제품이 open과 입력 초안을 소유한다. 닫기 후 초안을 지우지 않는다.
50
+ 2. open일 때만 플레이어를 mount한다. 자동 재생하지 않고 사용자 행동으로 시작한다.
51
+ 3. 브라우저/Native 미디어 이벤트에서 재생·정지·실패를 읽는다. 요청 성공으로 재생을 추정하지 않는다.
52
+ 4. 실패 시 설명과 재시도를 유지한다. 재시도는 정상 source로 호스트를 새로 만들며 Web은 재생 버튼으로 초점을 옮긴다.
53
+ 5. open=false 즉시 호스트를 unmount한다. 모달 퇴장 애니메이션이 끝날 때까지 기다리지 않는다.
54
+ 6. Web은 pause 후 src를 제거하고 load하여 자원을 해제한다. Native useVideoPlayer는 unmount 시 player를 release한다.
55
+ 7. 앱/문서가 비활성화되면 일시 정지한다. 복귀 시 자동 재생하지 않는다.
56
+
57
+ | 상태 | 모습 | 포커스·알림 |
58
+ | --- | --- | --- |
59
+ | 기본 | 열기 전 플레이어 없음, 메모 유지 | 열기 버튼 |
60
+ | 진행 중 | 실제 이벤트에 따른 일시 정지와 상태 | 재생 상태 알림 |
61
+ | 실패 | 설명·다시 시도, 원래 메모 유지 | 오류 알림, Web 재시도 후 재생 버튼 |
62
+ | 호스트 없음 | Native 지원 모듈 누락 안내, 닫기 가능 | 제목과 안내 |
63
+ | 닫힘 | 영상 호스트 제거 | 열기 버튼으로 초점 복귀 |
64
+
65
+ ## 코드 골격
66
+
67
+ ```tsx
68
+ // Web
69
+ import { Dialog } from "@hjmds/react/overlays";
70
+ <Dialog open={open} onOpenChange={setOpen} title={title} description={description}
71
+ closeLabel={closeLabel} size="large" returnFocusRef={triggerRef}>
72
+ {open ? <ProductPlayer source={source} /> : null}
73
+ </Dialog>
74
+ ```
75
+
76
+ ```tsx
77
+ // Native
78
+ import { Dialog } from "@hjmds/react-native/overlays";
79
+ <Dialog open={open} onOpenChange={setOpen} title={title} closeLabel={closeLabel}
80
+ size="large" returnFocusRef={triggerRef}>
81
+ {open ? <ProductPlayer source={source} /> : null}
82
+ </Dialog>
83
+ ```
84
+
85
+ ProductPlayer는 제품 소유 코드의 자리이며 HJM export가 아니다. Showcase를 앱에서 import하지 않는다.
86
+ 제품은 미디어 자산·번역 문구·자막/대본·재생 권한을 공급한다. 무음 테스트 패턴 설명은 실제 영상 자막 검증을 대신하지 않는다.
87
+
88
+ ## 플랫폼 차이
89
+
90
+ Web은 HTML video controls와 playsInline을 사용한다. Native 예제는 Expo SDK 57의 expo-video
91
+ 호스트를 선택하며 설치된 앱에 모듈이 없으면 명시적으로 안내한다. Native fullscreen/PiP는 이 짧은
92
+ 모달 미리보기에서 사용하지 않는다. 제품이 다른 플레이어를 사용해도 Dialog 계약을 유지하며
93
+ 닫기·백그라운드·실패·초점 복귀를 실제 호스트에서 검증한다.
94
+
95
+ | 항목 | Web | Native |
96
+ | --- | --- | --- |
97
+ | 호스트 | HTML video | 제품 제공 player, Showcase는 Expo Video |
98
+ | 정리 | pause·src 제거·load | hook 소유 player 해제 |
99
+ | 지원 누락 | 미디어 오류와 재시도 | 모듈 누락 안내 |
100
+ | 설명 | 화면의 동등한 텍스트 | 화면의 동등한 텍스트 |
@@ -11,7 +11,7 @@
11
11
  ## 목적
12
12
 
13
13
  첫 실행 사용자를 몇 단계(소개 → 관심 주제 → 시작)로 안내하고 마지막 단계에서 완료를 저장하는 화면을 OnboardingScreen 하나로 구성한다.
14
- 단계 제목·설명은 화면 머리, 진행 문구는 머리 아래, 이동 버튼은 footer에 고정하고 단계 본문만 바꾼다. 권한 요청·로그인·가입은
14
+ 단계 제목·설명은 화면 맨 위, 진행 문구는 그 아래에 둔다. Web은 머리를 고정하고 Native는 제목·설명·진행을 본문과 함께 스크롤한다. 이동 버튼은 footer에 고정한다. 권한 요청·로그인·가입은
15
15
  이 화면에 없다([권한 안내](flow-permission.md), [로그인](common-login.md)).
16
16
  스토리는 `기본`(1단계부터 직접 넘기기), `관심 주제 고르기`(2단계를 바로 연 상태), `실패와 복구`(다음 완료 저장 실패 → 다시 시작하기)다.
17
17
  2026-10-06 배포 직접 조립 온보딩(Steps·ContentTransition·여러 개 고르는 주제 버튼)을 이 항목으로 합쳤고, 그 고유 상태인
@@ -44,8 +44,8 @@
44
44
  | 영역 | 컴포넌트 | 위치 | 크기·간격 |
45
45
  | --- | --- | --- | --- |
46
46
  | 바깥 틀 | OnboardingScreen(내부 ScreenLayout `scroll="screen"`) | route 본문. host가 남은 높이·safe area·키보드를 준다 | 폭 최대 720, 바깥 padding `spacing.md` 16([ScreenLayout 배치](../components/screen-layout.md#배치)). 화면 props는 `layoutStyle`만 받는다 |
47
- | 머리 | `steps[index].title`·`description` + `skip`(ghost Button) | 맨 위, 고정 | 제목 열 최소 120 × 글자 배율, 모자라면 건너뛰기가 다음 줄로 내려간다 |
48
- | 진행 문구 | `progressLabel(current, total)` → Text `variant="caption" tone="muted"` | 머리 아래 notice 자리, 고정 | 좌우 16 |
47
+ | 머리 | `steps[index].title`·`description` + `skip`(ghost Button) | 맨 위, Web 고정·Native 본문 스크롤 | 제목 열 최소 120 × 글자 배율, 모자라면 건너뛰기가 다음 줄로 내려간다 |
48
+ | 진행 문구 | `progressLabel(current, total)` → Text `variant="caption" tone="muted"` | 머리 아래, Web notice 고정·Native 본문 스크롤 | 좌우 16 |
49
49
  | 단계 본문 | `steps[index].content` | 진행 문구 아래, 본문 스크롤 | 본문 안 간격은 제품 소유. 예제는 Stack `gap="lg"` 20 |
50
50
  | 관심 주제 | Stack `axis="inline" wrap gap="xs"`(Web `role="group"` + 이름) > [Chip](../components/chip.md) `selectionMode="multiple"` | 2단계 content 안 | 칩 높이 `small` 36(Native hitSlop으로 터치 44), 사이 `spacing.xs` 8 |
51
51
  | 저장 실패 | [Notice](../components/notice.md) `tone="danger"` + `action` | 마지막 단계 content 맨 아래 | 본문 Stack 간격을 따른다 |
@@ -191,3 +191,5 @@ const topicPicker = <Stack axis="inline" wrap gap="xs">
191
191
  - 완료 `pending` 동안에도 이전 버튼은 막히지 않는다. 저장 중 단계 이동이 문제가 되면 `onIndexChange`에서 무시한다.
192
192
  - 현재 스토리의 진행 문구는 `` `${index} / ${total}` `` 고정 문자열이다. 제품은 보간 키 하나(`onboarding.progress`)를 쓴다.
193
193
  - Storybook은 실제 서버·라우터 연동 증거가 아니다. 기본·어두운 테마·큰 글자와 실패와 복구를 각각 확인한다.
194
+
195
+ 2026-10-07 iOS 26.5 / 200% 글자에서 키보드가 열린 시작 안내의 고정 머리가 본문 높이를 모두 소비했다. Native는 기존 ScreenLayout의 본문 스크롤 안으로 단계 안내를 옮겨 입력에 도달하게 하고 footer의 완료·이전 버튼은 유지한다. [검토 결과](../../../../../docs/qa/2026-10-07-experiment-promotion-release.md).
@@ -0,0 +1,117 @@
1
+ # 기능 카드와 주 행동
2
+
3
+ - 단계: 화면
4
+ - 상태: 배포
5
+ - 지원: Web · Native
6
+ - 적용: 1.14.0
7
+ - 검토일: 2026-10-07
8
+ - 근거: `reference-adoption-previews.tsx`, `reference-adoption.css`
9
+ - 스토리북: `배포/화면/소개/기능 카드와 주 행동`
10
+
11
+ 승급: 2026-10-07 사용자 승인, [검토 결과](../../../../../docs/qa/2026-10-07-experiment-promotion-release.md). Storybook 분류이며 제품 적용 증거는 별도다.
12
+
13
+ ## 목적
14
+
15
+ 기능을 실제 미리보기로 보여 주고 첫 행동으로 이어지는 소개 화면이다. 기존 Surface/Stack/Button/ImageComparison을 조합한다.
16
+
17
+ ## 영역 구조
18
+
19
+ ```text
20
+ [브랜드]
21
+ [제목 · 가치 설명]
22
+ [비교 미리보기] [기능 설명 두 장] ← 넓은 Web 2:1
23
+ [첫 입력(시작한 뒤)]
24
+ [사용 방법(선택)]
25
+ [보조 행동] [주 행동]
26
+ [항상 보이는 체험·저장 범위]
27
+ [처리 결과 · 저장된 제목]
28
+ ```
29
+
30
+ 좁은 Web과 Native는 비교→설명 두 장→첫 행동 순서로 한 열에 놓는다.
31
+
32
+ | 영역 | 컴포넌트 | 위치 | 크기·간격 |
33
+ | --- | --- | --- | --- |
34
+ | 바깥 틀 | Web Stack / Native KeyboardAvoiding → ScreenLayout → Stack | Web 문서 스크롤 / Native 고정 제목 아래 본문 스크롤 | 본문 lg=20px, Native 제목 간격 md=16px, contentInset none |
35
+ | 기능 | Surface/Stack | 설명 다음 | padding lg=20px, 카드 gap md=16px |
36
+ | 제목/본문 | Text/Stack | 각 카드 안 | sm=12px |
37
+ | 첫 행동 | BottomCTA | 기능·입력 뒤 | description → 보조/주 행동, flow 배치 |
38
+ | 조건 | BottomInfo | 주 행동 바로 아래 | 항상 유지, 예제의 로컬 저장 범위 설명 |
39
+
40
+ ## 버튼과 행동 위치
41
+
42
+ | 행동 | 컴포넌트·tone | 위치 | 개수·순서 |
43
+ | --- | --- | --- | --- |
44
+ | 주 행동 | BottomCTA primaryAction | 기능·입력 아래 | 시작 → 미리보기에 저장, 1개 |
45
+ | 보조 행동 | BottomCTA secondaryAction | 같은 행동 영역 | 사용 방법 보기/접기 → 소개로 돌아가기 |
46
+ | 비교 보조 | Button·secondary | 이미지 슬라이더 아래 | 전→후 전체 보기 2개, wrap |
47
+ | 파괴 행동 | 없음 | 없음 | 0개 |
48
+
49
+ ## 상태
50
+
51
+ | 상태 | 화면 모습 | 행동 |
52
+ | --- | --- | --- |
53
+ | 기본 | 설명과 비교·주/보조 행동·조건 안내 | 첫 입력 또는 사용 방법으로 이동 |
54
+ | 로딩 | 실제 이미지 로드 상태 | 주 행동은 제품 가용성에 맞춤 |
55
+ | 빈 | 제품 자료가 없으면 비교 영역 생략 | 문구와 첫 행동 유지 |
56
+ | 오류 | 이미지 실패 대체 또는 저장 실패 문구·제목 유지 | 현재 제목으로 다시 저장 |
57
+ | 진행 중 | 주 행동 spinner, 보조 행동 비활성 | 중복 실행 방지, 입력 내용은 제품 상태에 유지 |
58
+ | 완료 | 확정한 제목과 성공 문구 | 다음 입력 가능 |
59
+
60
+ ## 사용하는 지침
61
+
62
+ | 지침 | 쓰는 곳 |
63
+ | --- | --- |
64
+ | [ImageComparison](../components/image-comparison.md) | 기능 미리보기 |
65
+ | [Stack](../components/stack.md) | 읽기 순서와 간격 |
66
+ | [BottomCTA](../components/bottom-cta.md) · [BottomInfo](../components/bottom-info.md) | 주·보조 행동과 항상 보이는 조건 |
67
+
68
+ ## 코드 골격
69
+
70
+ ```tsx
71
+ // Web
72
+ <Stack gap="lg">
73
+ <Text variant="heading">{title}</Text>
74
+ <Surface padding="lg"><ImageComparison {...comparison} /></Surface>
75
+ <BottomCTA primaryAction={{ label: startLabel, onClick: start }} secondaryAction={{ label: helpLabel, onClick: showHelp }} />
76
+ <BottomInfo items={conditions} />
77
+ </Stack>
78
+ ```
79
+
80
+ ```tsx
81
+ // Native: screen-owned scrolling keeps the CTA reachable below long previews.
82
+ <KeyboardAvoiding style={{ flex: 1 }}>
83
+ <ScreenLayout title={title} contentInset="none">
84
+ <Stack gap="lg">
85
+ <Surface padding="lg"><ImageComparison {...comparison} decrementLabel={decrementLabel} incrementLabel={incrementLabel} /></Surface>
86
+ <BottomCTA primaryAction={{ label: startLabel, onPress: start }} secondaryAction={{ label: helpLabel, onPress: showHelp }} />
87
+ <BottomInfo items={conditions} />
88
+ </Stack>
89
+ </ScreenLayout>
90
+ </KeyboardAvoiding>
91
+ ```
92
+
93
+ Native는 같은 public component entry를 `@hjmds/react-native`로 바꾸고 Button에 `onPress`를 쓴다.
94
+ Native ImageComparison에는 증감 행동 label을 추가한다. 제품의 계정/저장 안내와 데이터는 제품이 공급한다.
95
+
96
+ ## 큰 글자·다크·좁은 폭
97
+
98
+ | 조건 | 바뀌는 것 |
99
+ | --- | --- |
100
+ | 큰 글자 | 제목·본문·버튼이 자연스럽게 줄바꿈 |
101
+ | 다크 | provider semantic palette 사용 |
102
+ | 좁은 폭 | 예제 Web 48rem 이하에서 1열. Native는 항상 단일 순서 |
103
+
104
+
105
+ ### CTA 레퍼런스 흡수와 저장 소유권
106
+
107
+ 2026-10-07 CTA Gallery의 Webflow 데스크톱·모바일 캡처에서 주/보조 행동의 위계를,
108
+ Ente 캡처에서 플랫폼 조건에 맞춘 행동 묶음을 확인했다. HJM에는 기존 BottomCTA/BottomInfo로
109
+ 역할을 분리하며 외부 브랜드 색·스토어 배지·가격을 복제하지 않는다. 별도 CTA 엔진은 추가하지 않는다.
110
+
111
+ 제목은 화면의 controlled state에 둔다. 소개로 돌아가 입력을 숨겨도 제목은 남고 다시 시작하면
112
+ 복구된다. 실제 서버가 없는 데모임을 상시 표시한다. 기존 useDemoAction/ActionSession으로
113
+ 중복 요청·pending·실패 후 재시도를 검증하며 350ms 지연은 데모 전용이다. 실패 시 현재 제목은
114
+ 유지하고 다시 저장은 현재 입력 snapshot을 제출한다. 저장된 제목은 마지막으로 확정한 값이다.
115
+
116
+ Web 큰 글자에서는 BottomCTA 계약대로 주 행동이 위, 보조 행동이 아래로 쌓인다. 모바일 Native도
117
+ 같은 계약을 따르며 화면 host가 스크롤·키보드·safe area를 제공한다. Native 예제에는 기존 ScreenLayout과 KeyboardAvoiding을 연결한다. 스크롤 없는 Canvas에서 CTA가 화면 밖으로 잘렸던 2026-10-07 실제 확인에 따른 수정이다. 제품은 host safe area/keyboard offset을 실제 내비게이션에 맞춘다.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hjmds/design-contracts",
3
- "version": "1.13.1",
3
+ "version": "1.14.0",
4
4
  "description": "Renderer-neutral design contracts, tokens, recipes, and behaviors shared by HJM products.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -589,6 +589,12 @@
589
589
  "import": "./dist/content-transition.js",
590
590
  "default": "./dist/content-transition.js"
591
591
  },
592
+ "./reference-controls": {
593
+ "types": "./dist/reference-controls.d.ts",
594
+ "react-native": "./dist/reference-controls.js",
595
+ "import": "./dist/reference-controls.js",
596
+ "default": "./dist/reference-controls.js"
597
+ },
592
598
  "./duration-field": {
593
599
  "types": "./dist/duration-field.d.ts",
594
600
  "react-native": "./dist/duration-field.js",
@@ -666,6 +672,36 @@
666
672
  "react-native": "./dist/screen-patterns.js",
667
673
  "import": "./dist/screen-patterns.js",
668
674
  "default": "./dist/screen-patterns.js"
675
+ },
676
+ "./progressive-blur": {
677
+ "types": "./dist/progressive-blur.d.ts",
678
+ "react-native": "./dist/progressive-blur.js",
679
+ "import": "./dist/progressive-blur.js",
680
+ "default": "./dist/progressive-blur.js"
681
+ },
682
+ "./text-annotation": {
683
+ "types": "./dist/text-annotation.d.ts",
684
+ "react-native": "./dist/text-annotation.js",
685
+ "import": "./dist/text-annotation.js",
686
+ "default": "./dist/text-annotation.js"
687
+ },
688
+ "./date-entry": {
689
+ "types": "./dist/date-entry.d.ts",
690
+ "react-native": "./dist/date-entry.js",
691
+ "import": "./dist/date-entry.js",
692
+ "default": "./dist/date-entry.js"
693
+ },
694
+ "./field-group": {
695
+ "types": "./dist/field-group.d.ts",
696
+ "react-native": "./dist/field-group.js",
697
+ "import": "./dist/field-group.js",
698
+ "default": "./dist/field-group.js"
699
+ },
700
+ "./document-resource": {
701
+ "types": "./dist/document-resource.d.ts",
702
+ "react-native": "./dist/document-resource.js",
703
+ "import": "./dist/document-resource.js",
704
+ "default": "./dist/document-resource.js"
669
705
  }
670
706
  },
671
707
  "files": [