melta-app 0.1.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 (311) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +197 -0
  3. package/THIRD_PARTY_LICENSES.md +198 -0
  4. package/lib/module/components/ActionSheet.js +87 -0
  5. package/lib/module/components/ActionSheet.js.map +1 -0
  6. package/lib/module/components/Alert.js +93 -0
  7. package/lib/module/components/Alert.js.map +1 -0
  8. package/lib/module/components/Avatar.js +93 -0
  9. package/lib/module/components/Avatar.js.map +1 -0
  10. package/lib/module/components/BottomSheet.js +69 -0
  11. package/lib/module/components/BottomSheet.js.map +1 -0
  12. package/lib/module/components/Card.js +93 -0
  13. package/lib/module/components/Card.js.map +1 -0
  14. package/lib/module/components/Checkbox.js +115 -0
  15. package/lib/module/components/Checkbox.js.map +1 -0
  16. package/lib/module/components/EmptyState.js +70 -0
  17. package/lib/module/components/EmptyState.js.map +1 -0
  18. package/lib/module/components/Header.js +53 -0
  19. package/lib/module/components/Header.js.map +1 -0
  20. package/lib/module/components/Image.js +67 -0
  21. package/lib/module/components/Image.js.map +1 -0
  22. package/lib/module/components/Modal.js +95 -0
  23. package/lib/module/components/Modal.js.map +1 -0
  24. package/lib/module/components/Progress.js +113 -0
  25. package/lib/module/components/Progress.js.map +1 -0
  26. package/lib/module/components/Radio.js +134 -0
  27. package/lib/module/components/Radio.js.map +1 -0
  28. package/lib/module/components/Screen.js +57 -0
  29. package/lib/module/components/Screen.js.map +1 -0
  30. package/lib/module/components/Skeleton.js +169 -0
  31. package/lib/module/components/Skeleton.js.map +1 -0
  32. package/lib/module/components/Surface.js +49 -0
  33. package/lib/module/components/Surface.js.map +1 -0
  34. package/lib/module/components/TextField.js +84 -0
  35. package/lib/module/components/TextField.js.map +1 -0
  36. package/lib/module/components/Toast.js +105 -0
  37. package/lib/module/components/Toast.js.map +1 -0
  38. package/lib/module/components/Toggle.js +77 -0
  39. package/lib/module/components/Toggle.js.map +1 -0
  40. package/lib/module/components/action-sheet.styles.js +70 -0
  41. package/lib/module/components/action-sheet.styles.js.map +1 -0
  42. package/lib/module/components/alert.styles.js +80 -0
  43. package/lib/module/components/alert.styles.js.map +1 -0
  44. package/lib/module/components/avatar.styles.js +94 -0
  45. package/lib/module/components/avatar.styles.js.map +1 -0
  46. package/lib/module/components/bottom-sheet.styles.js +55 -0
  47. package/lib/module/components/bottom-sheet.styles.js.map +1 -0
  48. package/lib/module/components/card.styles.js +50 -0
  49. package/lib/module/components/card.styles.js.map +1 -0
  50. package/lib/module/components/checkbox.styles.js +55 -0
  51. package/lib/module/components/checkbox.styles.js.map +1 -0
  52. package/lib/module/components/empty-state.styles.js +60 -0
  53. package/lib/module/components/empty-state.styles.js.map +1 -0
  54. package/lib/module/components/header.styles.js +33 -0
  55. package/lib/module/components/header.styles.js.map +1 -0
  56. package/lib/module/components/image.styles.js +37 -0
  57. package/lib/module/components/image.styles.js.map +1 -0
  58. package/lib/module/components/index.js +26 -0
  59. package/lib/module/components/index.js.map +1 -0
  60. package/lib/module/components/modal.styles.js +68 -0
  61. package/lib/module/components/modal.styles.js.map +1 -0
  62. package/lib/module/components/progress.styles.js +55 -0
  63. package/lib/module/components/progress.styles.js.map +1 -0
  64. package/lib/module/components/radio.styles.js +96 -0
  65. package/lib/module/components/radio.styles.js.map +1 -0
  66. package/lib/module/components/screen.styles.js +38 -0
  67. package/lib/module/components/screen.styles.js.map +1 -0
  68. package/lib/module/components/skeleton.styles.js +114 -0
  69. package/lib/module/components/skeleton.styles.js.map +1 -0
  70. package/lib/module/components/surface.styles.js +37 -0
  71. package/lib/module/components/surface.styles.js.map +1 -0
  72. package/lib/module/components/textfield.styles.js +121 -0
  73. package/lib/module/components/textfield.styles.js.map +1 -0
  74. package/lib/module/components/toast.styles.js +81 -0
  75. package/lib/module/components/toast.styles.js.map +1 -0
  76. package/lib/module/components/toggle.styles.js +69 -0
  77. package/lib/module/components/toggle.styles.js.map +1 -0
  78. package/lib/module/contracts/contract-types.js +192 -0
  79. package/lib/module/contracts/contract-types.js.map +1 -0
  80. package/lib/module/icons/Icon.js +57 -0
  81. package/lib/module/icons/Icon.js.map +1 -0
  82. package/lib/module/icons/glyphs.js +257 -0
  83. package/lib/module/icons/glyphs.js.map +1 -0
  84. package/lib/module/icons/icon.styles.js +28 -0
  85. package/lib/module/icons/icon.styles.js.map +1 -0
  86. package/lib/module/icons/index.js +14 -0
  87. package/lib/module/icons/index.js.map +1 -0
  88. package/lib/module/index.js +20 -0
  89. package/lib/module/index.js.map +1 -0
  90. package/lib/module/package.json +1 -0
  91. package/lib/module/primitives/Button.js +105 -0
  92. package/lib/module/primitives/Button.js.map +1 -0
  93. package/lib/module/primitives/Metric.js +68 -0
  94. package/lib/module/primitives/Metric.js.map +1 -0
  95. package/lib/module/primitives/Row.js +43 -0
  96. package/lib/module/primitives/Row.js.map +1 -0
  97. package/lib/module/primitives/Stack.js +39 -0
  98. package/lib/module/primitives/Stack.js.map +1 -0
  99. package/lib/module/primitives/Tag.js +160 -0
  100. package/lib/module/primitives/Tag.js.map +1 -0
  101. package/lib/module/primitives/Text.js +54 -0
  102. package/lib/module/primitives/Text.js.map +1 -0
  103. package/lib/module/primitives/_internal/focus-ring.js +57 -0
  104. package/lib/module/primitives/_internal/focus-ring.js.map +1 -0
  105. package/lib/module/primitives/button.styles.js +88 -0
  106. package/lib/module/primitives/button.styles.js.map +1 -0
  107. package/lib/module/primitives/index.js +11 -0
  108. package/lib/module/primitives/index.js.map +1 -0
  109. package/lib/module/primitives/metric.styles.js +54 -0
  110. package/lib/module/primitives/metric.styles.js.map +1 -0
  111. package/lib/module/primitives/row.styles.js +53 -0
  112. package/lib/module/primitives/row.styles.js.map +1 -0
  113. package/lib/module/primitives/stack.styles.js +37 -0
  114. package/lib/module/primitives/stack.styles.js.map +1 -0
  115. package/lib/module/primitives/tag.styles.js +56 -0
  116. package/lib/module/primitives/tag.styles.js.map +1 -0
  117. package/lib/module/primitives/text.styles.js +33 -0
  118. package/lib/module/primitives/text.styles.js.map +1 -0
  119. package/lib/module/theme/ThemeProvider.js +41 -0
  120. package/lib/module/theme/ThemeProvider.js.map +1 -0
  121. package/lib/module/theme/index.js +19 -0
  122. package/lib/module/theme/index.js.map +1 -0
  123. package/lib/module/theme/native-theme.js +201 -0
  124. package/lib/module/theme/native-theme.js.map +1 -0
  125. package/lib/module/theme/types.js +4 -0
  126. package/lib/module/theme/types.js.map +1 -0
  127. package/lib/typescript/package.json +1 -0
  128. package/lib/typescript/src/components/ActionSheet.d.ts +45 -0
  129. package/lib/typescript/src/components/ActionSheet.d.ts.map +1 -0
  130. package/lib/typescript/src/components/Alert.d.ts +43 -0
  131. package/lib/typescript/src/components/Alert.d.ts.map +1 -0
  132. package/lib/typescript/src/components/Avatar.d.ts +45 -0
  133. package/lib/typescript/src/components/Avatar.d.ts.map +1 -0
  134. package/lib/typescript/src/components/BottomSheet.d.ts +36 -0
  135. package/lib/typescript/src/components/BottomSheet.d.ts.map +1 -0
  136. package/lib/typescript/src/components/Card.d.ts +46 -0
  137. package/lib/typescript/src/components/Card.d.ts.map +1 -0
  138. package/lib/typescript/src/components/Checkbox.d.ts +40 -0
  139. package/lib/typescript/src/components/Checkbox.d.ts.map +1 -0
  140. package/lib/typescript/src/components/EmptyState.d.ts +36 -0
  141. package/lib/typescript/src/components/EmptyState.d.ts.map +1 -0
  142. package/lib/typescript/src/components/Header.d.ts +34 -0
  143. package/lib/typescript/src/components/Header.d.ts.map +1 -0
  144. package/lib/typescript/src/components/Image.d.ts +41 -0
  145. package/lib/typescript/src/components/Image.d.ts.map +1 -0
  146. package/lib/typescript/src/components/Modal.d.ts +46 -0
  147. package/lib/typescript/src/components/Modal.d.ts.map +1 -0
  148. package/lib/typescript/src/components/Progress.d.ts +39 -0
  149. package/lib/typescript/src/components/Progress.d.ts.map +1 -0
  150. package/lib/typescript/src/components/Radio.d.ts +52 -0
  151. package/lib/typescript/src/components/Radio.d.ts.map +1 -0
  152. package/lib/typescript/src/components/Screen.d.ts +42 -0
  153. package/lib/typescript/src/components/Screen.d.ts.map +1 -0
  154. package/lib/typescript/src/components/Skeleton.d.ts +37 -0
  155. package/lib/typescript/src/components/Skeleton.d.ts.map +1 -0
  156. package/lib/typescript/src/components/Surface.d.ts +31 -0
  157. package/lib/typescript/src/components/Surface.d.ts.map +1 -0
  158. package/lib/typescript/src/components/TextField.d.ts +45 -0
  159. package/lib/typescript/src/components/TextField.d.ts.map +1 -0
  160. package/lib/typescript/src/components/Toast.d.ts +45 -0
  161. package/lib/typescript/src/components/Toast.d.ts.map +1 -0
  162. package/lib/typescript/src/components/Toggle.d.ts +39 -0
  163. package/lib/typescript/src/components/Toggle.d.ts.map +1 -0
  164. package/lib/typescript/src/components/action-sheet.styles.d.ts +65 -0
  165. package/lib/typescript/src/components/action-sheet.styles.d.ts.map +1 -0
  166. package/lib/typescript/src/components/alert.styles.d.ts +61 -0
  167. package/lib/typescript/src/components/alert.styles.d.ts.map +1 -0
  168. package/lib/typescript/src/components/avatar.styles.d.ts +60 -0
  169. package/lib/typescript/src/components/avatar.styles.d.ts.map +1 -0
  170. package/lib/typescript/src/components/bottom-sheet.styles.d.ts +50 -0
  171. package/lib/typescript/src/components/bottom-sheet.styles.d.ts.map +1 -0
  172. package/lib/typescript/src/components/card.styles.d.ts +27 -0
  173. package/lib/typescript/src/components/card.styles.d.ts.map +1 -0
  174. package/lib/typescript/src/components/checkbox.styles.d.ts +55 -0
  175. package/lib/typescript/src/components/checkbox.styles.d.ts.map +1 -0
  176. package/lib/typescript/src/components/empty-state.styles.d.ts +58 -0
  177. package/lib/typescript/src/components/empty-state.styles.d.ts.map +1 -0
  178. package/lib/typescript/src/components/header.styles.d.ts +30 -0
  179. package/lib/typescript/src/components/header.styles.d.ts.map +1 -0
  180. package/lib/typescript/src/components/image.styles.d.ts +28 -0
  181. package/lib/typescript/src/components/image.styles.d.ts.map +1 -0
  182. package/lib/typescript/src/components/index.d.ts +23 -0
  183. package/lib/typescript/src/components/index.d.ts.map +1 -0
  184. package/lib/typescript/src/components/modal.styles.d.ts +66 -0
  185. package/lib/typescript/src/components/modal.styles.d.ts.map +1 -0
  186. package/lib/typescript/src/components/progress.styles.d.ts +44 -0
  187. package/lib/typescript/src/components/progress.styles.d.ts.map +1 -0
  188. package/lib/typescript/src/components/radio.styles.d.ts +91 -0
  189. package/lib/typescript/src/components/radio.styles.d.ts.map +1 -0
  190. package/lib/typescript/src/components/screen.styles.d.ts +34 -0
  191. package/lib/typescript/src/components/screen.styles.d.ts.map +1 -0
  192. package/lib/typescript/src/components/skeleton.styles.d.ts +105 -0
  193. package/lib/typescript/src/components/skeleton.styles.d.ts.map +1 -0
  194. package/lib/typescript/src/components/surface.styles.d.ts +31 -0
  195. package/lib/typescript/src/components/surface.styles.d.ts.map +1 -0
  196. package/lib/typescript/src/components/textfield.styles.d.ts +75 -0
  197. package/lib/typescript/src/components/textfield.styles.d.ts.map +1 -0
  198. package/lib/typescript/src/components/toast.styles.d.ts +62 -0
  199. package/lib/typescript/src/components/toast.styles.d.ts.map +1 -0
  200. package/lib/typescript/src/components/toggle.styles.d.ts +53 -0
  201. package/lib/typescript/src/components/toggle.styles.d.ts.map +1 -0
  202. package/lib/typescript/src/contracts/contract-types.d.ts +193 -0
  203. package/lib/typescript/src/contracts/contract-types.d.ts.map +1 -0
  204. package/lib/typescript/src/icons/Icon.d.ts +40 -0
  205. package/lib/typescript/src/icons/Icon.d.ts.map +1 -0
  206. package/lib/typescript/src/icons/glyphs.d.ts +259 -0
  207. package/lib/typescript/src/icons/glyphs.d.ts.map +1 -0
  208. package/lib/typescript/src/icons/icon.styles.d.ts +20 -0
  209. package/lib/typescript/src/icons/icon.styles.d.ts.map +1 -0
  210. package/lib/typescript/src/icons/index.d.ts +12 -0
  211. package/lib/typescript/src/icons/index.d.ts.map +1 -0
  212. package/lib/typescript/src/index.d.ts +12 -0
  213. package/lib/typescript/src/index.d.ts.map +1 -0
  214. package/lib/typescript/src/primitives/Button.d.ts +48 -0
  215. package/lib/typescript/src/primitives/Button.d.ts.map +1 -0
  216. package/lib/typescript/src/primitives/Metric.d.ts +38 -0
  217. package/lib/typescript/src/primitives/Metric.d.ts.map +1 -0
  218. package/lib/typescript/src/primitives/Row.d.ts +37 -0
  219. package/lib/typescript/src/primitives/Row.d.ts.map +1 -0
  220. package/lib/typescript/src/primitives/Stack.d.ts +33 -0
  221. package/lib/typescript/src/primitives/Stack.d.ts.map +1 -0
  222. package/lib/typescript/src/primitives/Tag.d.ts +43 -0
  223. package/lib/typescript/src/primitives/Tag.d.ts.map +1 -0
  224. package/lib/typescript/src/primitives/Text.d.ts +45 -0
  225. package/lib/typescript/src/primitives/Text.d.ts.map +1 -0
  226. package/lib/typescript/src/primitives/_internal/focus-ring.d.ts +31 -0
  227. package/lib/typescript/src/primitives/_internal/focus-ring.d.ts.map +1 -0
  228. package/lib/typescript/src/primitives/button.styles.d.ts +29 -0
  229. package/lib/typescript/src/primitives/button.styles.d.ts.map +1 -0
  230. package/lib/typescript/src/primitives/index.d.ts +8 -0
  231. package/lib/typescript/src/primitives/index.d.ts.map +1 -0
  232. package/lib/typescript/src/primitives/metric.styles.d.ts +43 -0
  233. package/lib/typescript/src/primitives/metric.styles.d.ts.map +1 -0
  234. package/lib/typescript/src/primitives/row.styles.d.ts +50 -0
  235. package/lib/typescript/src/primitives/row.styles.d.ts.map +1 -0
  236. package/lib/typescript/src/primitives/stack.styles.d.ts +34 -0
  237. package/lib/typescript/src/primitives/stack.styles.d.ts.map +1 -0
  238. package/lib/typescript/src/primitives/tag.styles.d.ts +32 -0
  239. package/lib/typescript/src/primitives/tag.styles.d.ts.map +1 -0
  240. package/lib/typescript/src/primitives/text.styles.d.ts +26 -0
  241. package/lib/typescript/src/primitives/text.styles.d.ts.map +1 -0
  242. package/lib/typescript/src/theme/ThemeProvider.d.ts +32 -0
  243. package/lib/typescript/src/theme/ThemeProvider.d.ts.map +1 -0
  244. package/lib/typescript/src/theme/index.d.ts +15 -0
  245. package/lib/typescript/src/theme/index.d.ts.map +1 -0
  246. package/lib/typescript/src/theme/native-theme.d.ts +3 -0
  247. package/lib/typescript/src/theme/native-theme.d.ts.map +1 -0
  248. package/lib/typescript/src/theme/types.d.ts +121 -0
  249. package/lib/typescript/src/theme/types.d.ts.map +1 -0
  250. package/package.json +120 -0
  251. package/src/components/ActionSheet.tsx +112 -0
  252. package/src/components/Alert.tsx +84 -0
  253. package/src/components/Avatar.tsx +110 -0
  254. package/src/components/BottomSheet.tsx +81 -0
  255. package/src/components/Card.tsx +102 -0
  256. package/src/components/Checkbox.tsx +107 -0
  257. package/src/components/EmptyState.tsx +64 -0
  258. package/src/components/Header.tsx +51 -0
  259. package/src/components/Image.tsx +89 -0
  260. package/src/components/Modal.tsx +113 -0
  261. package/src/components/Progress.tsx +124 -0
  262. package/src/components/Radio.tsx +151 -0
  263. package/src/components/Screen.tsx +62 -0
  264. package/src/components/Skeleton.tsx +154 -0
  265. package/src/components/Surface.tsx +37 -0
  266. package/src/components/TextField.tsx +102 -0
  267. package/src/components/Toast.tsx +103 -0
  268. package/src/components/Toggle.tsx +94 -0
  269. package/src/components/action-sheet.styles.ts +102 -0
  270. package/src/components/alert.styles.ts +115 -0
  271. package/src/components/avatar.styles.ts +110 -0
  272. package/src/components/bottom-sheet.styles.ts +78 -0
  273. package/src/components/card.styles.ts +56 -0
  274. package/src/components/checkbox.styles.ts +83 -0
  275. package/src/components/empty-state.styles.ts +98 -0
  276. package/src/components/header.styles.ts +44 -0
  277. package/src/components/image.styles.ts +36 -0
  278. package/src/components/index.ts +23 -0
  279. package/src/components/modal.styles.ts +106 -0
  280. package/src/components/progress.styles.ts +74 -0
  281. package/src/components/radio.styles.ts +132 -0
  282. package/src/components/screen.styles.ts +44 -0
  283. package/src/components/skeleton.styles.ts +155 -0
  284. package/src/components/surface.styles.ts +50 -0
  285. package/src/components/textfield.styles.ts +135 -0
  286. package/src/components/toast.styles.ts +115 -0
  287. package/src/components/toggle.styles.ts +73 -0
  288. package/src/contracts/contract-types.ts +199 -0
  289. package/src/icons/Icon.tsx +65 -0
  290. package/src/icons/glyphs.ts +54 -0
  291. package/src/icons/icon.styles.ts +37 -0
  292. package/src/icons/index.ts +12 -0
  293. package/src/index.ts +24 -0
  294. package/src/primitives/Button.tsx +114 -0
  295. package/src/primitives/Metric.tsx +67 -0
  296. package/src/primitives/Row.tsx +54 -0
  297. package/src/primitives/Stack.tsx +42 -0
  298. package/src/primitives/Tag.tsx +126 -0
  299. package/src/primitives/Text.tsx +71 -0
  300. package/src/primitives/_internal/focus-ring.tsx +59 -0
  301. package/src/primitives/button.styles.ts +69 -0
  302. package/src/primitives/index.ts +8 -0
  303. package/src/primitives/metric.styles.ts +75 -0
  304. package/src/primitives/row.styles.ts +66 -0
  305. package/src/primitives/stack.styles.ts +47 -0
  306. package/src/primitives/tag.styles.ts +65 -0
  307. package/src/primitives/text.styles.ts +42 -0
  308. package/src/theme/ThemeProvider.tsx +60 -0
  309. package/src/theme/index.ts +18 -0
  310. package/src/theme/native-theme.ts +215 -0
  311. package/src/theme/types.ts +137 -0
@@ -0,0 +1,98 @@
1
+ /**
2
+ * empty-state.styles — EmptyState の pure style resolver(styleRefs conformance 対応で
3
+ * EmptyState.tsx から分離)。
4
+ *
5
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
6
+ * 直接実行できる。recipes/app/empty-state.recipe.json(melta-contracts の styleRefs)との
7
+ * 機械照合は scripts/lib/empty-state-conformance.test.ts が行う。
8
+ */
9
+
10
+ import type {
11
+ FontSizeKey,
12
+ FontWeightKey,
13
+ FontWeightValue,
14
+ NativeTheme,
15
+ SemanticColors,
16
+ SpacingKey,
17
+ ThemeMode,
18
+ } from "../theme";
19
+
20
+ /**
21
+ * default variant の構成キー(token キー)。
22
+ * component は Text / View にこのキーをそのまま渡し、resolver は同じキーから style 値を解決する
23
+ * (component と resolver が別々のキーを持って drift する事故を防ぐ SSOT)。
24
+ */
25
+ export const EMPTY_STATE_SPEC = {
26
+ padding: "8",
27
+ gap: "3",
28
+ titleFont: "lg",
29
+ titleWeight: "semibold",
30
+ titleColor: "text-heading",
31
+ descriptionFont: "sm",
32
+ descriptionColor: "text-muted",
33
+ actionMarginTop: "2",
34
+ } as const satisfies {
35
+ padding: SpacingKey;
36
+ gap: SpacingKey;
37
+ titleFont: FontSizeKey;
38
+ titleWeight: FontWeightKey;
39
+ titleColor: keyof SemanticColors;
40
+ descriptionFont: FontSizeKey;
41
+ descriptionColor: keyof SemanticColors;
42
+ actionMarginTop: SpacingKey;
43
+ };
44
+
45
+ /** slot 構成(recipe default variant の style / titleStyle / descriptionStyle / actionStyle と 1:1)。 */
46
+ export interface EmptyStateStyles {
47
+ /** 中央寄せコンテナ */
48
+ style: {
49
+ alignItems: "center";
50
+ justifyContent: "center";
51
+ padding: number;
52
+ gap: number;
53
+ };
54
+ /** compose する Text primitive(title)へ渡す値の解決結果 */
55
+ titleStyle: {
56
+ fontSize: number;
57
+ fontWeight: FontWeightValue;
58
+ color: string;
59
+ textAlign: "center";
60
+ };
61
+ /** compose する Text primitive(description)へ渡す値の解決結果 */
62
+ descriptionStyle: {
63
+ fontSize: number;
64
+ color: string;
65
+ textAlign: "center";
66
+ };
67
+ /** 任意 action(Button contained を内部 compose)のラッパ */
68
+ actionStyle: { marginTop: number };
69
+ }
70
+
71
+ /**
72
+ * default variant → style 解決(empty-state.recipe styleRefs の 1:1 写像)。
73
+ * title / description の fontSize・fontWeight・色は EMPTY_STATE_SPEC のキーから解決する
74
+ * (component 側は同じキーを Text の variant / weight / color prop に渡す = 同源)。
75
+ */
76
+ export function resolveEmptyStateStyles(theme: NativeTheme, mode: ThemeMode): EmptyStateStyles {
77
+ const sem = theme.color.semantic[mode];
78
+ return {
79
+ style: {
80
+ alignItems: "center",
81
+ justifyContent: "center",
82
+ padding: theme.spacing[EMPTY_STATE_SPEC.padding],
83
+ gap: theme.spacing[EMPTY_STATE_SPEC.gap],
84
+ },
85
+ titleStyle: {
86
+ fontSize: theme.typography.fontSize[EMPTY_STATE_SPEC.titleFont].fontSize,
87
+ fontWeight: theme.typography.fontWeight[EMPTY_STATE_SPEC.titleWeight],
88
+ color: sem[EMPTY_STATE_SPEC.titleColor],
89
+ textAlign: "center",
90
+ },
91
+ descriptionStyle: {
92
+ fontSize: theme.typography.fontSize[EMPTY_STATE_SPEC.descriptionFont].fontSize,
93
+ color: sem[EMPTY_STATE_SPEC.descriptionColor],
94
+ textAlign: "center",
95
+ },
96
+ actionStyle: { marginTop: theme.spacing[EMPTY_STATE_SPEC.actionMarginTop] },
97
+ };
98
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * header.styles — Header の pure style resolver(styleRefs conformance 対応で Header.tsx から分離)。
3
+ *
4
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
5
+ * 直接実行できる。recipes/app/header.recipe.json(melta-contracts の styleRefs)との
6
+ * 機械照合は scripts/lib/header-conformance.test.ts が行う。
7
+ */
8
+
9
+ import type { NativeTheme, ThemeMode } from "../theme";
10
+
11
+ export interface HeaderStyle {
12
+ containerStyle: {
13
+ flexDirection: "row";
14
+ alignItems: "center";
15
+ gap: number;
16
+ paddingHorizontal: number;
17
+ paddingVertical: number;
18
+ backgroundColor: string;
19
+ borderBottomWidth: 1;
20
+ borderBottomColor: string;
21
+ };
22
+ titleWrapStyle: { flex: 1 };
23
+ }
24
+
25
+ /**
26
+ * mode → ヘッダー style の解決(header.recipe styleRefs の 1:1 写像)。
27
+ * title の typography はここでは持たない — Header は melta の Text
28
+ * (variant="xl" weight="bold" color="text-heading" role="heading")を compose する(text recipe が正)。
29
+ */
30
+ export function resolveHeaderStyle(theme: NativeTheme, mode: ThemeMode): HeaderStyle {
31
+ return {
32
+ containerStyle: {
33
+ flexDirection: "row",
34
+ alignItems: "center",
35
+ gap: theme.spacing["3"],
36
+ paddingHorizontal: theme.spacing["4"],
37
+ paddingVertical: theme.spacing["3"],
38
+ backgroundColor: theme.color.semantic[mode]["bg-page"],
39
+ borderBottomWidth: 1,
40
+ borderBottomColor: theme.color.semantic[mode]["border-default"],
41
+ },
42
+ titleWrapStyle: { flex: 1 },
43
+ };
44
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * image.styles — Image の pure style resolver(styleRefs conformance 対応で Image.tsx から分離)。
3
+ *
4
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
5
+ * 直接実行できる。recipes/app/image.recipe.json(melta-contracts の styleRefs)との
6
+ * 機械照合は scripts/lib/image-conformance.test.ts が行う。
7
+ *
8
+ * recipe の variants.default.style / states.error.style は両方とも空 object=
9
+ * 「実装はデフォルトの装飾 style を持たない」が意図(contract の tokenRefs radius=radius.md
10
+ * とは意図的な食い違い。recipe description に明記済み)。ここでは radius prop
11
+ * (token キー限定)指定時のみ borderRadius + overflow:hidden を付ける。
12
+ */
13
+
14
+ import type { NativeTheme, RadiusKey } from "../theme";
15
+
16
+ /**
17
+ * ImageStyle / ViewStyle 双方に有効な共通サブセット。
18
+ * 画像本体(RNImage)と error 時の fallback View で同じ shape を共用する。
19
+ */
20
+ export interface ImageShapeStyle {
21
+ aspectRatio?: number;
22
+ borderRadius?: number;
23
+ overflow?: "hidden";
24
+ }
25
+
26
+ /** radius / aspectRatio props → shape style の解決。未指定なら空 object(装飾なし)。 */
27
+ export function resolveImageShape(
28
+ theme: NativeTheme,
29
+ { aspectRatio, radius }: { aspectRatio?: number; radius?: RadiusKey } = {},
30
+ ): ImageShapeStyle {
31
+ const borderRadius = radius != null ? theme.radius[radius] : undefined;
32
+ return {
33
+ ...(aspectRatio != null ? { aspectRatio } : null),
34
+ ...(borderRadius != null ? { borderRadius, overflow: "hidden" } : null),
35
+ };
36
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * melta-app components の公開エントリ(設計書 §1)。
3
+ * Surface はライブラリ公開(P1)で正式 export(契約 surface.contract.json + recipe を持つ implemented)。
4
+ */
5
+
6
+ export { Surface } from "./Surface";
7
+ export { Image } from "./Image";
8
+ export { Card } from "./Card";
9
+ export { Skeleton } from "./Skeleton";
10
+ export { EmptyState } from "./EmptyState";
11
+ export { Screen } from "./Screen";
12
+ export { Header } from "./Header";
13
+ export { Avatar } from "./Avatar";
14
+ export { TextField } from "./TextField";
15
+ export { Toggle } from "./Toggle";
16
+ export { Checkbox } from "./Checkbox";
17
+ export { Radio } from "./Radio";
18
+ export { Alert } from "./Alert";
19
+ export { Toast } from "./Toast";
20
+ export { Progress } from "./Progress";
21
+ export { Modal } from "./Modal";
22
+ export { ActionSheet } from "./ActionSheet";
23
+ export { BottomSheet } from "./BottomSheet";
@@ -0,0 +1,106 @@
1
+ /**
2
+ * modal.styles — Modal の pure style resolver(styleRefs conformance 対応で Modal.tsx から分離)。
3
+ *
4
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
5
+ * 直接実行できる。recipes/app/modal.recipe.json(melta-contracts の styleRefs)との
6
+ * 機械照合は scripts/lib/modal-conformance.test.ts が行う。
7
+ *
8
+ * - variant(confirmation/form/alert)は意味分類で style は 3 つとも共通(recipe と同じ)。
9
+ * props には受けるが style 解決では使わない(API 対称性のため interface には残す)。
10
+ * - overlay の黒 50% は token 外の literal(recipe description 参照。web も bg-black/50)。
11
+ * - elevation.overlay は iOS shadow* + Android elevation の複合 token のため、
12
+ * panelStyle 本体と分けて panelElevation で返す(Surface と同じ扱い)。
13
+ * - sizes はタブレット以上で効く maxWidth(モバイルは width 100% - overlay padding が先に効く)。
14
+ */
15
+
16
+ import type { ElevationStyle, FontWeightValue, NativeTheme, ThemeMode } from "../theme";
17
+ import type { SizeOf, VariantOf } from "../contracts/contract-types";
18
+
19
+ export type ModalVariant = VariantOf<"modal">;
20
+ export type ModalSize = SizeOf<"modal">;
21
+
22
+ /** size → panel の maxWidth(modal.recipe sizes の literal と 1:1)。 */
23
+ export const MODAL_MAX_WIDTH: Record<ModalSize, number> = {
24
+ small: 384,
25
+ medium: 512,
26
+ large: 768,
27
+ };
28
+
29
+ /** overlay の黒 50%(token 外 literal。recipe / web の bg-black/50 と同値)。 */
30
+ // eslint-disable-next-line melta/no-raw-color -- overlay の黒 50% は契約上 token 外の literal(recipe description / web の bg-black/50 と同値)
31
+ export const MODAL_OVERLAY_COLOR = "rgba(0,0,0,0.5)";
32
+
33
+ export interface ModalStyleProps {
34
+ /** 意味分類(style は共通)。default "confirmation"。 */
35
+ variant?: ModalVariant;
36
+ /** panel の maxWidth 段階。default "medium"。 */
37
+ size?: ModalSize;
38
+ }
39
+
40
+ export interface ModalStyle {
41
+ overlayStyle: {
42
+ flex: 1;
43
+ backgroundColor: string;
44
+ justifyContent: "center";
45
+ alignItems: "center";
46
+ padding: number;
47
+ };
48
+ panelStyle: {
49
+ backgroundColor: string;
50
+ borderRadius: number;
51
+ padding: number;
52
+ width: "100%";
53
+ maxWidth: number;
54
+ };
55
+ /** iOS shadow* + Android elevation の複合値。panelStyle と並べて spread する。 */
56
+ panelElevation: ElevationStyle;
57
+ titleStyle: { fontSize: number; fontWeight: FontWeightValue; color: string };
58
+ bodyStyle: { marginTop: number };
59
+ footerStyle: {
60
+ flexDirection: "row";
61
+ justifyContent: "flex-end";
62
+ gap: number;
63
+ marginTop: number;
64
+ };
65
+ }
66
+
67
+ /**
68
+ * size / mode → Modal style の解決(modal.recipe styleRefs の 1:1 写像)。
69
+ * variant は意味分類のみで style に影響しない(recipe の 3 variant が同値)。
70
+ */
71
+ export function resolveModalStyle(
72
+ theme: NativeTheme,
73
+ mode: ThemeMode,
74
+ { size = "medium" }: ModalStyleProps = {},
75
+ ): ModalStyle {
76
+ const semantic = theme.color.semantic[mode];
77
+ return {
78
+ overlayStyle: {
79
+ flex: 1,
80
+ backgroundColor: MODAL_OVERLAY_COLOR,
81
+ justifyContent: "center",
82
+ alignItems: "center",
83
+ padding: theme.spacing["4"],
84
+ },
85
+ panelStyle: {
86
+ backgroundColor: semantic["bg-surface"],
87
+ borderRadius: theme.radius.lg,
88
+ padding: theme.spacing["6"],
89
+ width: "100%",
90
+ maxWidth: MODAL_MAX_WIDTH[size],
91
+ },
92
+ panelElevation: theme.elevation.overlay,
93
+ titleStyle: {
94
+ fontSize: theme.typography.fontSize["2xl"].fontSize,
95
+ fontWeight: theme.typography.fontWeight.bold,
96
+ color: semantic["text-heading"],
97
+ },
98
+ bodyStyle: { marginTop: theme.spacing["2"] },
99
+ footerStyle: {
100
+ flexDirection: "row",
101
+ justifyContent: "flex-end",
102
+ gap: theme.spacing["3"],
103
+ marginTop: theme.spacing["6"],
104
+ },
105
+ };
106
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * progress.styles — Progress の pure style resolver(styleRefs conformance 対応で Progress.tsx から分離)。
3
+ *
4
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
5
+ * 直接実行できる。recipes/app/progress.recipe.json(melta-contracts の styleRefs)との
6
+ * 機械照合は scripts/lib/progress-conformance.test.ts が行う。
7
+ *
8
+ * - track(高さ8 = web h-2)の中を fill が value%(determinate)または往復アニメ
9
+ * (indeterminate variant)で埋める。fill の幅は実装(Progress.tsx)が value から算出する
10
+ * (recipe は色と形のみ、recipe description)。
11
+ * - track の背景は semantic border-default → dark mode では dark 側から解決する。
12
+ * fill は primary.500 / status.success.base(mode 非依存)。
13
+ */
14
+
15
+ import type { NativeTheme, RadiusKey, ThemeMode } from "../theme";
16
+
17
+ export type ProgressVariant = "primary" | "success" | "indeterminate";
18
+
19
+ /** track / fill の高さ(recipe の literal 8 = web h-2 の写像。token では無い raw px)。 */
20
+ export const PROGRESS_TRACK_HEIGHT = 8;
21
+
22
+ /** indeterminate variant の fill 幅比率(track の 40%。往復アニメ / reduce motion 時の静止幅)。 */
23
+ export const PROGRESS_INDETERMINATE_FILL_RATIO = 0.4;
24
+
25
+ /** 角丸キー(token キー。全 variant 共通 radius.full)。 */
26
+ export const PROGRESS_RADIUS = "full" as const satisfies RadiusKey;
27
+
28
+ /** value の 0〜100 clamp(非有限は 0 に落とす)。determinate の幅・accessibilityValue.now の同源。 */
29
+ export function clampProgressValue(value: number): number {
30
+ if (!Number.isFinite(value)) return 0;
31
+ return Math.min(100, Math.max(0, value));
32
+ }
33
+
34
+ /** slot 構成(progress.recipe 各 variant の trackStyle / fillStyle と 1:1)。 */
35
+ export interface ProgressStyles {
36
+ trackStyle: {
37
+ backgroundColor: string;
38
+ borderRadius: number;
39
+ height: number;
40
+ overflow: "hidden";
41
+ };
42
+ fillStyle: {
43
+ backgroundColor: string;
44
+ borderRadius: number;
45
+ height: number;
46
+ };
47
+ }
48
+
49
+ /**
50
+ * variant → 全 slot の style 解決(progress.recipe styleRefs の 1:1 写像)。
51
+ * - track: semantic border-default(mode 依存)。
52
+ * - fill: success は status.success.base、primary / indeterminate は primary.500(mode 非依存)。
53
+ */
54
+ export function resolveProgressStyles(
55
+ theme: NativeTheme,
56
+ mode: ThemeMode,
57
+ variant: ProgressVariant,
58
+ ): ProgressStyles {
59
+ const fill =
60
+ variant === "success" ? theme.color.status.success.base : theme.color.primary["500"];
61
+ return {
62
+ trackStyle: {
63
+ backgroundColor: theme.color.semantic[mode]["border-default"],
64
+ borderRadius: theme.radius[PROGRESS_RADIUS],
65
+ height: PROGRESS_TRACK_HEIGHT,
66
+ overflow: "hidden",
67
+ },
68
+ fillStyle: {
69
+ backgroundColor: fill,
70
+ borderRadius: theme.radius[PROGRESS_RADIUS],
71
+ height: PROGRESS_TRACK_HEIGHT,
72
+ },
73
+ };
74
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * radio.styles — Radio(RadioGroup)の pure style resolver(styleRefs conformance 対応で
3
+ * Radio.tsx から分離)。
4
+ *
5
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
6
+ * 直接実行できる。recipes/app/radio.recipe.json(melta-contracts の styleRefs)との
7
+ * 機械照合は scripts/lib/radio-conformance.test.ts が行う。
8
+ *
9
+ * recipe の構造メモ: circleStyle/dotStyle/labelStyle/groupLabelStyle/optionGap は
10
+ * variant 非依存の共通部として vertical にのみ載っている(recipe description)。
11
+ * 実装ではこの共通部を variant に関わらず同値で返す(conformance が variant 間一致を照合)。
12
+ */
13
+
14
+ import type { FontWeightValue, NativeTheme, ThemeMode } from "../theme";
15
+
16
+ export type RadioVariant = "vertical" | "horizontal" | "card-style";
17
+
18
+ /** recipe 由来の literal 値テーブル(token 化されていない数値。conformance が recipe と照合する)。 */
19
+ export const RADIO_SPEC = {
20
+ circleSize: 20,
21
+ circleBorderWidth: 2,
22
+ dotSize: 10,
23
+ cardBorderWidth: 1,
24
+ disabledOpacity: 0.5,
25
+ } as const;
26
+
27
+ export interface RadioGroupResolved {
28
+ /** variant 別レイアウト(vertical/card-style は縦積み、horizontal は wrap する横並び)。 */
29
+ containerStyle: { flexDirection: "column" | "row"; flexWrap?: "wrap"; gap: number };
30
+ /** selected 時に circle 内へ表示する内側ドット。 */
31
+ dotStyle: { width: number; height: number; borderRadius: number; backgroundColor: string };
32
+ /** option label(recipe の labelStyle スロットと 1:1。実装は Text primitive の base/text-default で同値)。 */
33
+ labelStyle: { fontSize: number; color: string };
34
+ /** groupLabel = fieldset の legend 相当(FORM_FIELDSET_LEGEND_REQUIRED で必須)。 */
35
+ groupLabelStyle: { fontSize: number; fontWeight: FontWeightValue; color: string; marginBottom: number };
36
+ /** 各 option 内の circle と label の間隔。 */
37
+ optionGap: number;
38
+ /** states.error のエラーメッセージ(danger.text-light は recipe 指定どおり mode 非依存)。 */
39
+ errorTextStyle: { fontSize: number; color: string; marginTop: number };
40
+ /** card-style のみ: 各 option を包む枠付きカード。 */
41
+ cardStyle?: { borderWidth: number; borderColor: string; borderRadius: number; padding: number };
42
+ /** card-style のみ: selected 時にカードへ重ねる差分。 */
43
+ cardSelectedStyle?: { borderColor: string; backgroundColor: string };
44
+ }
45
+
46
+ /**
47
+ * variant → グループ全体の style 解決(radio.recipe styleRefs の 1:1 写像)。
48
+ * circle は selected/error の state 差分を持つため resolveRadioCircleStyle に分離。
49
+ */
50
+ export function resolveRadioGroupStyle(
51
+ theme: NativeTheme,
52
+ mode: ThemeMode,
53
+ variant: RadioVariant,
54
+ ): RadioGroupResolved {
55
+ const sem = theme.color.semantic[mode];
56
+ const containerStyle: RadioGroupResolved["containerStyle"] =
57
+ variant === "horizontal"
58
+ ? { flexDirection: "row", flexWrap: "wrap", gap: theme.spacing["4"] }
59
+ : { flexDirection: "column", gap: theme.spacing["3"] };
60
+ return {
61
+ containerStyle,
62
+ dotStyle: {
63
+ width: RADIO_SPEC.dotSize,
64
+ height: RADIO_SPEC.dotSize,
65
+ borderRadius: theme.radius.full,
66
+ backgroundColor: theme.color.primary["500"],
67
+ },
68
+ labelStyle: {
69
+ fontSize: theme.typography.fontSize.base.fontSize,
70
+ color: sem["text-default"],
71
+ },
72
+ groupLabelStyle: {
73
+ fontSize: theme.typography.fontSize.sm.fontSize,
74
+ fontWeight: theme.typography.fontWeight.medium,
75
+ color: sem["text-heading"],
76
+ marginBottom: theme.spacing["3"],
77
+ },
78
+ optionGap: theme.spacing["2"],
79
+ errorTextStyle: {
80
+ fontSize: theme.typography.fontSize.xs.fontSize,
81
+ color: theme.color.status.danger.textLight,
82
+ marginTop: theme.spacing["2"],
83
+ },
84
+ ...(variant === "card-style"
85
+ ? {
86
+ cardStyle: {
87
+ borderWidth: RADIO_SPEC.cardBorderWidth,
88
+ borderColor: sem["border-default"],
89
+ borderRadius: theme.radius.md,
90
+ padding: theme.spacing["4"],
91
+ },
92
+ cardSelectedStyle: {
93
+ borderColor: theme.color.primary["500"],
94
+ backgroundColor: theme.color.primary["50"],
95
+ },
96
+ }
97
+ : null),
98
+ };
99
+ }
100
+
101
+ /**
102
+ * 状態 → radioCircle の style 解決(variant 非依存の共通部 + states.selected / states.error 差分)。
103
+ * error は selected より優先(契約 stateSpecs: 選択済みでもエラーなら赤枠)。
104
+ */
105
+ export function resolveRadioCircleStyle(
106
+ theme: NativeTheme,
107
+ mode: ThemeMode,
108
+ { selected, error = false }: { selected: boolean; error?: boolean },
109
+ ): {
110
+ width: number;
111
+ height: number;
112
+ borderWidth: number;
113
+ borderColor: string;
114
+ borderRadius: number;
115
+ alignItems: "center";
116
+ justifyContent: "center";
117
+ } {
118
+ const sem = theme.color.semantic[mode];
119
+ return {
120
+ width: RADIO_SPEC.circleSize,
121
+ height: RADIO_SPEC.circleSize,
122
+ borderWidth: RADIO_SPEC.circleBorderWidth,
123
+ borderColor: error
124
+ ? theme.color.status.danger.base
125
+ : selected
126
+ ? theme.color.primary["500"]
127
+ : sem["border-strong"],
128
+ borderRadius: theme.radius.full,
129
+ alignItems: "center",
130
+ justifyContent: "center",
131
+ };
132
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * screen.styles — Screen の pure style resolver(styleRefs conformance 対応で Screen.tsx から分離)。
3
+ *
4
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
5
+ * 直接実行できる。recipes/app/screen.recipe.json(melta-contracts の styleRefs)との
6
+ * 機械照合は scripts/lib/screen-conformance.test.ts が行う。
7
+ */
8
+
9
+ import type { NativeTheme, SpacingKey, ThemeMode } from "../theme";
10
+
11
+ /** content の padding(spacing token キー限定 | "none")。default "4"(recipe に焼いてある)。 */
12
+ export type ScreenPadding = SpacingKey | "none";
13
+
14
+ export interface ScreenStyleProps {
15
+ /** fixed = flex:1 の View / scroll = ScrollView contentContainerStyle。 */
16
+ variant: "fixed" | "scroll";
17
+ /** content の padding。default "4"。 */
18
+ padding?: ScreenPadding;
19
+ }
20
+
21
+ export interface ScreenStyle {
22
+ safeAreaStyle: { flex: 1; backgroundColor: string };
23
+ contentStyle: { flex?: 1; padding?: number };
24
+ }
25
+
26
+ /**
27
+ * variant / padding → 画面骨格 style の解決(screen.recipe styleRefs の 1:1 写像)。
28
+ * - safeAreaStyle は両 variant 共通(flex:1 + bg-page。mode で semantic 解決)。
29
+ * - contentStyle は fixed のみ flex:1 を持つ(scroll は ScrollView が伸びるため不要)。
30
+ * - padding="none" は padding を出力しない。
31
+ */
32
+ export function resolveScreenStyle(
33
+ theme: NativeTheme,
34
+ mode: ThemeMode,
35
+ { variant, padding = "4" }: ScreenStyleProps,
36
+ ): ScreenStyle {
37
+ return {
38
+ safeAreaStyle: { flex: 1, backgroundColor: theme.color.semantic[mode]["bg-page"] },
39
+ contentStyle: {
40
+ ...(variant === "fixed" ? { flex: 1 as const } : null),
41
+ ...(padding !== "none" ? { padding: theme.spacing[padding] } : null),
42
+ },
43
+ };
44
+ }