@hjmds/design-contracts 1.13.1 → 1.15.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 (200) 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/design-profile-layout.d.ts +11 -0
  17. package/dist/design-profile-layout.d.ts.map +1 -0
  18. package/dist/design-profile-layout.js +18 -0
  19. package/dist/design-profile-layout.js.map +1 -0
  20. package/dist/design-profile.d.ts +89 -0
  21. package/dist/design-profile.d.ts.map +1 -0
  22. package/dist/design-profile.js +262 -0
  23. package/dist/design-profile.js.map +1 -0
  24. package/dist/design-system-provider.d.ts +6 -0
  25. package/dist/design-system-provider.d.ts.map +1 -1
  26. package/dist/design-system-provider.js +4 -2
  27. package/dist/design-system-provider.js.map +1 -1
  28. package/dist/document-resource.d.ts +104 -0
  29. package/dist/document-resource.d.ts.map +1 -0
  30. package/dist/document-resource.js +77 -0
  31. package/dist/document-resource.js.map +1 -0
  32. package/dist/effect-surface.d.ts +6 -1
  33. package/dist/effect-surface.d.ts.map +1 -1
  34. package/dist/effect-surface.js +5 -2
  35. package/dist/effect-surface.js.map +1 -1
  36. package/dist/field-group.d.ts +47 -0
  37. package/dist/field-group.d.ts.map +1 -0
  38. package/dist/field-group.js +92 -0
  39. package/dist/field-group.js.map +1 -0
  40. package/dist/gooey-navigation.d.ts +19 -1
  41. package/dist/gooey-navigation.d.ts.map +1 -1
  42. package/dist/gooey-navigation.js +37 -2
  43. package/dist/gooey-navigation.js.map +1 -1
  44. package/dist/image.d.ts +17 -0
  45. package/dist/image.d.ts.map +1 -1
  46. package/dist/image.js +19 -0
  47. package/dist/image.js.map +1 -1
  48. package/dist/internal/effect-noise.d.ts +2 -0
  49. package/dist/internal/effect-noise.d.ts.map +1 -0
  50. package/dist/internal/effect-noise.js +4 -0
  51. package/dist/internal/effect-noise.js.map +1 -0
  52. package/dist/palette-contrast.d.ts +6 -0
  53. package/dist/palette-contrast.d.ts.map +1 -1
  54. package/dist/palette-contrast.js +17 -0
  55. package/dist/palette-contrast.js.map +1 -1
  56. package/dist/progressive-blur.d.ts +32 -0
  57. package/dist/progressive-blur.d.ts.map +1 -0
  58. package/dist/progressive-blur.js +28 -0
  59. package/dist/progressive-blur.js.map +1 -0
  60. package/dist/reference-controls.d.ts +32 -0
  61. package/dist/reference-controls.d.ts.map +1 -0
  62. package/dist/reference-controls.js +28 -0
  63. package/dist/reference-controls.js.map +1 -0
  64. package/dist/screen-patterns.d.ts +16 -1
  65. package/dist/screen-patterns.d.ts.map +1 -1
  66. package/dist/screen-patterns.js +4 -0
  67. package/dist/screen-patterns.js.map +1 -1
  68. package/dist/scroll-progress.d.ts +7 -1
  69. package/dist/scroll-progress.d.ts.map +1 -1
  70. package/dist/scroll-progress.js +21 -2
  71. package/dist/scroll-progress.js.map +1 -1
  72. package/dist/text-annotation.d.ts +43 -0
  73. package/dist/text-annotation.d.ts.map +1 -0
  74. package/dist/text-annotation.js +137 -0
  75. package/dist/text-annotation.js.map +1 -0
  76. package/dist/toast-liquid.d.ts +3 -1
  77. package/dist/toast-liquid.d.ts.map +1 -1
  78. package/dist/toast-liquid.js +6 -2
  79. package/dist/toast-liquid.js.map +1 -1
  80. package/dist/version.d.ts +1 -1
  81. package/dist/version.js +1 -1
  82. package/dist/version.js.map +1 -1
  83. package/docs/agreement.md +14 -0
  84. package/docs/asset.md +7 -0
  85. package/docs/brand-boundary.md +14 -5
  86. package/docs/code-block.md +12 -1
  87. package/docs/collapsible.md +6 -0
  88. package/docs/design-profile.md +263 -0
  89. package/docs/design-system-provider.md +7 -0
  90. package/docs/dialog.md +20 -1
  91. package/docs/effect-surface.md +19 -3
  92. package/docs/generated/component-maturity.md +1 -1
  93. package/docs/generated/renderer-evidence.json +3 -3
  94. package/docs/generated/renderer-evidence.md +1 -1
  95. package/docs/generated/showcase-manifest.json +1 -1
  96. package/docs/gooey-navigation.md +37 -6
  97. package/docs/heading.md +15 -0
  98. package/docs/image.md +17 -0
  99. package/docs/optional-adapters.md +25 -0
  100. package/docs/popover.md +15 -0
  101. package/docs/rating.md +6 -1
  102. package/docs/reference-controls.md +40 -0
  103. package/docs/task-list.md +15 -1
  104. package/docs/text-annotation.md +85 -0
  105. package/docs/theming.md +18 -5
  106. package/docs/usage/README.md +23 -1
  107. package/docs/usage/components/activity-heatmap.md +3 -1
  108. package/docs/usage/components/agreement.md +15 -3
  109. package/docs/usage/components/alert-dialog.md +16 -1
  110. package/docs/usage/components/asset.md +9 -2
  111. package/docs/usage/components/avatar.md +33 -1
  112. package/docs/usage/components/badge.md +3 -1
  113. package/docs/usage/components/bottom-cta.md +3 -1
  114. package/docs/usage/components/bottom-navigation.md +5 -1
  115. package/docs/usage/components/button.md +7 -1
  116. package/docs/usage/components/calendar.md +3 -1
  117. package/docs/usage/components/card.md +26 -3
  118. package/docs/usage/components/carousel.md +10 -1
  119. package/docs/usage/components/chat-message.md +11 -1
  120. package/docs/usage/components/chip.md +5 -0
  121. package/docs/usage/components/code-block.md +14 -2
  122. package/docs/usage/components/collapsible.md +10 -2
  123. package/docs/usage/components/combobox.md +12 -1
  124. package/docs/usage/components/command-palette.md +11 -6
  125. package/docs/usage/components/content-transition.md +29 -5
  126. package/docs/usage/components/context-menu.md +7 -1
  127. package/docs/usage/components/date-picker.md +3 -1
  128. package/docs/usage/components/design-system-provider.md +7 -5
  129. package/docs/usage/components/dialog.md +70 -1
  130. package/docs/usage/components/effect-surface.md +4 -2
  131. package/docs/usage/components/empty-state.md +10 -2
  132. package/docs/usage/components/field.md +26 -1
  133. package/docs/usage/components/form.md +13 -3
  134. package/docs/usage/components/heading.md +7 -1
  135. package/docs/usage/components/image-comparison.md +82 -0
  136. package/docs/usage/components/image.md +83 -2
  137. package/docs/usage/components/keyboard-avoiding.md +6 -1
  138. package/docs/usage/components/link.md +3 -1
  139. package/docs/usage/components/list-row.md +5 -1
  140. package/docs/usage/components/list.md +8 -1
  141. package/docs/usage/components/load-more.md +3 -1
  142. package/docs/usage/components/mentions.md +3 -1
  143. package/docs/usage/components/menu.md +3 -1
  144. package/docs/usage/components/menubar.md +7 -1
  145. package/docs/usage/components/message-composer.md +16 -5
  146. package/docs/usage/components/notice.md +9 -0
  147. package/docs/usage/components/number-field.md +3 -1
  148. package/docs/usage/components/onboarding-screen.md +16 -9
  149. package/docs/usage/components/overview-screen.md +73 -0
  150. package/docs/usage/components/password-field.md +5 -1
  151. package/docs/usage/components/popover.md +14 -1
  152. package/docs/usage/components/progress.md +28 -0
  153. package/docs/usage/components/progressive-blur.md +113 -0
  154. package/docs/usage/components/rating.md +74 -0
  155. package/docs/usage/components/saved-items-screen.md +3 -1
  156. package/docs/usage/components/screen-layout.md +9 -1
  157. package/docs/usage/components/search-field.md +13 -1
  158. package/docs/usage/components/search-screen.md +5 -0
  159. package/docs/usage/components/segmented-control.md +17 -0
  160. package/docs/usage/components/select.md +9 -0
  161. package/docs/usage/components/sheet.md +14 -1
  162. package/docs/usage/components/skeleton.md +9 -0
  163. package/docs/usage/components/slider.md +3 -1
  164. package/docs/usage/components/statistic.md +14 -1
  165. package/docs/usage/components/surface.md +8 -1
  166. package/docs/usage/components/tabs.md +11 -2
  167. package/docs/usage/components/tag.md +3 -1
  168. package/docs/usage/components/tags-input.md +11 -1
  169. package/docs/usage/components/text-area.md +3 -1
  170. package/docs/usage/components/text-transition.md +8 -2
  171. package/docs/usage/components/text.md +3 -1
  172. package/docs/usage/components/toast.md +23 -1
  173. package/docs/usage/components/top-bar.md +3 -1
  174. package/docs/usage/components/upload-item.md +3 -1
  175. package/docs/usage/compositions/action-feedback.md +77 -0
  176. package/docs/usage/compositions/adaptive-content.md +81 -0
  177. package/docs/usage/compositions/command-records.md +106 -0
  178. package/docs/usage/compositions/content-transition-comparison.md +108 -0
  179. package/docs/usage/compositions/context-toolbar.md +85 -0
  180. package/docs/usage/compositions/date-entry.md +108 -0
  181. package/docs/usage/compositions/date-time-selection.md +110 -0
  182. package/docs/usage/compositions/design-profile-comparison.md +114 -0
  183. package/docs/usage/compositions/document-resource.md +124 -0
  184. package/docs/usage/compositions/field-group.md +104 -0
  185. package/docs/usage/compositions/illustrated-outcome.md +91 -0
  186. package/docs/usage/compositions/live-list.md +104 -0
  187. package/docs/usage/compositions/optional-adapters.md +1 -1
  188. package/docs/usage/compositions/origin-dialog.md +108 -0
  189. package/docs/usage/compositions/selection-motion.md +73 -0
  190. package/docs/usage/compositions/texture-comparison.md +86 -0
  191. package/docs/usage/compositions/upload-recovery.md +80 -0
  192. package/docs/usage/compositions/video-dialog.md +100 -0
  193. package/docs/usage/screens/flow-onboarding.md +5 -3
  194. package/docs/usage/screens/product-bento.md +117 -0
  195. package/docs/usage/tokens/color.md +9 -2
  196. package/docs/usage/tokens/elevation-opacity.md +8 -1
  197. package/docs/usage/tokens/motion.md +10 -1
  198. package/docs/usage/tokens/radius.md +8 -1
  199. package/docs/usage/tokens/typography.md +15 -1
  200. package/package.json +49 -1
@@ -1,6 +1,6 @@
1
1
  # Code block
2
2
 
3
- Reviewed: 2026-10-01. Optional `/code-block` entries in both renderers expose
3
+ Reviewed: 2026-10-07. Optional `/code-block` entries in both renderers expose
4
4
  `CodeBlock`. This is a source preview, not an editor or executable HTML renderer.
5
5
  The visual integration request required syntax presentation without another input
6
6
  or clipboard engine, so source validation belongs to contracts and actions are slots.
@@ -30,3 +30,14 @@ host tests check selectable content and scroll/wrap composition. The
30
30
  200% controlled text scaling and actual iOS simulator long-press Copy, with exact
31
31
  source/clipboard equality. Header and source use the common text-scale helper;
32
32
  token spans inherit once. Android clipboard and physical-device verification remain separate.
33
+
34
+
35
+ The product design profile supplies `tokens.fontFamily.code` and `tokens.typography.body`
36
+ to both source hosts. Syntax spans inherit those metrics and the original code remains
37
+ unchanged. Native translates the default generic monospace intent to Menlo on iOS and
38
+ monospace on Android; custom font installation stays with the product. The source is
39
+ LTR inside an RTL shell: an actual RTL comparison moved the trailing semicolon to the
40
+ beginning of the displayed statement. Localized headings and surrounding controls retain
41
+ the product direction. This is a reading-order decision, not a source-text rewrite.
42
+
43
+ Native 제목은 제품 UI font, 원문과 span은 code font를 읽는다. 두 역할은 같은 내부 플랫폼 font 해석을 공유하며, 제목이 OS 서체로 남던 경로를 보완했다. 실제 font 등록은 제품이 맡는다.
@@ -29,3 +29,9 @@ chrome이 따라오고 그걸 다시 CSS로 지우게 된다. 그래서 별도
29
29
  host-renderer evidence; it does not claim physical keyboard, VoiceOver, or TalkBack verification.
30
30
  - Native and Web long-copy fixtures put the long label in the trigger itself. The child body stays
31
31
  short so the scenario tests the constrained interactive label rather than arbitrary content.
32
+
33
+ ## 프로필 도구의 표현
34
+
35
+ 2026-10-07 테마 전환 시 입력이 사라지는 문제를 피하려고 `presentation="inline"`과 `keepMounted`를 추가했다.
36
+ inline은 트리거를 숨기고 항상 내용을 펼친다. 기본 disclosure는 기존 open/defaultOpen 규칙을 유지한다.
37
+ keepMounted가 있어도 닫힌 내용은 포커스·스크린리더·터치 대상에서 제외한다. 단순 read-only 내용은 기존 기본값을 쓴다.
@@ -0,0 +1,263 @@
1
+ # 디자인 프리셋 계약
2
+
3
+ 검토일: 2026-10-07 · 상태: 10종 실험 구현·대상 로컬 검사 완료 · 미게시(1.14.0 이후)
4
+
5
+ 사용자가 레트로·종이·숲 등의 테마에 따라 같은 기능의 상호작용·구성·화면 배치도 자동으로 달라지고, 앱이 자기 테마를 한 번 주입하기를 요청했다. 색상 프리셋만으로는 그 요구를 충족하지 못하므로 네 축을 하나의 데이터 계약으로 둔다. 기존 상태 엔진을 테마마다 복제하는 방식은 채택하지 않는다.
6
+
7
+ ## 소유권과 공개 경로
8
+
9
+ `@hjmds/design-contracts/design-profile`은 `hjmDesignPresets`, `defineHjmDesignProfile`, `resolveDesignProfileSurfaceMaterial`, `HjmDesignProfile`, `HjmDesignProfileInput`, `HjmDesignPreset`을 제공한다. 이 subpath는 기존 ThemeStudio의 색상 편집과 역할이 다르다. 색상 편집 subpath에 질감/구성 그래프를 추가하지 않고 선택형 프로필 진입점으로 분리했다. package export 추가의 근거는 이 절이다.
10
+
11
+ 제품은 설정 파일에서 preset을 상속하고 필요한 축만 수정한다. 설정은 Web/Native renderer를 import하지 않으며 글꼴 자산의 설치·라이선스·로딩, 브랜드 자산, 데이터·권한·라우팅·서버 확정은 제품이 소유한다. HJM은 지원 가능한 표현/행동/배치와 환경 대체 경로를 소유한다.
12
+
13
+ ```ts
14
+ import { defineHjmDesignProfile } from "@hjmds/design-contracts/design-profile";
15
+
16
+ export const productDesign = defineHjmDesignProfile({
17
+ extends: "forest",
18
+ id: "product-design",
19
+ compositions: { collection: "rows" },
20
+ });
21
+ ```
22
+
23
+ 이 helper는 검증한 불변 프로필을 만든다. Web `HjmProvider.designProfile`, Native `HjmNativeProvider.designProfile`에 넣으며, 중첩 Provider는 가장 가까운 프로필을 상속한다. 기존 프로필 없는 소비자의 기본값은 유지한다.
24
+
25
+ ### 제품 설정과 참고 테마를 조합하기
26
+
27
+ 같은 제품이 `extends`만 바꾸면 나머지 부분 지정은 계속 제품 소유다. `palette`는 light/dark의 지정 역할만,
28
+ `compositions`·`screens`·`interactions`는 지정 축만 덮고 모서리·글자·질감 등의 미지정 값은 참고 테마를 상속한다.
29
+ 기록/계정/라우팅 상태를 프로필 객체에 넣거나 프로필 id를 React subtree key로 써서 교체하지 않는다.
30
+
31
+ 2026-10-07 필요한 조사 후 기존 테마 조합 실험에 산책 노트(녹색/cards/landscape)와 문장 모음(보라/rows/editorial)
32
+ 두 앱 설정 fixture를 추가했다. 두 플랫폼은 같은 순수 설정을 공유하며 각 workspace의 실제 공개 helper로 검증한다.
33
+ 앱 브랜드를 새 HJM preset/global registry로 등록하지 않고 기존 10종 위에 조합하는 경계를 보여 주기 위한 선택이다.
34
+ 이 fixture는 운영 제품의 테마 적용이나 Native 기기 검증 증거가 아니다. 앱은 자신의 설정 파일과 제품 데이터를 넣는다.
35
+ 행동·상태와 실제 지원 축은 [사용 지침](usage/compositions/design-profile-comparison.md)을 따른다.
36
+
37
+ ## 축과 기본값
38
+
39
+ | 축 | 중립 기본값 | 참고 프리셋의 차이 |
40
+ | --- | --- | --- |
41
+ | palette | 현재 HJM light/dark 17 semantic roles | 레트로의 잉크/황갈색, 종이의 따뜻한 중립색, 숲의 녹색 |
42
+ | tokens | 기존 radius/fontFamily/typography/heading/shadow | 모서리·글자 크기/행간/강조·그림자와 일반 monospace fallback; 폰트 자산은 번들하지 않음 |
43
+ | material | canvas/card/surface 모두 null | 레트로 noise, 종이 grain, 숲 mesh+glow; 오로라만 active=true, 나머지는 정적 |
44
+ | interactions | contentTransition=fade, selectionMotion=none | 레트로 slide, 종이 fade, 숲 rise와 slide 선택 배경 |
45
+ | compositions | collection=rows, toolbar=inline | 레트로 grid/inline, 종이 rows/collapsible, 숲 cards/collapsible |
46
+ | screens | overview=dashboard | 종이 editorial, 숲 landscape |
47
+
48
+ 상속 후 데이터는 재귀적으로 동결한다. 호출자의 배열/descriptor를 동결하지 않고 복사해 앱 소유 상태에 영향을 주지 않는다. light/dark 팔레트와 nested 토큰은 역할별로 병합하며, preset 원본은 바뀌지 않는다. 고정된 원·pill 의미 때문에 radius.full=999는 유지한다. 글자 크기·줄 높이·그림자·질감 범위와 지원하는 변형 이름을 검사하고 지정 색상 쌍의 대비 미달을 거부한다. 이 검사는 완성 화면 접근성 인증이 아니다.
49
+
50
+ ## 기존 API 비교와 연결 순서
51
+
52
+ - 기존 Provider/brandPalette/environment는 유지한다. 프리셋은 별도 환경 축이 아니라 네 단계의 표현/배치 기본값이며 명시적인 props가 우선한다.
53
+ - `ContentTransition`의 fade/rise/slide/scale와 `SegmentedControl`·`Tabs`의 selectionMotion을 재사용한다. Tabs의 명시 appearance가 우선이며 세로는 standard다. 없는 피드백 엔진을 제공했다고 표시하지 않는다.
54
+ - Surface와 Web 테마 변수, Native tokens 및 직접 foundation을 읽는 소비자를 함께 연결한다. `tokens.radius` 값 정의만으로 전체 컴포넌트 적용을 주장하지 않는다.
55
+ - 구성은 기존 Grid/List/Collapsible/도구 묶음과 공개 슬롯을 대조한다. 화면은 기존 ScreenLayout의 제목·본문·상태·주 행동 계약을 유지하며 배치 변형을 추가한다. 같은 화면의 데이터/초안을 variant subtree 안에 저장해 전환 시 버리지 않는다.
56
+ - 질감은 optional EffectSurface renderer의 host/peer 경계를 유지한다. 프로필의 descriptor 정의만으로 native SVG peer 설치나 실제 표시를 보증하지 않는다.
57
+
58
+ ## 현재 증거와 남은 조건
59
+
60
+ 공통 데이터·Provider·기본 토큰 소비·상호작용 기본값·OverviewScreen 구성과 화면·양쪽 Storybook 비교를 구현했다. 전체 기존 컴포넌트의 정적 토큰 소비 감사는 진행 중이다. 브라우저의 입력 유지·복구와 light/dark·좁은 폭·큰 글자·RTL·모션 축소는 [QA 기록](../../../docs/qa/2026-10-07-design-profile-research.md)에서 확인했다. Native 실기기 검증은 아직 미완료다. 실험 등록·승격·게시·Utilverse 적용을 분리한다. 완료 기준은 [작업 계획](../../../docs/plans/reference-release-utilverse-2026-10-07.md)의 프리셋 절을 따른다.
61
+
62
+ ## 10종 확장과 현재 연결
63
+
64
+ 2026-10-07 사용자 요청으로 참조 팩은 최소 10종이며 neutral은 수에서 제외한다.
65
+ [조사/QA 기록](../../../docs/qa/2026-10-07-design-profile-research.md)에 개별 출처와 원본 관찰/HJM 해석을 구분한다.
66
+ Provider의 `designProfile`에 `hjmDesignPresets.forest` 또는 `defineHjmDesignProfile(...)` 결과를 넣는다.
67
+ 부분 JSON을 Provider에 직접 넣지 않는다. 앱의 파일·등록·설정 저장과 폰트 로딩은 앱이 소유한다.
68
+ `brandPalette`는 선택된 프로필의 해당 테마 팔레트 위에 놓인다.
69
+
70
+ 프로필은 현재 양 플랫폼 Provider, 기본 Text/Surface/Button·필드 모서리, ContentTransition,
71
+ SegmentedControl·Tabs, ScreenLayout 및 optional OverviewScreen에 연결한다. 모든 기존 공개 컴포넌트의
72
+ 정적 recipe 경로까지 자동 반영 완료를 뜻하지 않는다. ScreenLayout의 기존 기본 배치는 프로필이 없으면 유지한다.
73
+ 유리의 실제 backdrop blur와 클레이 inset shadow는 아래 Surface 질감 계약으로 연결한다. Native의 선택형 host·OS·architecture 조건과 실제 기기 검증은 별도다.
74
+
75
+
76
+ ## 큰 제목까지 한 번에 지정하기
77
+
78
+ `tokens.heading`은 `level1`~`level5`의 fontSize/lineHeight/fontWeight를 부분 지정한다.
79
+ 현재 Heading은 두 renderer 모두 이 값으로 그리고 문서 `semanticLevel`과 textScale을
80
+ 따로 유지한다. 중립은 foundation의 40/32/24/20/18px를 그대로 쓰며, 에디토리얼의
81
+ level1/2는 44/34px·행간 54/44px·굵기 500, 브루탈리즘은 48/38px·행간 56/46px·굵기
82
+ 800이다. 이 두 큰 제목 선택은 원본 치수 복제가 아니라 편집형/강한 강조 프리셋의
83
+ 시각 계층을 구분한 HJM 실험값이며 좁은 폭·큰 글자 QA와 함께 판단한다.
84
+
85
+ ```ts
86
+ const productDesign = defineHjmDesignProfile({
87
+ extends: "paper",
88
+ tokens: { heading: { level1: { fontSize: 52, lineHeight: 64, fontWeight: "500" } } },
89
+ });
90
+ ```
91
+
92
+ 미지정 값은 preset을 상속한다. `tokens.typography.heading/titleLarge/title`은 이전과
93
+ 같이 Heading level3/4/5의 변경 기본값이며, 같은 필드에 명시한 `tokens.heading`이
94
+ 우선한다. 나머지 프로필 축·본문 Text typography와 문서 순서는 바꾸지 않는다.
95
+ 지원하지 않는 persisted heading 단계는 조용히 무시하지 않고 거부한다.
96
+
97
+ ## 오버레이·선택 입력의 프로필 연결 보완
98
+
99
+ 2026-10-07 실제 소비 경로 대조에서 Web의 Dialog/Sheet/Toast 전용 그림자 변수와 Native의
100
+ Dialog/AlertDialog/Sheet, Select/Combobox, Notice/Progress/Skeleton/Toast가 프로필의 해당
101
+ 역할 대신 foundation/recipe 값을 직접 읽었다. Provider 값만 바꾸는 방식으로는 동일 화면의
102
+ 카드와 열린 오버레이가 다른 표현을 유지했으므로 기존 API의 소비 경로를 연결했다.
103
+
104
+ - Web Dialog/Sheet/Toast와 Native Dialog/AlertDialog/Sheet/일반 Toast는 `tokens.shadow.floating`을
105
+ 읽는다. 프로필 없는 소비자는 각 recipe의 기존 그림자와 Native elevation을 유지한다.
106
+ - Native에서 모서리의 역할 이름은 각 recipe가 정하고 값은 Provider의 `tokens.radius`가 정한다.
107
+ 원·pill의 full=999, Sheet 하단의 바닥 모서리 0, 명시한 Skeleton 반지름은 유지한다.
108
+ - Android elevation은 별도 플랫폼 그림자를 그리므로 프로필 opacity=0이면 elevation도 0이다.
109
+ 나머지는 radius/offsetY의 최대값으로 근사한다. CSS blur와 기기 그림자의 픽셀 동등성을 뜻하지
110
+ 않는다. [플랫폼 근거](https://reactnative.dev/docs/view-style-props#elevation).
111
+ - 액션·선택·초안·Modal lifecycle·safe area·키보드 처리는 바꾸지 않는다. Liquid Toast의
112
+ managed presentation은 기존 별도 표현 host가 계속 소유한다.
113
+
114
+ 기존 테마 조합 실험에서 Notice/Skeleton/Toast와 Dialog/Sheet를 직접 열고, 오버레이 안의
115
+ 다음 테마 버튼으로 10종을 순회한다. 같은 제어 초안을 닫기/재열기에서도 유지한다.
116
+ Web의 10개 밝은 Dialog와 10개 dark/RTL/2배 Sheet 및 390px 검토는 위 QA 기록에 있다.
117
+ Native 테스트는 실제 기기의 표시·VoiceOver 증거가 아니다. 오버레이 토큰 연결만으로 모든 질감이 적용되는 것은 아니다. 아래 Surface 질감 연결과 별도로 남은 다른 컴포넌트의 직접 토큰/recipe 소비 경로도 계속 대조한다.
118
+
119
+
120
+ ## Surface/Card의 유리·클레이 질감
121
+
122
+ 2026-10-07 원본 대조에서 유리는 glow만, 클레이는 grain만 있어 물리적인 표면 표현이 빠져 있었다.
123
+ `material.surface`를 기존 Surface와 그 소비자인 Card에 연결한다. 새 wrapper나 상태 엔진을 만들지 않는다.
124
+ EffectSurface는 mesh/glow/noise/grain 장식이며, ProgressiveBlur는 스크롤·입력 가림을 판단하는 가장자리
125
+ 마스크다. 배경 영역 전체의 blur/inset은 이들과 역할이 달라 Surface가 소유한다.
126
+
127
+ | 필드 | 중립/미지정 | 범위와 실제 사용 |
128
+ | --- | --- | --- |
129
+ | `material.surface` | null | 부분 객체는 선택 preset의 surface를 상속, null은 해당 처리를 해제 |
130
+ | `blurStrength` | 0 | 0~1. glass 0.75 → Web 24px. Native host의 강도는 기기별로 보정하며 픽셀 동등성 아님 |
131
+ | `fillOpacity` | 1 | 0.85~1. glass 요청 0.88. blur가 0이거나 지원되지 않으면 불투명 |
132
+ | `insetShadows` | 빈 배열 | 최대 2개. color 6자리 HEX·opacity 0~1·radius 0~96·offsetX/Y -96~96 |
133
+
134
+ clay의 안쪽 빛은 white/0.22/radius10/offset3,4, 그림자는 black/0.12/radius12/offset-3,-4다.
135
+ 밝은 glass의 textSub=#5b6879·textWeak=#748292는 중립 팔레트의 약한 색이 대비 보정에서 opacity=1을
136
+ 요구했던 실제 비교 결과 때문에 더 짙게 정했다. 대비 기준을 낮추지 않고 질감과 읽기 경계를 함께 유지한다.
137
+ 이 값은 외부 원본 치수·브랜드색의 복사가 아니라 HJM의 정적인 표면 실험값이다. 바깥 그림자는 기존
138
+ `tokens.shadow.floating`, 모서리는 같은 `tokens.radius` 역할을 계속 읽는다.
139
+
140
+ ```ts
141
+ const productDesign = defineHjmDesignProfile({
142
+ extends: "glass",
143
+ material: { surface: { blurStrength: 0.5 } },
144
+ });
145
+ ```
146
+
147
+ `resolveDesignProfileSurfaceMaterial(profile, finalThemePalette)`는 Provider의 최종 제품 팔레트에서
148
+ bg 위의 기존 대비 쌍이 검정/흰색 배경 합성 후에도 유지되도록 요청 opacity를 0.01씩 높인다.
149
+ 질감 뒤의 실제 이미지가 글자 대비의 근거가 될 수 없기 때문이다. 두 renderer는 같은 엔진인
150
+ `@hjmds/design-contracts/palette-contrast`의 `resolveSurfaceFillOpacity(requested, palette)`를 읽는다.
151
+ 이 palette-only 진입점을 재사용해 일반 Provider가 선택형 전체 preset registry를 runtime import하지 않는다. 이 함수는 장식·선택된 입력·이미지·
152
+ 실제 화면 전체 접근성을 인증하지 않는다. inset의 가장자리와 미디어/결과 상태는 실제 화면에서도 확인한다.
153
+
154
+ ### Web
155
+
156
+ Provider가 네 surface CSS 변수를 매번 해석한다. 중첩 neutral은 상위 glass/clay를 지운다.
157
+ 실제 `backdrop-filter` 또는 Safari의 prefixed 속성을 지원할 때만 투명 fill을 쓰고, OS
158
+ `prefers-reduced-transparency: reduce`이면 opaque/none으로 대체한다. blur=0이면 `none`으로
159
+ 내보내므로 평범한 Surface에 불필요한 backdrop stacking context를 만들지 않는다.
160
+
161
+ ### Native의 한 번 등록하는 host
162
+
163
+ `HjmNativeProvider.surfaceEffects`는 `renderBackdrop({ strength, theme })`와 `insetShadows`를
164
+ 제품 루트에서 공급한다. 중첩 Provider는 그대로 상속하며 `{}`는 그 subtree를 해제한다.
165
+ core renderer는 Expo/Skia/blur 라이브러리를 import하지 않는다. `renderBackdrop`은 실제 backdrop
166
+ React element를 반환하고 사용할 수 없으면 null을 반환한다. callback은 앱 setup에서 안정적으로 둔다.
167
+
168
+ - iOS는 [AccessibilityInfo](https://reactnative.dev/docs/0.81/accessibilityinfo)의 투명도 줄이기 설정을
169
+ 한 번 관찰한다. unknown/reject/설정 활성화는 불투명이다. 실시간 이벤트가 초기 비동기 응답보다 우선한다.
170
+ - 장식만 pointer/접근성에서 제외하고 모서리 clip을 한다. 본문은 stable keyed sibling이므로 optional host
171
+ 실패·테마 전환이 초안을 remount하지 않는다. 실패는 opaque로 대체하고 host 함수 교체/질감 변경 때만 재시도한다.
172
+ - `insetShadows=true`는 제품이 [RN New Architecture와 Android API 29 이상](https://reactnative.dev/docs/0.81/view-style-props#boxshadow)을 확인한 경우만 쓴다. 기본 false이며 core는 기존 architecture도 지원한다.
173
+ - [Expo BlurView](https://docs.expo.dev/versions/latest/sdk/blur-view/)를 쓰는 Android 제품은 먼저 렌더한
174
+ BlurTargetView의 ref를 host에 공급한다. Target은 효과가 그려지는 범위를 덮어야 한다. Showcase는 API31 미만을
175
+ 불투명으로 유지하며, 지원 기기에서 strength×100과 `dimezisBlurViewSdk31Plus`를 쓴다.
176
+
177
+ ```tsx
178
+ // 선택형 blur 모듈이 설치된 제품 host. capability 확인과 Target 배경은 제품 setup 소유.
179
+ const effects = useMemo(() => ({
180
+ insetShadows: hostSupportsInsetShadows,
181
+ renderBackdrop: ({ strength, theme }: { strength: number; theme: "light" | "dark" }) =>
182
+ hostSupportsBlur ? <BlurView style={StyleSheet.absoluteFill} blurTarget={targetRef}
183
+ intensity={strength * 100} tint={theme} blurMethod="dimezisBlurViewSdk31Plus" /> : null,
184
+ }), [hostSupportsBlur, hostSupportsInsetShadows, targetRef]);
185
+
186
+ <HjmNativeProvider designProfile={productDesign} surfaceEffects={effects}>{children}</HjmNativeProvider>
187
+ ```
188
+
189
+ 실험 ‘테마 조합’의 무늬 배경 위 공개 Card에서 입력한 초안과 다음 테마 버튼으로 비교한다.
190
+ Web 실제 표시·Native mock-host 회귀·기기 미확인 범위는 [QA 기록](../../../docs/qa/2026-10-07-design-profile-research.md)에 보존한다.
191
+ 오버레이/상단 바 등 Surface를 쓰지 않는 모든 공개 소비자에 이 material까지 반영 완료한 것은 아니다.
192
+
193
+
194
+ ## 모서리·서체 소비 경로 보완
195
+
196
+ 2026-10-07 후속 감사에서 Native의 날짜·태그·약관·목록·메뉴·상단 바·저장 컬렉션 등은
197
+ recipe가 정한 역할을 foundation에서 직접 읽어 프로필의 모서리를 놓쳤다. 같은 공개 API가
198
+ Provider의 `tokens.radius`에서 역할을 해석하도록 연결했다. 원·pill의 full, 날짜 셀의 원형,
199
+ selection glyph의 고정 geometry는 별도 계약으로 유지한다. 테마가 상태 엔진을 대체하지 않는다.
200
+
201
+ PasswordField large, Calendar custom content, CodeBlock, optional GestureSheetInput도
202
+ Provider typography를 읽는다. PasswordField는 같은 줄 높이로 프레임을 계산하며 size recipe는
203
+ 최소 높이로만 사용한다. CodeBlock의 `fontFamily.code`는 Web CSS 변수와 Native host로 연결하고
204
+ 글자 확대는 한 번만 적용한다. 사용자 font 등록·실기기 glyph/줄바꿈은 제품 검증 대상이다.
205
+
206
+ 구조 비교 근거: [Tailwind theme 변수](https://tailwindcss.com/docs/theme)는 서체·모서리 등
207
+ 범주별 token과 실제 소비 utility를 연결하고, [shadcn theme](https://ui.shadcn.com/docs/theming)는
208
+ semantic foreground/background와 공유 radius scale을 소비 컴포넌트에 연결한다. HJM도 기존
209
+ semantic role을 재사용하되 CSS 생성기·단일 비율 radius를 새 의존성으로 도입하지 않는다.
210
+ 기존 프로필의 sm/md/lg/xl 개별 값과 네이티브 번역·상태 계약을 유지하는 선택이다.
211
+
212
+
213
+ ## Native UI 서체의 실제 host 연결
214
+
215
+ 2026-10-07 raw Text/TextInput 대조에서 Text는 UI 서체를 읽었지만 FieldRenderer,
216
+ Combobox, NumberField, Slider, TagsInput, optional GestureSheetInput과 CodeBlock 제목은
217
+ 시스템 서체를 유지했다. [React Native 텍스트 상속](https://reactnative.dev/docs/text)은 Text
218
+ 하위 트리에 한정되므로 상위 View 스타일만으로 해결하지 않는다. 내부 font resolver를 공유하고
219
+ 각 입력/라벨 host에서 Provider의 UI 역할을 읽는다. CodeBlock 원문만 code 역할을 유지한다.
220
+ 고정 체크·닫기 glyph와 투명 OTP editor는 기존 의미를 유지한다.
221
+
222
+ 기본 UI stack 전체는 Native OS 서체로 유지한다. 첫 항목만 비교하면 제품이 직접 등록한
223
+ `ui: ["Inter"]`까지 기본 stack으로 오인하므로 전체 stack과 비교한다. 제품의 명시적인 named
224
+ font는 첫 항목을 Native에 전달한다. Native는 CSS fallback 목록을 그대로 해석하지 않는다.
225
+ `ui-monospace`/`monospace`는 기존 iOS Menlo·Android monospace로 번역한다. 나머지 제품 font는
226
+ 유효한 플랫폼 등록 이름과 글리프/굵기 지원을 제품이 검증해야 한다. 제품 자산은 HJM에 번들하지 않는다.
227
+
228
+ TagsInput의 실제 입력칸은 body 글자·줄 높이와 같은 controlled scale을 한 번만 읽는다.
229
+ 부모/중첩 프로필 전환은 입력 요소·초안·NumberField의 미확정 숫자·검색어를 유지한다.
230
+ [Refero token 지침](https://styles.refero.design/ai-agents/css-variables-design-tokens)의 역할 소비,
231
+ [컴포넌트 비교](https://styles.refero.design/ai-agents/component-design-prompts)의 반복되는 서체 역할,
232
+ [검수 지침](https://styles.refero.design/ai-agents/agentic-ui-quality-checklist)의 실제 상태 검토를
233
+ 기존 HJM 계약과 대조한 후속 보완이다. linked 제품 소스와 모든 상태를 검수한 결과는 아니다.
234
+ 실제 기기의 폰트 로딩·텍스트 줄바꿈·접근성 증거는 계속 별도 검증한다.
235
+
236
+ ## 팝오버와 하단 chrome의 그림자 상속
237
+
238
+ 2026-10-07 추가 소비 감사에서 Web Popover의 inline recipe 값과 Native BottomCTA·
239
+ floating/capsule BottomNavigation의 recipe 그림자가 프로필을 우회하는 것을 확인했다.
240
+ 기존 API에 `shadow.floating`을 연결했다. bar는 무그림자를 유지하고 BottomCTA는 footer가
241
+ 위 콘텐츠와 겹치는 역할이라 offsetY의 절댓값을 위쪽으로 뒤집는다(bottomCtaRecipe 근거).
242
+ 별도의 그림자 토큰/엔진을 추가하지 않는다. Native의 0-opacity는 iOS 값뿐 아니라 기존
243
+ 공통 helper로 Android elevation도 제거한다. 프로필 없는 경로는 이전 renderer 외형이다.
244
+
245
+ 양 Showcase의 같은 저장/실패 행동은 공개 BottomCTA로 비교하고 Web chrome 비교에는
246
+ 기존 공개 Popover를 연결했다. 열린 초안/포커스·safe area·선택 route·행동 소유권 검증과
247
+ Native 기기 미확인 범위는 [QA](../../../docs/qa/2026-10-07-design-profile-research.md)에 남긴다.
248
+
249
+ ## 선택형 리퀴드 알림의 프로필 소비
250
+
251
+ 2026-10-07 optional Native `/toast-liquid`를 별도로 대조한 결과 settled 카드와 RN 내용 clip은
252
+ 고정 모서리 12, Skia 그림자는 foundation `raised`를 읽고 있었다. 가장 가까운 프로필의
253
+ `radius.lg`와 `shadow.raised`로 연결한다. 일반 Toast의 `floating`과 합치지 않은 이유는
254
+ [기존 깊이 검토](../../react-native/docs/liquid-toast.md#current-shape--2026-10-02)에서 정한 얕은 카드 역할이다.
255
+ 프로필 없는 소비자는 이전 12와 raised를 유지한다. 그림자의 양방향 offset을 포함해 Canvas
256
+ 네 가장자리의 paint 여유를 함께 계산한다. 프로필이 얕은/무그림자를 고르면 그 값도 그대로 소비한다.
257
+
258
+ `buildLiquidToastGeometry`는 네 번째 선택 인자로 유한한 0 이상 settled radius를 받는다(기본 12).
259
+ 모서리는 측정 폭·높이의 절반으로 제한한다. 원형 origin, 큐, 행동·닫힘, 모션 감소·화면 읽기
260
+ fallback은 유지한다. Web은 일반 Toast fallback이므로 Native 효과를 양 플랫폼 제공으로 세지 않는다.
261
+ 기존 테마 비교 구성의 Native 예제로 같은 visible 알림을 보존한 채 10종을 순회한다.
262
+ 선택 peer는 optional subpath에 유지하며 새 공개 컴포넌트나 상태 엔진을 추가하지 않는다.
263
+ 실제 기기 외형·제스처·음성·성능은 [QA](../../../docs/qa/2026-10-07-design-profile-research.md)의 미확인 범위다.
@@ -143,3 +143,10 @@ catalog 상태는 `beta`다. Web과 RN, 두 제품에서 값 해석·Context 전
143
143
  중첩 Provider의 omitted axis 상속 경계까지 확인됐다. 다만 이 상속 adapter가 포함된
144
144
  추가 제품 릴리스 증거는 아직 없으므로 roadmap은 다음 승격 조건을
145
145
  `evidence-needed`로 기록하고 `stable`을 과장하지 않는다.
146
+
147
+ ## 디자인 프로필 연결(실험·미게시)
148
+
149
+ 2026-10-07 사용자 요청으로 options의 `designProfile`에 정규화한 프로필을 받고 해석된 값에도 전달한다.
150
+ 기본 semantic 팔레트는 프로필의 현재 테마 값이며 `brandPalette`가 그 위에 병합된다. 환경·상태 강조색은
151
+ 기존 계약을 유지한다. 코어 Provider는 프로필 레지스트리를 런타임 import하지 않는다(type-only).
152
+ renderer 기본값·선택 기준·부분 상속은 [디자인 프로필 계약](design-profile.md)을 따른다.
package/docs/dialog.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Dialog
2
2
 
3
3
  Dialog provides a modal boundary for a task that needs the user's attention. This
4
- Reviewed: 2026-10-05. The original
4
+ Reviewed: 2026-10-07. The original
5
5
  contract was recorded during the 2026-09-29 promotion audit because Web and Native
6
6
  already had different title APIs and dismissal sources, while there was no single
7
7
  component guide describing their shared behavior.
@@ -45,3 +45,22 @@ screen-reader behavior remains a separate consumer validation concern.
45
45
  Native accessibility follow-up (2026-10-01): at 200% text scale, the close glyph was clipped inside the fixed IconButton frame. Dialog and Sheet now render that decorative glyph at a fixed icon size, matching Toast; title/body text still scales and the named close action and touch target are preserved. `sheet-viewport.test.tsx` checks both renderers and close callbacks.
46
46
 
47
47
  Native viewport candidate (BT-QA-027, 2026-10-05): BurnTok local QA exposed a long confirmation extending beyond the visible screen. Dialog and AlertDialog now constrain the content surface and provide a shrinking scroll body, with actions outside that body and provider safe-area padding. Host tests cover those structural contracts and cancellation; they cannot prove Yoga geometry. Ordinary-size iOS confirmation and cancellation were checked. Enlarged-text device verification remains pending: the user stopped that QA scope before the candidate was confirmed, so this is not a completed device fix. Font caps and clipped copy were rejected because they remove readable content.
48
+
49
+ ## Optional measured origin motion (published API, experimental presentation)
50
+
51
+ 2026-10-07 Aceternity card/grid comparison exposed a stale publication label here.
52
+ Both npm 1.14.0 renderer tarballs include `DialogProps.motionOrigin` in `dist/overlays.d.ts`,
53
+ matching release commit `8d6f665`. Publication does not close the device/performance debt below.
54
+
55
+ `motionOrigin` supplies a trigger rectangle measured immediately before opening in the same physical
56
+ viewport/window coordinate system as the destination. The existing content-transition resolver supplies
57
+ the inverse transform. Source investigation found lost trigger focus and discarded drafts in the external
58
+ Morphing Dialog/Popover demos, so this presentation reuses canonical Dialog state rather than replacing
59
+ the modal engine. It does not implement shared image/text identities or a new Popover engine.
60
+
61
+ Web retains one subtree through exit and suppresses stale animation completion when reopened.
62
+ Native uses the actual modal measurement and bounds its optional measurement wait by the existing
63
+ enter duration, falling back to ordinary presentation if the host fails to reply. Reduced motion skips
64
+ spatial interpolation. Device geometry, resizing/keyboard behavior, themes and performance remain
65
+ experimental until the QA report verifies them. See the usage guide and
66
+ [origin transition QA](../../../docs/qa/2026-10-07-overlay-origin-transition.md).
@@ -1,10 +1,10 @@
1
1
  # Composable decorative surfaces
2
2
 
3
- 2026-10-01. Optional Web/Native presentation, independent implementation inspired
3
+ 2026-10-07. Optional Web/Native presentation, independent implementation inspired
4
4
  by layered shader composition. No Shaders.com engine, presets or source is shipped.
5
5
 
6
6
  Import `EffectSurface` from the renderer `/effect-surface` entry. The shared
7
- `/effect-surface` contract accepts unique `layers` (`mesh`, `glow`, `grain`), a
7
+ `/effect-surface` contract accepts unique `layers` (`mesh`, `glow`, `grain`, `noise`), a
8
8
  stable `seed`, `intensity` from 0 to 1, a cycle `period` from 2 to 120 seconds,
9
9
  `active` (false by default), and three semantic color references. Web uses local
10
10
  SVG/WAAPI; Native requires the existing optional SVG peer and core Animated.
@@ -24,7 +24,7 @@ The static seeded geometry and the base theme background stay visible when motio
24
24
  stops. Effects never duplicate content, take focus, intercept touches or add an
25
25
  accessible name. The content itself stays in normal layout.
26
26
 
27
- Noise uses a seeded repeating small-dot tile rather than large spots. Geometry
27
+ The existing grain uses a seeded repeating small-dot tile rather than large spots. Geometry
28
28
  is shared, while host rasterization and transform details can differ. This is
29
29
  atmospheric parity, not a pixel-identical renderer promise. Motion is opt-in and
30
30
  slow by default to avoid adding continuous work to ordinary content screens.
@@ -48,3 +48,19 @@ A failed Native foreground animation start keeps the static decoration and stops
48
48
  retrying for that effect lifecycle. Descriptor validation stays outside this
49
49
  fallback so invalid caller input is still reported. This implements integration
50
50
  plan §5's requirement that decorative failures must not remove product content.
51
+
52
+
53
+ ## Static noise comparison (unpublished after 1.13.1)
54
+
55
+ The opt-in `noise` layer uses an original 64×64 periodic six-octave value-noise
56
+ alpha tile, generated by `scripts/generate-effect-noise.py`. Both renderers tint
57
+ it with the current theme text color via an SVG mask. Its 64×64 tile repeats in physical host units outside
58
+ the existing geometric 100×100 viewBox; seed shifts the phase. It is not pixel-identical to
59
+ SVG feTurbulence/Perlin noise and grain remains unchanged.
60
+
61
+ Reason: the installed react-native-svg15.15.5 FeTurbulence.render warns and returns
62
+ null. A shared static mask keeps both hosts visible without a new native/GPU
63
+ peer or per-frame noise generation. Magic UI's reference motivated the comparison,
64
+ but no source or asset from that component is included. Check actual readability
65
+ and rasterization cost before using it over product text. The comparison is at
66
+ `실험/구성/정보 표시/질감 비교`; it is not a promotion of the new layer.
@@ -1,6 +1,6 @@
1
1
  # Component maturity and evidence manifest
2
2
 
3
- > Generated from `@hjmds/design-contracts` 1.13.1. Do not edit this file directly; run `pnpm contracts:sync`.
3
+ > Generated from `@hjmds/design-contracts` 1.15.0. Do not edit this file directly; run `pnpm contracts:sync`.
4
4
 
5
5
  This document is the human-readable projection of the same catalog and Showcase manifest consumed by product CI.
6
6
 
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "designSystemVersion": "1.13.1",
3
+ "designSystemVersion": "1.15.0",
4
4
  "source": "packages/design-contracts/docs/generated/showcase-manifest.json",
5
5
  "surfaces": {
6
6
  "web": {
7
7
  "packageName": "@hjmds/react",
8
- "packageVersion": "1.13.1",
8
+ "packageVersion": "1.15.0",
9
9
  "activeComponents": 103,
10
10
  "claimedComponents": 103,
11
11
  "completeScenarioComponents": 103,
@@ -5642,7 +5642,7 @@
5642
5642
  },
5643
5643
  "native": {
5644
5644
  "packageName": "@hjmds/react-native",
5645
- "packageVersion": "1.13.1",
5645
+ "packageVersion": "1.15.0",
5646
5646
  "activeComponents": 83,
5647
5647
  "claimedComponents": 83,
5648
5648
  "completeScenarioComponents": 83,
@@ -1,6 +1,6 @@
1
1
  # Renderer evidence coverage
2
2
 
3
- > Generated for HJM 1.13.1. Do not edit directly; run `pnpm evidence:sync`.
3
+ > Generated for HJM 1.15.0. Do not edit directly; run `pnpm evidence:sync`.
4
4
 
5
5
  This projection joins the canonical surface maturity manifest with first-party renderer claims. Missing scenarios are explicit beta promotion debt; stable surfaces are blocked by CI until none remain.
6
6
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "designSystemVersion": "1.13.1",
3
+ "designSystemVersion": "1.15.0",
4
4
  "packageName": "@hjmds/design-contracts",
5
5
  "components": [
6
6
  {
@@ -1,10 +1,13 @@
1
1
  # Gooey navigation
2
2
 
3
- Reviewed: 2026-10-01
3
+ Reviewed: 2026-10-07
4
4
 
5
5
  Use the existing `Tabs` from `@hjmds/react/navigation` or
6
- `@hjmds/react-native/navigation` with `appearance="gooey"`. The default remains
7
- `standard`. A new navigation controller would duplicate existing selection,
6
+ `@hjmds/react-native/navigation` with an explicit `appearance="standard"`, `"slide"` or `"gooey"`.
7
+ The unpublished follow-up after 1.14.0 inherits `designProfile.interactions.selectionMotion`
8
+ when appearance is omitted: `slide` selects a plain moving line and `none` selects
9
+ `standard`. Without a profile the default remains `standard`. Explicit appearance
10
+ wins over the profile. A new navigation controller would duplicate existing selection,
8
11
  keyboard, disabled-item and panel contracts, so only the selected indicator is
9
12
  extended. Vertical tabs deliberately retain the standard line: stretching a
10
13
  horizontal bridge across a vertical list would obscure unrelated items.
@@ -21,10 +24,11 @@ coordinates also support RTL and horizontal scrolling.
21
24
  Reduced motion, backgrounding and cleanup settle the indicator without changing
22
25
  selection. Native width animation uses Core Animated's JS driver because width
23
26
  cannot use the native transform driver without distorting corner radii. No new
24
- optional animation dependency is introduced. Rapid re-selection targets the last
25
- selected tab; this is deterministic selection feedback, not a physics simulation.
27
+ optional animation dependency is introduced. Rapid re-selection captures the visible intermediate bounds before cancellation
28
+ and starts the next animation there, while selection targets the last chosen tab.
29
+ This is deterministic selection feedback, not a physics simulation.
26
30
 
27
- Both Storybooks expose `컴포넌트 / 탐색 / Gooey Navigation` with Default,
31
+ Both Storybooks expose `배포/컴포넌트/탐색/선택 표시가 이어지는 탭` with Default,
28
32
  Dark and LargeText plus a direction toggle. Disabled tabs, existing activation
29
33
  mode and panel associations remain canonical. The Native renderer is tested with
30
34
  mock layout events; actual device appearance remains to be verified.
@@ -34,3 +38,30 @@ content bounds when selection, direction or viewport width changes. This correct
34
38
  LargeText RTL selected-label clipping issue found in the [device flow audit](../../../docs/evidence/component-flows-2026-10-01/README.md).
35
39
  The standard appearance shares this behavior; fitted and non-scrollable lists do not
36
40
  programmatically scroll. Selection semantics and the host's panel ownership are unchanged.
41
+
42
+ ## Plain sliding and profile inheritance (unpublished after 1.14.0)
43
+
44
+ The Aceternity [comparison](../../../docs/plans/aceternity-interaction-adoption-2026-10-07.md)
45
+ found that profile sliding reached SegmentedControl but not Tabs. The existing
46
+ Tabs renderer now resolves the appearance through `resolveTabsAppearance`;
47
+ selection, keyboard, disabled items and panel mounting keep their existing owner.
48
+ It does not recreate stacked panels or shared-element content transitions.
49
+
50
+ `resolveTabIndicator` uses the shared `motion.normal` (200ms) and
51
+ `easing.standard` for plain sliding: source and destination x/width interpolate
52
+ without the elastic union bridge. Plain/standard indicators keep the existing
53
+ 2-point height; explicit gooey keeps its 6-point decorative geometry, 320ms bridge
54
+ and established platform easing. Vertical orientation always resolves to standard.
55
+
56
+ Web tracks list and tab measurements, including fitted RTL width changes, and
57
+ samples running or paused WAAPI frames before cancellation. Native tracks its
58
+ JS-driver frame in a ref through an Animated listener, removed on cleanup. This
59
+ adds no animation dependency or per-frame React render. Background/reduced motion
60
+ settles the indicator at the selected tab.
61
+
62
+ `실험/구성/비교와 검증/테마 조합` compares inherited, standard, slide and gooey
63
+ through the public Tabs API with visited panel mounting. Changing a theme does
64
+ not choose a different panel lifetime: products still own controlled drafts or
65
+ `mountPolicy`. The [QA record](../../../docs/qa/2026-10-07-design-profile-research.md)
66
+ separates actual Chromium checks from Native mock-host tests; Native device
67
+ appearance/performance and experiment promotion remain pending.
package/docs/heading.md CHANGED
@@ -23,3 +23,18 @@ level5 18px까지 다섯 단계가 있었지만 어떤 renderer도 노출하지
23
23
  구조를 왜곡하는 대신 둘을 따로 적는다. 생략하면 `level`의 숫자를 따른다.
24
24
 
25
25
  **Native.** 접근성 role은 `header` 하나뿐이라 문서 단계는 `aria-level`로 함께 싣는다.
26
+
27
+
28
+ ## 디자인 프로필의 전체 제목 크기(실험·미게시)
29
+
30
+ 2026-10-07 [Heading 갤러리](https://component.gallery/components/heading/)를 비교하며
31
+ 현재 renderer가 level3~5만 프로필 typography에 연결하고 level1/2는 고정값으로 남긴
32
+ 누락을 확인했다. 앱이 테마를 한 번 넣어 큰 제목까지 재사용하려는 요구 때문에
33
+ [디자인 프로필](design-profile.md)의 `tokens.heading`을 다섯 시각 단계로 둔다.
34
+ 본문 크기에서 큰 제목을 임의로 배율 계산하는 대안은 계층과 행간이 달라질 수 있어
35
+ 채택하지 않는다. 원본 갤러리의 수치·코드·폰트 자산을 복사한 것이 아니다.
36
+
37
+ 프로필이 없으면 원래 40/32/24/20/18 크기를 유지한다. 기존 level3~5 typography
38
+ alias는 helper에서 병합하고 명시적인 heading override가 마지막에 우선한다.
39
+ Web은 CSS 변수, Native는 Text host의 metrics로 반영하고 `semanticLevel`·문구·초점을
40
+ 바꾸지 않는다. 테마 전환은 시각 크기만 바꾸며 실제 문서 단계는 기존 계약이 소유한다.
package/docs/image.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Image contract
2
2
 
3
+ ## 정확한 결과 크기 검사 — 2026-10-07, 미게시
4
+
5
+ Utilverse ADR-0020의 사진 결과 확인은 fit·2배·출력 크기를 구분한다. 기존 Image의 cover/contain/fill은
6
+ 요소 안에서 이미지를 맞추는 방법이며, 확대 검사 viewport/이동 경계와 다르다. 새 이미지 primitive를
7
+ 만들지 않고 기존 `components/image` subpath에 `resolveImageInspectionGeometry(image, viewport, mode)`를 추가한다.
8
+
9
+ - `mode`: `fit`은 남은 viewport에 전체 이미지를 맞추며 작은 이미지는 확대한다. `double`은 그 2배다.
10
+ - `pixels`: 출력 이미지의 width/height와 같은 layout 단위. 기기의 물리 pixel과 1:1이라는 뜻이 아니다.
11
+ - 반환은 scale/width/height와 중앙 기준 양·음 이동 한계 panBounds.x/y다. 모자라는 축의 이동 한계는 0이다.
12
+ - image/viewport 크기는 양수·유한값이어야 한다. 미측정 0이나 계산 overflow는 RangeError로 거절한다.
13
+ 알려지지 않은 mode는 TypeError다. renderer는 실제 viewport 측정 후 호출해야 한다.
14
+
15
+ 600×600 사진, 402×454 viewport의 2배는 804×804, 이동 한계는 x ±201/y ±175다. iOS의
16
+ zoom-toolkit Gallery는 scale=1 상태의 세로 pan을 pull로 처리해 손을 떼면 0으로 돌려보냈다.
17
+ 같은 peer의 ResumableZoom에서는 위 한계를 실측했다. Gallery private scale을 바꾸거나 원본 크기를
18
+ 속이지 않는다. 이 순수 geometry는 아직 ImageViewer의 공개 배율 UI에 연결되지 않았다.
19
+
3
20
  **문제.** 이 시스템에 이미지가 하나도 없었습니다. 사진 콘텐츠(선수 프로필 사진, FA 등급
4
21
  차트 이미지)를 레이아웃 밀림 없이, 로드 실패에도 의미를 잃지 않게 보여 주는 첫 계약입니다.
5
22
 
@@ -1,5 +1,30 @@
1
1
  # Optional presentation adapters
2
2
 
3
+ ## Image host extension — 2026-10-07 (unpublished)
4
+
5
+ Native ImageViewer accepts `renderImage` with the item, measured viewport width/height and
6
+ `onReady`/`onError`. This lets a product retain Expo display events and cache policy without
7
+ adding Expo to the adapter. `onImageStatusChange` reports loading/ready/error for every mounted
8
+ item, including offscreen pages. It is not current-page visibility or user review approval.
9
+ Default RN Image still uses onLoad; an Expo consumer can use onDisplay instead. Retry remounts
10
+ the image host, and callbacks from retired attempts or closed/replaced sessions are ignored.
11
+ Failure stays terminal until retry. Closing sends no final status event; the product owns
12
+ review invalidation on close, replacement and view-mode changes. This closes the host gap
13
+ identified in Utilverse ADR-0020. The optional controlled `inspection` config adds fit/2x/output-size
14
+ review using positive intrinsic item width/height, the shared image geometry resolver and ResumableZoom.
15
+ It fixes the image scale and provides clamped pan plus non-drag directional/center controls; the
16
+ ordinary Gallery keeps its pinch/paging behavior when inspection is absent. Inspection pages use
17
+ previous/next buttons, not swipe paging. Mode, viewport, item and retry changes remount the host,
18
+ retire callbacks and reset readiness/position. Output-size means layout units, not physical device pixels.
19
+ Host width/height are the computed image dimensions in inspection mode (possibly larger than the viewport).
20
+ The [image usage guide](usage/components/image.md) defines labels, placement and review invalidation.
21
+ This is unpublished and is not proof of Expo onDisplay validation or Utilverse adoption.
22
+ The Native Modal accepts supportedOrientations in fullScreen presentation. Optional left/right
23
+ safe-area insets protect controls and feedback in landscape while the gallery remains full width.
24
+ Products must supply updated insets and permit rotation in their manifests; OS rotation lock still applies.
25
+ The additive Native-only props keep this optional subpath and its existing peers; the base Image
26
+ renderers retain their own host APIs. There is no Web ImageViewer counterpart.
27
+
3
28
  ## Current evidence — 2026-09-30
4
29
 
5
30
  The six opt-in entries are implemented. The earlier checkout verification below is a historical
package/docs/popover.md CHANGED
@@ -154,3 +154,18 @@ Dialog 안의 Popover는 첫 Escape를 소유한다. 내부 Menu가 Escape를
154
154
  재시도, dismiss 정책, 중첩 modal/menu, 선택형 hover 지연과 touch/keyboard press 경로,
155
155
  320px·2배 글자·RTL·충돌 배치, exit 격리를 다룬다.
156
156
  제품 채택·실제 보조기기 검증은 남아 있다.
157
+
158
+
159
+ ## 선택적 출발 위치 전환 (미게시, 2026-10-07)
160
+
161
+ Motion Primitives의 Add Note 예제에서 닫기 후 초안과 트리거 초점이 사라지는 것을 확인했다.
162
+ 별도 MorphingPopover 상태 엔진을 도입하는 대신 기존 Popover에 `motionOrigin?: TransitionRect`를
163
+ 추가한다. viewport 좌표를 받고, 충돌 회피 위치가 확정된 후 Dialog와 공유하는 WAAPI 표현 helper를 쓴다.
164
+ 시간·easing은 Popover recipe가 소유한다. 움직이는 크기를 충돌 계산에 다시 넣으면 스크롤 중 위치가
165
+ 흔들리므로 측정에는 layout 크기를 쓴다. 기존 호출은 기존 측정·opacity 전환을 유지한다.
166
+
167
+ 이 옵션은 비모달 의미를 바꾸지 않는다. Escape/닫기는 기존 시점에 트리거로 초점을 돌리고,
168
+ 바깥 클릭/Tab은 이동한 대상의 초점을 유지한다. 닫는 동안 inert/aria-hidden이며 빠른 재열기는
169
+ 이전 animation 완료를 무시한다. 초안과 서버 저장은 제품 소유이며 portal 밖에서 보존한다.
170
+ 잘못된 좌표·모션 감소·WAAPI 미지원은 공간 전환 없이 기존 경로를 사용한다.
171
+ Native Popover는 여전히 제공하지 않는다. 모바일의 같은 편집 목적에는 Dialog/Sheet를 사용한다.
package/docs/rating.md CHANGED
@@ -1,4 +1,9 @@
1
- # Rating — 계약을 만들지 않는다
1
+ # Rating — 과거 판단과 현재 계약
2
+
3
+ > 2026-10-07 현재 상태 정정: 2026-10-06 사용자 레퍼런스 적용 요청으로 정수 선택·미평가·소수 평균을
4
+ > 구분하는 supplemental Rating을 추가했다. 현재 계약은 [reference-controls](reference-controls.md),
5
+ > import와 배치는 [사용 지침](usage/components/rating.md)을 따른다. 아래 “만들지 않는다”는 과거 판단이며
6
+ > 현재 API 부재를 뜻하지 않는다. Slider 기반 반점 입력 예제는 별도 용도로 유지한다.
2
7
 
3
8
  > 2026-09-30 정리: 구현된 조합을 미구현으로 집계하지 않도록 독립 Planned 행과 catalog ID를 제거했다.
4
9
  > 기존 조합 예제와 공개 helper는 유지하며, 참조표는 실제 구성 컴포넌트로 연결한다.