@hjmds/design-contracts 0.8.2

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 (353) hide show
  1. package/README.md +208 -0
  2. package/dist/alert-dialog.d.ts +102 -0
  3. package/dist/alert-dialog.d.ts.map +1 -0
  4. package/dist/alert-dialog.js +136 -0
  5. package/dist/alert-dialog.js.map +1 -0
  6. package/dist/base-recipes.d.ts +184 -0
  7. package/dist/base-recipes.d.ts.map +1 -0
  8. package/dist/base-recipes.js +129 -0
  9. package/dist/base-recipes.js.map +1 -0
  10. package/dist/behaviors.d.ts +1254 -0
  11. package/dist/behaviors.d.ts.map +1 -0
  12. package/dist/behaviors.js +972 -0
  13. package/dist/behaviors.js.map +1 -0
  14. package/dist/bottom-navigation-defaults.d.ts +13 -0
  15. package/dist/bottom-navigation-defaults.d.ts.map +1 -0
  16. package/dist/bottom-navigation-defaults.js +10 -0
  17. package/dist/bottom-navigation-defaults.js.map +1 -0
  18. package/dist/bottom-navigation.d.ts +114 -0
  19. package/dist/bottom-navigation.d.ts.map +1 -0
  20. package/dist/bottom-navigation.js +223 -0
  21. package/dist/bottom-navigation.js.map +1 -0
  22. package/dist/breadcrumb.d.ts +97 -0
  23. package/dist/breadcrumb.d.ts.map +1 -0
  24. package/dist/breadcrumb.js +99 -0
  25. package/dist/breadcrumb.js.map +1 -0
  26. package/dist/calendar.d.ts +285 -0
  27. package/dist/calendar.d.ts.map +1 -0
  28. package/dist/calendar.js +297 -0
  29. package/dist/calendar.js.map +1 -0
  30. package/dist/card.d.ts +39 -0
  31. package/dist/card.d.ts.map +1 -0
  32. package/dist/card.js +50 -0
  33. package/dist/card.js.map +1 -0
  34. package/dist/carousel.d.ts +180 -0
  35. package/dist/carousel.d.ts.map +1 -0
  36. package/dist/carousel.js +172 -0
  37. package/dist/carousel.js.map +1 -0
  38. package/dist/catalog.d.ts +7158 -0
  39. package/dist/catalog.d.ts.map +1 -0
  40. package/dist/catalog.js +220 -0
  41. package/dist/catalog.js.map +1 -0
  42. package/dist/collection.d.ts +123 -0
  43. package/dist/collection.d.ts.map +1 -0
  44. package/dist/collection.js +211 -0
  45. package/dist/collection.js.map +1 -0
  46. package/dist/color-references.d.ts +46 -0
  47. package/dist/color-references.d.ts.map +1 -0
  48. package/dist/color-references.js +39 -0
  49. package/dist/color-references.js.map +1 -0
  50. package/dist/colors.d.ts +56 -0
  51. package/dist/colors.d.ts.map +1 -0
  52. package/dist/colors.js +90 -0
  53. package/dist/colors.js.map +1 -0
  54. package/dist/command-palette.d.ts +240 -0
  55. package/dist/command-palette.d.ts.map +1 -0
  56. package/dist/command-palette.js +97 -0
  57. package/dist/command-palette.js.map +1 -0
  58. package/dist/component-contracts.d.ts +137 -0
  59. package/dist/component-contracts.d.ts.map +1 -0
  60. package/dist/component-contracts.js +53 -0
  61. package/dist/component-contracts.js.map +1 -0
  62. package/dist/component-definitions.d.ts +135 -0
  63. package/dist/component-definitions.d.ts.map +1 -0
  64. package/dist/component-definitions.js +142 -0
  65. package/dist/component-definitions.js.map +1 -0
  66. package/dist/component-recipes.d.ts +3583 -0
  67. package/dist/component-recipes.d.ts.map +1 -0
  68. package/dist/component-recipes.js +1503 -0
  69. package/dist/component-recipes.js.map +1 -0
  70. package/dist/component-references.d.ts +416 -0
  71. package/dist/component-references.d.ts.map +1 -0
  72. package/dist/component-references.js +140 -0
  73. package/dist/component-references.js.map +1 -0
  74. package/dist/content-state.d.ts +104 -0
  75. package/dist/content-state.d.ts.map +1 -0
  76. package/dist/content-state.js +116 -0
  77. package/dist/content-state.js.map +1 -0
  78. package/dist/counter-badge-recipe.d.ts +80 -0
  79. package/dist/counter-badge-recipe.d.ts.map +1 -0
  80. package/dist/counter-badge-recipe.js +44 -0
  81. package/dist/counter-badge-recipe.js.map +1 -0
  82. package/dist/counter-badge.d.ts +12 -0
  83. package/dist/counter-badge.d.ts.map +1 -0
  84. package/dist/counter-badge.js +21 -0
  85. package/dist/counter-badge.js.map +1 -0
  86. package/dist/data-table.d.ts +203 -0
  87. package/dist/data-table.d.ts.map +1 -0
  88. package/dist/data-table.js +182 -0
  89. package/dist/data-table.js.map +1 -0
  90. package/dist/date-picker.d.ts +268 -0
  91. package/dist/date-picker.d.ts.map +1 -0
  92. package/dist/date-picker.js +168 -0
  93. package/dist/date-picker.js.map +1 -0
  94. package/dist/description-list.d.ts +68 -0
  95. package/dist/description-list.d.ts.map +1 -0
  96. package/dist/description-list.js +85 -0
  97. package/dist/description-list.js.map +1 -0
  98. package/dist/design-system-provider.d.ts +80 -0
  99. package/dist/design-system-provider.d.ts.map +1 -0
  100. package/dist/design-system-provider.js +147 -0
  101. package/dist/design-system-provider.js.map +1 -0
  102. package/dist/evidence.d.ts +49 -0
  103. package/dist/evidence.d.ts.map +1 -0
  104. package/dist/evidence.js +133 -0
  105. package/dist/evidence.js.map +1 -0
  106. package/dist/file-picker.d.ts +183 -0
  107. package/dist/file-picker.d.ts.map +1 -0
  108. package/dist/file-picker.js +224 -0
  109. package/dist/file-picker.js.map +1 -0
  110. package/dist/floating-action-button.d.ts +143 -0
  111. package/dist/floating-action-button.d.ts.map +1 -0
  112. package/dist/floating-action-button.js +149 -0
  113. package/dist/floating-action-button.js.map +1 -0
  114. package/dist/form.d.ts +143 -0
  115. package/dist/form.d.ts.map +1 -0
  116. package/dist/form.js +206 -0
  117. package/dist/form.js.map +1 -0
  118. package/dist/foundations.d.ts +300 -0
  119. package/dist/foundations.d.ts.map +1 -0
  120. package/dist/foundations.js +238 -0
  121. package/dist/foundations.js.map +1 -0
  122. package/dist/grid.d.ts +75 -0
  123. package/dist/grid.d.ts.map +1 -0
  124. package/dist/grid.js +133 -0
  125. package/dist/grid.js.map +1 -0
  126. package/dist/icon-button-recipe.d.ts +99 -0
  127. package/dist/icon-button-recipe.d.ts.map +1 -0
  128. package/dist/icon-button-recipe.js +53 -0
  129. package/dist/icon-button-recipe.js.map +1 -0
  130. package/dist/icon.d.ts +41 -0
  131. package/dist/icon.d.ts.map +1 -0
  132. package/dist/icon.js +147 -0
  133. package/dist/icon.js.map +1 -0
  134. package/dist/image.d.ts +82 -0
  135. package/dist/image.d.ts.map +1 -0
  136. package/dist/image.js +100 -0
  137. package/dist/image.js.map +1 -0
  138. package/dist/index.d.ts +58 -0
  139. package/dist/index.d.ts.map +1 -0
  140. package/dist/index.js +66 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/layout.d.ts +118 -0
  143. package/dist/layout.d.ts.map +1 -0
  144. package/dist/layout.js +118 -0
  145. package/dist/layout.js.map +1 -0
  146. package/dist/link.d.ts +57 -0
  147. package/dist/link.d.ts.map +1 -0
  148. package/dist/link.js +142 -0
  149. package/dist/link.js.map +1 -0
  150. package/dist/load-more.d.ts +64 -0
  151. package/dist/load-more.d.ts.map +1 -0
  152. package/dist/load-more.js +124 -0
  153. package/dist/load-more.js.map +1 -0
  154. package/dist/mentions.d.ts +67 -0
  155. package/dist/mentions.d.ts.map +1 -0
  156. package/dist/mentions.js +107 -0
  157. package/dist/mentions.js.map +1 -0
  158. package/dist/number-field.d.ts +208 -0
  159. package/dist/number-field.d.ts.map +1 -0
  160. package/dist/number-field.js +247 -0
  161. package/dist/number-field.js.map +1 -0
  162. package/dist/otp-field.d.ts +152 -0
  163. package/dist/otp-field.d.ts.map +1 -0
  164. package/dist/otp-field.js +117 -0
  165. package/dist/otp-field.js.map +1 -0
  166. package/dist/pagination.d.ts +181 -0
  167. package/dist/pagination.d.ts.map +1 -0
  168. package/dist/pagination.js +226 -0
  169. package/dist/pagination.js.map +1 -0
  170. package/dist/password-field.d.ts +187 -0
  171. package/dist/password-field.d.ts.map +1 -0
  172. package/dist/password-field.js +120 -0
  173. package/dist/password-field.js.map +1 -0
  174. package/dist/popover.d.ts +152 -0
  175. package/dist/popover.d.ts.map +1 -0
  176. package/dist/popover.js +137 -0
  177. package/dist/popover.js.map +1 -0
  178. package/dist/progress-recipe.d.ts +43 -0
  179. package/dist/progress-recipe.d.ts.map +1 -0
  180. package/dist/progress-recipe.js +16 -0
  181. package/dist/progress-recipe.js.map +1 -0
  182. package/dist/recipes.d.ts +31 -0
  183. package/dist/recipes.d.ts.map +1 -0
  184. package/dist/recipes.js +46 -0
  185. package/dist/recipes.js.map +1 -0
  186. package/dist/responsive.d.ts +27 -0
  187. package/dist/responsive.d.ts.map +1 -0
  188. package/dist/responsive.js +66 -0
  189. package/dist/responsive.js.map +1 -0
  190. package/dist/result.d.ts +111 -0
  191. package/dist/result.d.ts.map +1 -0
  192. package/dist/result.js +97 -0
  193. package/dist/result.js.map +1 -0
  194. package/dist/selection-helpers.d.ts +16 -0
  195. package/dist/selection-helpers.d.ts.map +1 -0
  196. package/dist/selection-helpers.js +52 -0
  197. package/dist/selection-helpers.js.map +1 -0
  198. package/dist/semantic-colors.d.ts +275 -0
  199. package/dist/semantic-colors.d.ts.map +1 -0
  200. package/dist/semantic-colors.js +84 -0
  201. package/dist/semantic-colors.js.map +1 -0
  202. package/dist/sheet.d.ts +51 -0
  203. package/dist/sheet.d.ts.map +1 -0
  204. package/dist/sheet.js +69 -0
  205. package/dist/sheet.js.map +1 -0
  206. package/dist/showcase.d.ts +153 -0
  207. package/dist/showcase.d.ts.map +1 -0
  208. package/dist/showcase.js +210 -0
  209. package/dist/showcase.js.map +1 -0
  210. package/dist/side-panel.d.ts +199 -0
  211. package/dist/side-panel.d.ts.map +1 -0
  212. package/dist/side-panel.js +111 -0
  213. package/dist/side-panel.js.map +1 -0
  214. package/dist/slider.d.ts +138 -0
  215. package/dist/slider.d.ts.map +1 -0
  216. package/dist/slider.js +150 -0
  217. package/dist/slider.js.map +1 -0
  218. package/dist/splitter.d.ts +113 -0
  219. package/dist/splitter.d.ts.map +1 -0
  220. package/dist/splitter.js +99 -0
  221. package/dist/splitter.js.map +1 -0
  222. package/dist/statistic.d.ts +41 -0
  223. package/dist/statistic.d.ts.map +1 -0
  224. package/dist/statistic.js +76 -0
  225. package/dist/statistic.js.map +1 -0
  226. package/dist/steps.d.ts +196 -0
  227. package/dist/steps.d.ts.map +1 -0
  228. package/dist/steps.js +160 -0
  229. package/dist/steps.js.map +1 -0
  230. package/dist/tag.d.ts +128 -0
  231. package/dist/tag.d.ts.map +1 -0
  232. package/dist/tag.js +93 -0
  233. package/dist/tag.js.map +1 -0
  234. package/dist/timeline.d.ts +147 -0
  235. package/dist/timeline.d.ts.map +1 -0
  236. package/dist/timeline.js +127 -0
  237. package/dist/timeline.js.map +1 -0
  238. package/dist/toast.d.ts +164 -0
  239. package/dist/toast.d.ts.map +1 -0
  240. package/dist/toast.js +529 -0
  241. package/dist/toast.js.map +1 -0
  242. package/dist/tokens.d.ts +9 -0
  243. package/dist/tokens.d.ts.map +1 -0
  244. package/dist/tokens.js +9 -0
  245. package/dist/tokens.js.map +1 -0
  246. package/dist/tooltip.d.ts +44 -0
  247. package/dist/tooltip.d.ts.map +1 -0
  248. package/dist/tooltip.js +88 -0
  249. package/dist/tooltip.js.map +1 -0
  250. package/dist/tour.d.ts +218 -0
  251. package/dist/tour.d.ts.map +1 -0
  252. package/dist/tour.js +211 -0
  253. package/dist/tour.js.map +1 -0
  254. package/dist/transfer-list.d.ts +207 -0
  255. package/dist/transfer-list.d.ts.map +1 -0
  256. package/dist/transfer-list.js +193 -0
  257. package/dist/transfer-list.js.map +1 -0
  258. package/dist/tree-select.d.ts +78 -0
  259. package/dist/tree-select.d.ts.map +1 -0
  260. package/dist/tree-select.js +132 -0
  261. package/dist/tree-select.js.map +1 -0
  262. package/dist/tree.d.ts +206 -0
  263. package/dist/tree.d.ts.map +1 -0
  264. package/dist/tree.js +223 -0
  265. package/dist/tree.js.map +1 -0
  266. package/dist/upload-item.d.ts +173 -0
  267. package/dist/upload-item.d.ts.map +1 -0
  268. package/dist/upload-item.js +156 -0
  269. package/dist/upload-item.js.map +1 -0
  270. package/dist/version.d.ts +3 -0
  271. package/dist/version.d.ts.map +1 -0
  272. package/dist/version.js +3 -0
  273. package/dist/version.js.map +1 -0
  274. package/docs/affix.md +63 -0
  275. package/docs/anchor.md +59 -0
  276. package/docs/ant-design-coverage.md +119 -0
  277. package/docs/app-provider.md +50 -0
  278. package/docs/app-rn-adoption.md +227 -0
  279. package/docs/architecture.md +320 -0
  280. package/docs/authoring-brief.md +87 -0
  281. package/docs/border-beam.md +66 -0
  282. package/docs/bottom-navigation.md +127 -0
  283. package/docs/breadcrumb.md +82 -0
  284. package/docs/calendar.md +154 -0
  285. package/docs/carousel.md +130 -0
  286. package/docs/cascader.md +93 -0
  287. package/docs/catalog-decision-status.md +306 -0
  288. package/docs/color-picker.md +72 -0
  289. package/docs/command-palette.md +116 -0
  290. package/docs/confirm-popover.md +93 -0
  291. package/docs/consistency-audit.md +383 -0
  292. package/docs/consumer-release-gate.md +90 -0
  293. package/docs/content-state.md +156 -0
  294. package/docs/context-panel.md +88 -0
  295. package/docs/cross-platform-core-normalization.md +118 -0
  296. package/docs/data-table.md +79 -0
  297. package/docs/date-picker.md +84 -0
  298. package/docs/description-list.md +75 -0
  299. package/docs/design-system-provider.md +139 -0
  300. package/docs/dropdown.md +78 -0
  301. package/docs/expansion-roadmap.md +285 -0
  302. package/docs/file-picker.md +59 -0
  303. package/docs/floating-action-button.md +111 -0
  304. package/docs/form.md +134 -0
  305. package/docs/generated/component-maturity.md +103 -0
  306. package/docs/generated/renderer-evidence.json +5597 -0
  307. package/docs/generated/renderer-evidence.md +132 -0
  308. package/docs/generated/showcase-manifest.json +3732 -0
  309. package/docs/icon.md +22 -0
  310. package/docs/identity.md +121 -0
  311. package/docs/image.md +84 -0
  312. package/docs/implementation-0.5.md +85 -0
  313. package/docs/layout-primitives.md +107 -0
  314. package/docs/layout.md +83 -0
  315. package/docs/library-reference-decisions.md +123 -0
  316. package/docs/link.md +67 -0
  317. package/docs/load-more.md +31 -0
  318. package/docs/mentions.md +82 -0
  319. package/docs/migration-0.2.md +108 -0
  320. package/docs/migration-0.3.md +72 -0
  321. package/docs/migration-0.5.md +82 -0
  322. package/docs/migration-0.6.md +197 -0
  323. package/docs/notification.md +54 -0
  324. package/docs/number-field.md +82 -0
  325. package/docs/otp-field.md +103 -0
  326. package/docs/pagination.md +139 -0
  327. package/docs/password-field.md +98 -0
  328. package/docs/popover.md +124 -0
  329. package/docs/promotion-candidates.md +169 -0
  330. package/docs/qr-code.md +69 -0
  331. package/docs/rating.md +58 -0
  332. package/docs/responsive-grid.md +90 -0
  333. package/docs/result.md +96 -0
  334. package/docs/showcase.md +97 -0
  335. package/docs/side-panel.md +71 -0
  336. package/docs/slider.md +79 -0
  337. package/docs/splitter.md +55 -0
  338. package/docs/statistic.md +16 -0
  339. package/docs/steps.md +115 -0
  340. package/docs/tag.md +57 -0
  341. package/docs/time-picker.md +88 -0
  342. package/docs/timeline.md +146 -0
  343. package/docs/toast.md +127 -0
  344. package/docs/tooltip.md +58 -0
  345. package/docs/tour.md +136 -0
  346. package/docs/transfer-list.md +94 -0
  347. package/docs/tree-select.md +101 -0
  348. package/docs/tree.md +123 -0
  349. package/docs/upload-item.md +68 -0
  350. package/docs/utility.md +53 -0
  351. package/docs/virtual-list.md +70 -0
  352. package/docs/watermark.md +58 -0
  353. package/package.json +402 -0
package/README.md ADDED
@@ -0,0 +1,208 @@
1
+ # `@hjmds/design-contracts`
2
+
3
+ HJM 제품들이 함께 사용하는 플랫폼 중립 디자인 계약입니다. 밝고 간결한 정보 위계와
4
+ 결정적인 순간의 선명한 피드백을 공유하되, 특정 제품이나 도메인의 의미는 포함하지 않습니다.
5
+
6
+ 이 패키지는 **UI 컴포넌트 라이브러리가 아닙니다.** React element, React Native view,
7
+ DOM event, focus trap 또는 navigation adapter를 렌더링하지 않고, 두 플랫폼 renderer가
8
+ 구현해야 할 토큰·recipe·상태·접근성 계약만 배포합니다. `@hjmds/react`와
9
+ `@hjmds/react-native`는 같은 monorepo의 별도 패키지이며 contracts의 framework-neutral
10
+ 경계를 침범하지 않고 DOM/RN primitive로 번역합니다.
11
+
12
+ > **조용한 화면 위에 중요한 순간만 선명하게.**
13
+
14
+ 상세 원칙은 [`docs/identity.md`](./docs/identity.md), 계층·지원 단계·확장 계획은
15
+ [`docs/architecture.md`](./docs/architecture.md)에 정리되어 있습니다.
16
+ 외부 라이브러리에서 어떤 문제 분해 원칙만 가져오고 무엇을 복제하지 않는지는
17
+ [`docs/library-reference-decisions.md`](./docs/library-reference-decisions.md)에 기록합니다.
18
+ Toast의 queue·announcement·timer 수명주기는 [`docs/toast.md`](./docs/toast.md)에 별도로
19
+ 고정되어 있습니다.
20
+
21
+ `badgeRecipe`은 Web/Native 공통 `filled | outline` variant를 정의하며 기본값은 기존과 같은
22
+ `filled`입니다. renderer가 별도 색을 추측하지 않도록 outline 배경 정책, border fallback,
23
+ 강한 tone의 outline content 역할까지 계약에 포함합니다.
24
+ Icon의 semantic name·RTL·장식/정보 접근성 경계는 [`docs/icon.md`](./docs/icon.md)에
25
+ 고정되어 있습니다.
26
+ Tooltip의 Web hover/focus·provider·positioning 경계는
27
+ [`docs/tooltip.md`](./docs/tooltip.md)에 고정되어 있습니다.
28
+ BottomNavigation의 route source-of-truth와 adaptive renderer 경계는
29
+ [`docs/bottom-navigation.md`](./docs/bottom-navigation.md)에 고정되어 있습니다.
30
+ Link의 실제 목적지·Web anchor·Native router 경계는
31
+ [`docs/link.md`](./docs/link.md)에 고정되어 있습니다.
32
+ 공통 계약을 Web과 Native에서 검증하는 showcase 규칙과 실행 방법은
33
+ [`docs/showcase.md`](./docs/showcase.md)에 정리되어 있습니다.
34
+ Ant Design 6.6.1 core 73개를 HJM의 canonical component scope로 번역한 crosswalk는
35
+ [`docs/ant-design-coverage.md`](./docs/ant-design-coverage.md)에 정리되어 있습니다.
36
+ v0.5의 Provider·typography·Showcase evidence 변경과 소비 절차는
37
+ [`docs/migration-0.5.md`](./docs/migration-0.5.md)에 정리되어 있습니다.
38
+ 기존 `@hjm/design-system`에서 현재 패키지 이름과 granular export로 바꾸는 절차는
39
+ [`docs/migration-0.6.md`](./docs/migration-0.6.md)에 정리되어 있습니다.
40
+
41
+ ## Showcase
42
+
43
+ ```bash
44
+ pnpm install
45
+ pnpm showcase:web # Web Storybook
46
+ pnpm showcase:web:check # story 계약과 타입 검사
47
+ pnpm showcase:web:build # 배포 가능한 정적 Storybook
48
+ ```
49
+
50
+ Web Storybook은 탐색 가능한 component home, foundation·catalog·환경 매트릭스를 보여주고, 실제 React Native
51
+ renderer는 소비 앱의 on-device Storybook에서 같은 story identifier로 검증합니다.
52
+ light/dark, LTR/RTL, 100–200% 글자 크기, reduced motion이 공통 필수 환경입니다.
53
+
54
+ `compareShowcaseStoryIds`와 `assertShowcaseStoryIds`의 전체 inventory 검사는 모든 Stable/Beta
55
+ 컴포넌트를 제공한다고 선언한 first-party/full-coverage Storybook용 gate입니다. 일부 화면이나
56
+ 부분 채택 소비 앱은 이 gate를 사용하지 않고, 실제 실행한 story와 scenario만 versioned evidence
57
+ artifact로 제출합니다.
58
+
59
+ ## 경계
60
+
61
+ 이 contracts 패키지가 소유하는 것:
62
+
63
+ - light/dark 시맨틱 색상과 범용 강조색
64
+ - spacing, radius, typography, glyph, motion, touch target, shadow, layout, layer
65
+ - semantic color reference와 플랫폼 독립 resolver
66
+ - button, surface, field 및 확장 컴포넌트의 typed recipe
67
+ - shared/adaptive/web/native 범위와 stable/beta/planned/deprecated 상태를 담은 component catalog
68
+ - 브랜드 그라디언트와 접근성 계약 테스트
69
+
70
+ renderer 및 소비 앱 계층이 소유하는 것:
71
+
72
+ - React DOM 또는 React Native 컴포넌트와 이벤트 타입 (`@hjmds/react`, `@hjmds/react-native`)
73
+ - 제품별 저장 키와 사용자 설정 영속화
74
+ - 아이콘 라이브러리, 폰트 로딩, 애니메이션 구현
75
+ - 제품 전용 컴포넌트와 의미 매핑
76
+
77
+ 예를 들어 야구 팀 색상, 경기 상태, 스코어보드, 라인업, 야구장과 같은 야구 도메인
78
+ UI는 Yajalal이 소유합니다. 다른 제품의 기능 상태 역시 각 제품이 범용 `AccentTone`에
79
+ 매핑합니다. 이 패키지에는 `react`, `react-native`, DOM 또는 Expo import를 추가하지
80
+ 않습니다.
81
+
82
+ ## 소비 원칙
83
+
84
+ 웹과 RN은 같은 토큰과 recipe를 읽고 각 플랫폼 renderer가 실제 UI primitive로
85
+ 번역합니다. 공유하는 것은 컴포넌트의 **의미와 계약**이지 렌더링 코드가 아닙니다.
86
+
87
+ 신규 recipe는 `slots`, `defaults`, `sizes`, `tones/variants`, `states`를 중심으로
88
+ 구성합니다. 외부 라이브러리에서는 컴포넌트 범위·anatomy·상호작용·접근성 패턴을
89
+ 참고하지만 제3자 외형, 전용 자산, 제품 의미는 복사하지 않습니다.
90
+
91
+ 확장 순서와 shared/adaptive/Web/Native 분류는
92
+ [`docs/expansion-roadmap.md`](./docs/expansion-roadmap.md)에 기록합니다. 시각 recipe뿐 아니라
93
+ `behaviorRegistry`의 키보드·포커스·접근성 scenario와 collection selection 계약을 함께
94
+ 만족해야 행동이 있는 컴포넌트가 구현된 것으로 봅니다.
95
+
96
+ ### RN/Metro 친화 진입점
97
+
98
+ 새 package의 root export는 기존 symbol API 호환을 위해 유지하지만 catalog·showcase·전체
99
+ recipe graph까지 노출하므로 앱 runtime에서는 필요한 subpath를 우선합니다.
100
+
101
+ | 진입점 | 용도 |
102
+ | --- | --- |
103
+ | `@hjmds/design-contracts/tokens` | 색·foundation·semantic reference 전체 |
104
+ | `@hjmds/design-contracts/foundations` | spacing·type·motion·layout foundation만 |
105
+ | `@hjmds/design-contracts/colors` | light/dark palette와 accent resolver만 |
106
+ | `@hjmds/design-contracts/color-references` | semantic color reference 생성·해석기만 |
107
+ | `@hjmds/design-contracts/responsive` | 공통 window class와 responsive value resolver |
108
+ | `@hjmds/design-contracts/grid` | Web/RN 공통 Grid descriptor와 geometry resolver |
109
+ | `@hjmds/design-contracts/recipes` | 공통 core component recipe |
110
+ | `@hjmds/design-contracts/recipes/base` | Button·Surface·Field 최소 recipe graph |
111
+ | `@hjmds/design-contracts/contracts` | renderer가 구현할 공통 anatomy/style 계약 |
112
+ | `@hjmds/design-contracts/components/<name>` | `toast`, `form` 등 한 컴포넌트의 상태·validator |
113
+ | `@hjmds/design-contracts/recipes/all` | planned를 포함한 전체 recipe; tooling용 |
114
+ | `@hjmds/design-contracts/behaviors` | 전체 behavior registry; tooling용 |
115
+ | `@hjmds/design-contracts/catalog` | maturity/catalog metadata; tooling용 |
116
+ | `@hjmds/design-contracts/evidence` | versioned product evidence schema·validator; CI용 |
117
+ | `@hjmds/design-contracts/version` | package graph 없이 현재 contract 버전만 읽는 runtime entry |
118
+ | `@hjmds/design-contracts/showcase` | Storybook manifest와 evidence rule; CI용 |
119
+ | `@hjmds/design-contracts/manifest.json` | JS runtime 없이 읽는 생성 manifest; CI용 |
120
+ | `@hjmds/design-contracts/renderer-evidence.json` | first-party renderer claim과 scenario debt snapshot; CI용 |
121
+
122
+ ```ts
123
+ import { spacing, typography } from "@hjmds/design-contracts/foundations";
124
+ import { designSystemVersion } from "@hjmds/design-contracts/version";
125
+ import { resolveContentStateAnnouncement } from "@hjmds/design-contracts/components/content-state";
126
+ import { createToastStore } from "@hjmds/design-contracts/components/toast";
127
+ ```
128
+
129
+ `pnpm bundle:check`는 각 진입점이 연결하는 ESM module 수와 raw/gzip 크기를 검사합니다.
130
+ 특히 token·단일 component 진입점에서 catalog/showcase/root module이 다시 유입되면 실패합니다.
131
+
132
+ ```ts
133
+ import { THEMES } from "@hjmds/design-contracts/colors";
134
+ import { radius, typography } from "@hjmds/design-contracts/foundations";
135
+ import { buttonRecipe, type ButtonTone } from "@hjmds/design-contracts/recipes";
136
+
137
+ const tone: ButtonTone = "primary";
138
+ const contract = buttonRecipe.tones[tone];
139
+ const colors = THEMES.light;
140
+
141
+ const rendererInput = {
142
+ backgroundColor: contract.background
143
+ ? colors[contract.background]
144
+ : "transparent",
145
+ color: colors[contract.content],
146
+ borderRadius: radius.md,
147
+ ...typography.body,
148
+ };
149
+ ```
150
+
151
+ 웹 renderer는 이를 CSS/CSS variable로 변환하고, RN renderer는 `StyleSheet`와
152
+ `Pressable`로 변환합니다. 앱 화면에서 원시 색상·간격을 다시 선언하지 않습니다.
153
+ v0.2 신규 recipe의 `ColorReference`는 제품 별칭이 아닌 공용 status palette로 풉니다.
154
+
155
+ ```ts
156
+ import {
157
+ ACCENTS,
158
+ THEMES,
159
+ accentFill,
160
+ resolveColorReference,
161
+ } from "@hjmds/design-contracts/tokens";
162
+ import { badgeRecipe } from "@hjmds/design-contracts/recipes";
163
+
164
+ const palette = {
165
+ theme: THEMES.dark,
166
+ statusAccents: ACCENTS.dark,
167
+ statusAccentFills: accentFill,
168
+ };
169
+ const successText = resolveColorReference(
170
+ badgeRecipe.tones.success.content,
171
+ palette,
172
+ );
173
+ ```
174
+
175
+ 현재 소비 경계는 다음과 같습니다.
176
+
177
+ - Yajalal RN은 `src/lib/theme` 어댑터 뒤에서 이 패키지를 직접 사용합니다.
178
+ - BurnTok 웹/RN은 기존 `@burntok/design-system` import를 유지하며, 그 패키지가
179
+ 공통 계약을 재수출하고 `ai` 제품 accent와 `built`, `rare`, `popular` 제품 의미만
180
+ 매핑합니다. 공통 `ai` 아이콘 이름은 특정 제품 색이나 모델이 아니라 “AI 기능”을
181
+ 나타내는 일반 의미 역할입니다.
182
+ - 저장 키, CSS 변수 이름, KBO 구단/경기 상태 같은 제품 의미는 각 앱에 남습니다.
183
+
184
+ ## Git tag로 설치
185
+
186
+ 릴리즈 태그가 생성된 뒤 소비 저장소에서는 정확한 태그를 고정합니다.
187
+ `v0.5.2`까지의 태그는 이전 package name을 담고 있습니다. 첫 rename release는 `v0.6.0`이며
188
+ 소비 저장소는 이전 이름과 새 이름을 동시에 두지 않고 한 변경에서 전환합니다.
189
+
190
+ ```bash
191
+ pnpm add '@hjmds/design-contracts@git+https://github.com/jim1286/hjm-design-system.git#v<version>&path:/packages/design-contracts'
192
+ ```
193
+
194
+ `<version>`은 설치할 fixed release의 정확한 SemVer로 바꿉니다.
195
+
196
+ 태그에는 `dist/` 빌드 결과를 함께 포함해야 합니다. 브랜치나 커밋되지 않은 로컬 경로에
197
+ 의존하지 않으며, 계약 변경은 SemVer로 배포합니다.
198
+
199
+ ## 개발
200
+
201
+ ```bash
202
+ pnpm install
203
+ pnpm check
204
+ ```
205
+
206
+ `pnpm check`는 TypeScript typecheck, Vitest 계약/대비 테스트, 배포용 declaration 빌드,
207
+ subpath import graph 예산 검사를 순서대로 실행합니다. 공개 토큰이나 recipe를 변경할 때는
208
+ light/dark key 대칭, WCAG 대비, 최소 44 단위 터치 영역 테스트도 함께 갱신해야 합니다.
@@ -0,0 +1,102 @@
1
+ import type { AlertDialogTone } from "./component-recipes.js";
2
+ export type AlertDialogMode = "alert" | "confirm";
3
+ export type AlertDialogInitialFocus = "cancel" | "confirm";
4
+ export type AlertDialogAsyncState = "idle" | "busy" | "error";
5
+ export type AlertDialogConfirmAction = () => void | Promise<void>;
6
+ export type AlertDialogCancelReason = "cancel-action" | "escape" | "back" | "programmatic" | "interrupted";
7
+ export type AlertDialogDismissReason = Exclude<AlertDialogCancelReason, "interrupted"> | "outside";
8
+ export type AlertDialogOpenChangeReason = "trigger" | "confirm" | AlertDialogCancelReason;
9
+ export type AlertDialogResult = Readonly<{
10
+ outcome: "confirmed";
11
+ }> | Readonly<{
12
+ outcome: "cancelled";
13
+ reason: AlertDialogCancelReason;
14
+ }>;
15
+ type AlertDialogAsyncAction = Readonly<{
16
+ onConfirm: AlertDialogConfirmAction;
17
+ fallbackErrorMessage: string;
18
+ resolveErrorMessage?: (error: unknown) => string;
19
+ }> | Readonly<{
20
+ onConfirm?: never;
21
+ fallbackErrorMessage?: never;
22
+ resolveErrorMessage?: never;
23
+ }>;
24
+ type AlertDialogCopy = Readonly<{
25
+ title: string;
26
+ description: string;
27
+ confirmLabel: string;
28
+ }>;
29
+ /**
30
+ * Renderer-neutral copy and action contract. Products own localized copy;
31
+ * renderers own modal isolation, focus, motion, and visual translation.
32
+ */
33
+ export type AlertDialogRequest = (AlertDialogCopy & Readonly<{
34
+ mode: "alert";
35
+ tone?: Extract<AlertDialogTone, "attention">;
36
+ cancelLabel?: never;
37
+ onConfirm?: never;
38
+ fallbackErrorMessage?: never;
39
+ resolveErrorMessage?: never;
40
+ }>) | (AlertDialogCopy & Readonly<{
41
+ mode: "confirm";
42
+ tone?: AlertDialogTone;
43
+ cancelLabel: string;
44
+ }> & AlertDialogAsyncAction);
45
+ export type AlertDialogOpenState = Readonly<{
46
+ open: boolean;
47
+ defaultOpen?: never;
48
+ onOpenChange(open: boolean, detail: Readonly<{
49
+ reason: AlertDialogOpenChangeReason;
50
+ }>): void;
51
+ }> | Readonly<{
52
+ open?: never;
53
+ defaultOpen?: boolean;
54
+ onOpenChange?: (open: boolean, detail: Readonly<{
55
+ reason: AlertDialogOpenChangeReason;
56
+ }>) => void;
57
+ }>;
58
+ export declare const alertDialogBehaviorDefaults: {
59
+ readonly initialFocus: {
60
+ readonly alert: "confirm";
61
+ readonly confirm: "cancel";
62
+ };
63
+ readonly outsideDismiss: false;
64
+ readonly escapeOrBackOutcome: "cancelled";
65
+ readonly dismissWhileBusy: false;
66
+ };
67
+ export declare function validateAlertDialogRequest(request: AlertDialogRequest): void;
68
+ export declare function getAlertDialogInitialFocus(mode: AlertDialogMode): AlertDialogInitialFocus;
69
+ export declare function canDismissAlertDialog(reason: AlertDialogDismissReason, busy: boolean): boolean;
70
+ export type AlertDialogPhase = Readonly<{
71
+ status: "idle";
72
+ }> | Readonly<{
73
+ status: "busy";
74
+ }> | Readonly<{
75
+ status: "error";
76
+ message: string;
77
+ }> | Readonly<{
78
+ status: "closing";
79
+ result: AlertDialogResult;
80
+ }> | Readonly<{
81
+ status: "closed";
82
+ result: AlertDialogResult;
83
+ }>;
84
+ export type AlertDialogSession = Readonly<{
85
+ request: AlertDialogRequest;
86
+ result: Promise<AlertDialogResult>;
87
+ getSnapshot(): AlertDialogPhase;
88
+ subscribe(listener: () => void): () => void;
89
+ /** Returns true only for the attempt that moved the session toward closing. */
90
+ confirm(): Promise<boolean>;
91
+ cancel(reason: Exclude<AlertDialogCancelReason, "interrupted">): boolean;
92
+ attemptOutsideDismiss(): false;
93
+ completeExit(): boolean;
94
+ interrupt(): boolean;
95
+ }>;
96
+ /**
97
+ * Owns a complete AlertDialog lifecycle, including side-effect de-duplication
98
+ * and settling only after the renderer reports that exit motion completed.
99
+ */
100
+ export declare function createAlertDialogSession(request: AlertDialogRequest): AlertDialogSession;
101
+ export {};
102
+ //# sourceMappingURL=alert-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alert-dialog.d.ts","sourceRoot":"","sources":["../src/alert-dialog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ export const alertDialogBehaviorDefaults = {
2
+ initialFocus: { alert: "confirm", confirm: "cancel" },
3
+ outsideDismiss: false,
4
+ escapeOrBackOutcome: "cancelled",
5
+ dismissWhileBusy: false,
6
+ };
7
+ function assertCopy(value, field) {
8
+ if (value.trim().length === 0) {
9
+ throw new TypeError(`AlertDialog ${field} must not be empty`);
10
+ }
11
+ }
12
+ export function validateAlertDialogRequest(request) {
13
+ assertCopy(request.title, "title");
14
+ assertCopy(request.description, "description");
15
+ assertCopy(request.confirmLabel, "confirmLabel");
16
+ if (request.mode === "alert") {
17
+ if (request.tone === "danger") {
18
+ throw new TypeError("AlertDialog danger tone requires confirm mode");
19
+ }
20
+ return;
21
+ }
22
+ assertCopy(request.cancelLabel, "cancelLabel");
23
+ if (request.onConfirm)
24
+ assertCopy(request.fallbackErrorMessage, "fallbackErrorMessage");
25
+ }
26
+ export function getAlertDialogInitialFocus(mode) {
27
+ return alertDialogBehaviorDefaults.initialFocus[mode];
28
+ }
29
+ export function canDismissAlertDialog(reason, busy) {
30
+ if (busy && !alertDialogBehaviorDefaults.dismissWhileBusy)
31
+ return false;
32
+ if (reason === "outside")
33
+ return alertDialogBehaviorDefaults.outsideDismiss;
34
+ return true;
35
+ }
36
+ function resolveFailureMessage(request, error) {
37
+ if (!request.onConfirm)
38
+ return "";
39
+ try {
40
+ const resolved = request.resolveErrorMessage?.(error).trim();
41
+ return resolved || request.fallbackErrorMessage;
42
+ }
43
+ catch {
44
+ return request.fallbackErrorMessage;
45
+ }
46
+ }
47
+ /**
48
+ * Owns a complete AlertDialog lifecycle, including side-effect de-duplication
49
+ * and settling only after the renderer reports that exit motion completed.
50
+ */
51
+ export function createAlertDialogSession(request) {
52
+ validateAlertDialogRequest(request);
53
+ let phase = { status: "idle" };
54
+ let settleResult;
55
+ let settled = false;
56
+ const listeners = new Set();
57
+ const result = new Promise((resolve) => {
58
+ settleResult = resolve;
59
+ });
60
+ const notify = () => {
61
+ for (const listener of listeners)
62
+ listener();
63
+ };
64
+ const transition = (next) => {
65
+ phase = next;
66
+ notify();
67
+ };
68
+ const settle = (next) => {
69
+ if (settled)
70
+ return false;
71
+ settled = true;
72
+ settleResult(next);
73
+ return true;
74
+ };
75
+ const session = {
76
+ request,
77
+ result,
78
+ getSnapshot: () => phase,
79
+ subscribe(listener) {
80
+ listeners.add(listener);
81
+ return () => listeners.delete(listener);
82
+ },
83
+ async confirm() {
84
+ if (phase.status !== "idle" && phase.status !== "error")
85
+ return false;
86
+ if (request.mode === "alert" || !request.onConfirm) {
87
+ transition({ status: "closing", result: { outcome: "confirmed" } });
88
+ return true;
89
+ }
90
+ transition({ status: "busy" });
91
+ try {
92
+ await request.onConfirm();
93
+ if (phase.status !== "busy")
94
+ return false;
95
+ transition({ status: "closing", result: { outcome: "confirmed" } });
96
+ return true;
97
+ }
98
+ catch (error) {
99
+ if (phase.status !== "busy")
100
+ return false;
101
+ transition({ status: "error", message: resolveFailureMessage(request, error) });
102
+ return false;
103
+ }
104
+ },
105
+ cancel(reason) {
106
+ if (!canDismissAlertDialog(reason, phase.status === "busy"))
107
+ return false;
108
+ if (phase.status !== "idle" && phase.status !== "error")
109
+ return false;
110
+ transition({ status: "closing", result: { outcome: "cancelled", reason } });
111
+ return true;
112
+ },
113
+ attemptOutsideDismiss() {
114
+ return false;
115
+ },
116
+ completeExit() {
117
+ if (phase.status !== "closing")
118
+ return false;
119
+ const finalResult = phase.result;
120
+ transition({ status: "closed", result: finalResult });
121
+ return settle(finalResult);
122
+ },
123
+ interrupt() {
124
+ if (phase.status === "closed")
125
+ return false;
126
+ const interrupted = {
127
+ outcome: "cancelled",
128
+ reason: "interrupted",
129
+ };
130
+ transition({ status: "closed", result: interrupted });
131
+ return settle(interrupted);
132
+ },
133
+ };
134
+ return session;
135
+ }
136
+ //# sourceMappingURL=alert-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alert-dialog.js","sourceRoot":"","sources":["../src/alert-dialog.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AlertDialogTone } from \"./component-recipes.js\";\n\nexport type AlertDialogMode = \"alert\" | \"confirm\";\nexport type AlertDialogInitialFocus = \"cancel\" | \"confirm\";\nexport type AlertDialogAsyncState = \"idle\" | \"busy\" | \"error\";\nexport type AlertDialogConfirmAction = () => void | Promise<void>;\nexport type AlertDialogCancelReason =\n | \"cancel-action\"\n | \"escape\"\n | \"back\"\n | \"programmatic\"\n | \"interrupted\";\nexport type AlertDialogDismissReason =\n | Exclude<AlertDialogCancelReason, \"interrupted\">\n | \"outside\";\nexport type AlertDialogOpenChangeReason = \"trigger\" | \"confirm\" | AlertDialogCancelReason;\n\nexport type AlertDialogResult =\n | Readonly<{ outcome: \"confirmed\" }>\n | Readonly<{ outcome: \"cancelled\"; reason: AlertDialogCancelReason }>;\n\ntype AlertDialogAsyncAction =\n | Readonly<{\n onConfirm: AlertDialogConfirmAction;\n fallbackErrorMessage: string;\n resolveErrorMessage?: (error: unknown) => string;\n }>\n | Readonly<{\n onConfirm?: never;\n fallbackErrorMessage?: never;\n resolveErrorMessage?: never;\n }>;\n\ntype AlertDialogCopy = Readonly<{\n title: string;\n description: string;\n confirmLabel: string;\n}>;\n\n/**\n * Renderer-neutral copy and action contract. Products own localized copy;\n * renderers own modal isolation, focus, motion, and visual translation.\n */\nexport type AlertDialogRequest =\n | (AlertDialogCopy &\n Readonly<{\n mode: \"alert\";\n tone?: Extract<AlertDialogTone, \"attention\">;\n cancelLabel?: never;\n onConfirm?: never;\n fallbackErrorMessage?: never;\n resolveErrorMessage?: never;\n }>)\n | (AlertDialogCopy &\n Readonly<{\n mode: \"confirm\";\n tone?: AlertDialogTone;\n cancelLabel: string;\n }> &\n AlertDialogAsyncAction);\n\nexport type AlertDialogOpenState =\n | Readonly<{\n open: boolean;\n defaultOpen?: never;\n onOpenChange(\n open: boolean,\n detail: Readonly<{ reason: AlertDialogOpenChangeReason }>,\n ): void;\n }>\n | Readonly<{\n open?: never;\n defaultOpen?: boolean;\n onOpenChange?: (\n open: boolean,\n detail: Readonly<{ reason: AlertDialogOpenChangeReason }>,\n ) => void;\n }>;\n\nexport const alertDialogBehaviorDefaults = {\n initialFocus: { alert: \"confirm\", confirm: \"cancel\" },\n outsideDismiss: false,\n escapeOrBackOutcome: \"cancelled\",\n dismissWhileBusy: false,\n} as const satisfies Readonly<{\n initialFocus: Record<AlertDialogMode, AlertDialogInitialFocus>;\n outsideDismiss: false;\n escapeOrBackOutcome: \"cancelled\";\n dismissWhileBusy: false;\n}>;\n\nfunction assertCopy(value: string, field: string): void {\n if (value.trim().length === 0) {\n throw new TypeError(`AlertDialog ${field} must not be empty`);\n }\n}\n\nexport function validateAlertDialogRequest(request: AlertDialogRequest): void {\n assertCopy(request.title, \"title\");\n assertCopy(request.description, \"description\");\n assertCopy(request.confirmLabel, \"confirmLabel\");\n if (request.mode === \"alert\") {\n if (request.tone === (\"danger\" as AlertDialogTone)) {\n throw new TypeError(\"AlertDialog danger tone requires confirm mode\");\n }\n return;\n }\n assertCopy(request.cancelLabel, \"cancelLabel\");\n if (request.onConfirm) assertCopy(request.fallbackErrorMessage, \"fallbackErrorMessage\");\n}\n\nexport function getAlertDialogInitialFocus(\n mode: AlertDialogMode,\n): AlertDialogInitialFocus {\n return alertDialogBehaviorDefaults.initialFocus[mode];\n}\n\nexport function canDismissAlertDialog(\n reason: AlertDialogDismissReason,\n busy: boolean,\n): boolean {\n if (busy && !alertDialogBehaviorDefaults.dismissWhileBusy) return false;\n if (reason === \"outside\") return alertDialogBehaviorDefaults.outsideDismiss;\n return true;\n}\n\nexport type AlertDialogPhase =\n | Readonly<{ status: \"idle\" }>\n | Readonly<{ status: \"busy\" }>\n | Readonly<{ status: \"error\"; message: string }>\n | Readonly<{ status: \"closing\"; result: AlertDialogResult }>\n | Readonly<{ status: \"closed\"; result: AlertDialogResult }>;\n\nexport type AlertDialogSession = Readonly<{\n request: AlertDialogRequest;\n result: Promise<AlertDialogResult>;\n getSnapshot(): AlertDialogPhase;\n subscribe(listener: () => void): () => void;\n /** Returns true only for the attempt that moved the session toward closing. */\n confirm(): Promise<boolean>;\n cancel(reason: Exclude<AlertDialogCancelReason, \"interrupted\">): boolean;\n attemptOutsideDismiss(): false;\n completeExit(): boolean;\n interrupt(): boolean;\n}>;\n\nfunction resolveFailureMessage(\n request: Extract<AlertDialogRequest, { mode: \"confirm\" }>,\n error: unknown,\n): string {\n if (!request.onConfirm) return \"\";\n try {\n const resolved = request.resolveErrorMessage?.(error).trim();\n return resolved || request.fallbackErrorMessage;\n } catch {\n return request.fallbackErrorMessage;\n }\n}\n\n/**\n * Owns a complete AlertDialog lifecycle, including side-effect de-duplication\n * and settling only after the renderer reports that exit motion completed.\n */\nexport function createAlertDialogSession(\n request: AlertDialogRequest,\n): AlertDialogSession {\n validateAlertDialogRequest(request);\n\n let phase: AlertDialogPhase = { status: \"idle\" };\n let settleResult!: (result: AlertDialogResult) => void;\n let settled = false;\n const listeners = new Set<() => void>();\n const result = new Promise<AlertDialogResult>((resolve) => {\n settleResult = resolve;\n });\n\n const notify = () => {\n for (const listener of listeners) listener();\n };\n const transition = (next: AlertDialogPhase) => {\n phase = next;\n notify();\n };\n const settle = (next: AlertDialogResult): boolean => {\n if (settled) return false;\n settled = true;\n settleResult(next);\n return true;\n };\n\n const session: AlertDialogSession = {\n request,\n result,\n getSnapshot: () => phase,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n async confirm() {\n if (phase.status !== \"idle\" && phase.status !== \"error\") return false;\n\n if (request.mode === \"alert\" || !request.onConfirm) {\n transition({ status: \"closing\", result: { outcome: \"confirmed\" } });\n return true;\n }\n\n transition({ status: \"busy\" });\n try {\n await request.onConfirm();\n if ((phase as AlertDialogPhase).status !== \"busy\") return false;\n transition({ status: \"closing\", result: { outcome: \"confirmed\" } });\n return true;\n } catch (error) {\n if ((phase as AlertDialogPhase).status !== \"busy\") return false;\n transition({ status: \"error\", message: resolveFailureMessage(request, error) });\n return false;\n }\n },\n cancel(reason) {\n if (!canDismissAlertDialog(reason, phase.status === \"busy\")) return false;\n if (phase.status !== \"idle\" && phase.status !== \"error\") return false;\n transition({ status: \"closing\", result: { outcome: \"cancelled\", reason } });\n return true;\n },\n attemptOutsideDismiss() {\n return false;\n },\n completeExit() {\n if (phase.status !== \"closing\") return false;\n const finalResult = phase.result;\n transition({ status: \"closed\", result: finalResult });\n return settle(finalResult);\n },\n interrupt() {\n if (phase.status === \"closed\") return false;\n const interrupted: AlertDialogResult = {\n outcome: \"cancelled\",\n reason: \"interrupted\",\n };\n transition({ status: \"closed\", result: interrupted });\n return settle(interrupted);\n },\n };\n\n return session;\n}\n"]}
@@ -0,0 +1,184 @@
1
+ import { control, radius, spacing } from "./foundations.js";
2
+ export type ButtonTone = "primary" | "secondary" | "ghost" | "danger" | "link";
3
+ export type ButtonSize = keyof typeof control.buttonHeight;
4
+ export type SurfaceTone = "default" | "raised" | "accent" | "subtle";
5
+ export type SurfacePadding = "none" | keyof typeof spacing;
6
+ export type SurfaceRadius = keyof typeof radius;
7
+ export type FieldVariant = "surface" | "inset";
8
+ export type FieldShape = "medium" | "large" | "full";
9
+ /** Small renderer entry point for the three foundational visual recipes. */
10
+ export declare const buttonRecipe: {
11
+ readonly slots: readonly ["root", "leading", "label", "trailing", "spinner"];
12
+ readonly defaults: {
13
+ readonly tone: "primary";
14
+ readonly size: "medium";
15
+ };
16
+ readonly tones: {
17
+ readonly primary: {
18
+ readonly background: "primary";
19
+ readonly content: "onPrimary";
20
+ readonly border: null;
21
+ };
22
+ readonly secondary: {
23
+ readonly background: "surfaceAlt";
24
+ readonly content: "text";
25
+ readonly border: "border";
26
+ };
27
+ readonly ghost: {
28
+ readonly background: null;
29
+ readonly content: "textMuted";
30
+ readonly border: null;
31
+ };
32
+ readonly danger: {
33
+ readonly background: "dangerFill";
34
+ readonly content: "onDanger";
35
+ readonly border: null;
36
+ };
37
+ readonly link: {
38
+ readonly background: null;
39
+ readonly content: "contentBrand";
40
+ readonly border: null;
41
+ };
42
+ };
43
+ readonly sizes: {
44
+ readonly small: {
45
+ readonly height: 36;
46
+ readonly hitSlop: 4;
47
+ readonly paddingHorizontal: 12;
48
+ readonly textVariant: "label";
49
+ };
50
+ readonly medium: {
51
+ readonly height: 44;
52
+ readonly hitSlop: 0;
53
+ readonly paddingHorizontal: 16;
54
+ readonly textVariant: "body";
55
+ };
56
+ readonly large: {
57
+ readonly height: 52;
58
+ readonly hitSlop: 0;
59
+ readonly paddingHorizontal: 20;
60
+ readonly textVariant: "bodyLarge";
61
+ };
62
+ };
63
+ readonly opacity: {
64
+ readonly disabled: 0.5;
65
+ readonly pressed: 0.86;
66
+ };
67
+ };
68
+ export declare const surfaceRecipe: {
69
+ readonly default: {
70
+ readonly background: "surface";
71
+ readonly border: "border";
72
+ readonly borderAlpha: 1;
73
+ readonly elevated: false;
74
+ readonly borderAlways: false;
75
+ };
76
+ readonly raised: {
77
+ readonly background: "bg";
78
+ readonly border: "border";
79
+ readonly borderAlpha: 1;
80
+ readonly elevated: true;
81
+ readonly borderAlways: false;
82
+ };
83
+ readonly accent: {
84
+ readonly background: "surfaceAccent";
85
+ readonly border: "primary";
86
+ readonly borderAlpha: 0.3;
87
+ readonly elevated: false;
88
+ readonly borderAlways: false;
89
+ };
90
+ readonly subtle: {
91
+ readonly background: "bg";
92
+ readonly border: "border";
93
+ readonly borderAlpha: 1;
94
+ readonly elevated: false;
95
+ readonly borderAlways: true;
96
+ };
97
+ };
98
+ export declare const fieldRecipe: {
99
+ readonly slots: readonly ["root", "label", "control", "leading", "input", "trailing", "hint", "error"];
100
+ readonly defaults: {
101
+ readonly variant: "surface";
102
+ readonly shape: "medium";
103
+ };
104
+ readonly variants: {
105
+ readonly surface: {
106
+ readonly background: "surface";
107
+ };
108
+ readonly inset: {
109
+ readonly background: "bg";
110
+ };
111
+ };
112
+ readonly shapes: {
113
+ readonly medium: "md";
114
+ readonly large: "lg";
115
+ readonly full: "full";
116
+ };
117
+ readonly states: {
118
+ readonly idle: {
119
+ readonly border: "textMuted";
120
+ };
121
+ readonly focused: {
122
+ readonly border: "contentBrand";
123
+ };
124
+ readonly invalid: {
125
+ readonly border: "danger";
126
+ };
127
+ };
128
+ readonly minHeight: 44;
129
+ readonly multilineMinHeight: 80;
130
+ readonly borderWidth: 1;
131
+ readonly focusRingWidth: 2;
132
+ readonly focusRingOffset: 2;
133
+ readonly paddingHorizontal: 16;
134
+ readonly paddingVertical: 12;
135
+ readonly textVariant: "body";
136
+ readonly label: {
137
+ readonly color: "textBody";
138
+ readonly textVariant: "body";
139
+ readonly fontWeight: "600";
140
+ readonly gap: 8;
141
+ };
142
+ readonly support: {
143
+ readonly hintColor: "textMuted";
144
+ readonly errorColor: "danger";
145
+ readonly textVariant: "label";
146
+ readonly gap: 6;
147
+ };
148
+ readonly placeholder: {
149
+ readonly color: "textMuted";
150
+ };
151
+ readonly disabledOpacity: 0.6;
152
+ };
153
+ /**
154
+ * Renderer-neutral Surface geometry. Tone colors stay in `surfaceRecipe` for
155
+ * compatibility; these axes make the previously implicit Web/Native defaults
156
+ * explicit without changing that public recipe shape.
157
+ */
158
+ export declare const surfaceDefaults: {
159
+ readonly tone: "default";
160
+ readonly padding: "none";
161
+ readonly radius: "lg";
162
+ readonly bordered: false;
163
+ };
164
+ export declare const surfaceGeometry: {
165
+ readonly paddings: {
166
+ readonly xxs: 4;
167
+ readonly xs: 8;
168
+ readonly sm: 12;
169
+ readonly md: 16;
170
+ readonly lg: 20;
171
+ readonly xl: 24;
172
+ readonly xxl: 32;
173
+ readonly xxxl: 40;
174
+ readonly none: 0;
175
+ };
176
+ readonly radii: {
177
+ readonly sm: 8;
178
+ readonly md: 12;
179
+ readonly lg: 16;
180
+ readonly xl: 24;
181
+ readonly full: 999;
182
+ };
183
+ };
184
+ //# sourceMappingURL=base-recipes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-recipes.d.ts","sourceRoot":"","sources":["../src/base-recipes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAc,MAAM,EAAE,OAAO,EAAc,MAAM,kBAAkB,CAAC;AAGpF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAC/E,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,OAAO,CAAC,YAAY,CAAC;AAC3D,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,OAAO,OAAO,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,MAAM,CAAC;AAChD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAC/C,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAErD,4EAA4E;AAC5E,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDxB,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCzB,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+EvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;CAU3B,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;CAM3B,CAAC"}