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,155 @@
1
+ /**
2
+ * skeleton.styles — Skeleton の pure style resolver(styleRefs conformance 対応で Skeleton.tsx から分離)。
3
+ *
4
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
5
+ * 直接実行できる。recipes/app/skeleton.recipe.json(melta-contracts の styleRefs)との
6
+ * 機械照合は scripts/lib/skeleton-conformance.test.ts が行う。
7
+ */
8
+
9
+ import type {
10
+ ElevationKey,
11
+ ElevationStyle,
12
+ NativeTheme,
13
+ RadiusKey,
14
+ SemanticColors,
15
+ SpacingKey,
16
+ ThemeMode,
17
+ } from "../theme";
18
+
19
+ export type SkeletonVariant = "text" | "circle" | "card";
20
+ /** contract states(loading = pulse、loaded = Skeleton 自体をアンマウント)。 */
21
+ export type SkeletonState = "loading" | "loaded";
22
+
23
+ /**
24
+ * card variant の Surface 土台へ渡す props(token キー)。
25
+ * component は Surface にこのキーをそのまま渡し、resolver は同じキーから style 値を解決する
26
+ * (component と resolver が別々のキーを持って drift する事故を防ぐ SSOT)。
27
+ */
28
+ export const CARD_SURFACE_SPEC = {
29
+ bg: "bg-surface",
30
+ radius: "lg",
31
+ elevation: "sm",
32
+ padding: "6",
33
+ } as const satisfies {
34
+ bg: keyof SemanticColors;
35
+ radius: RadiusKey;
36
+ elevation: ElevationKey;
37
+ padding: SpacingKey;
38
+ };
39
+
40
+ /** バー / アバター円の寸法。recipe と同じく token に対応が無い literal(recipe description 参照)。 */
41
+ export const SKELETON_METRICS = {
42
+ /** text variant の行バー高さ */
43
+ textBarHeight: 14,
44
+ /** card variant 内のバー高さ */
45
+ cardBarHeight: 12,
46
+ /** circle variant / card 内アバター円の直径 */
47
+ circleSize: 40,
48
+ } as const;
49
+
50
+ /**
51
+ * pulse の opacity 振れ幅(states.loading.animation の opacityFrom/opacityTo)。
52
+ * to は states.loading.style.opacity(= dim 側の見た目)と同値。
53
+ */
54
+ export const PULSE_OPACITY = { from: 1, to: 0.4 } as const;
55
+
56
+ /** バー1本分の style(text の行バー / card 内バーで共通の形)。 */
57
+ export interface SkeletonBarStyle {
58
+ height: number;
59
+ borderRadius: number;
60
+ backgroundColor: string;
61
+ }
62
+
63
+ /** variant ごとの slot 構成(recipe の style / barStyle と 1:1)。 */
64
+ export interface SkeletonVariantStyles {
65
+ /** text: 行バー style + 行間 gap。recipe は 1 slot に併記(component 側で gap をコンテナへ分離) */
66
+ text: { style: SkeletonBarStyle & { gap: number } };
67
+ circle: {
68
+ style: { width: number; height: number; borderRadius: number; backgroundColor: string };
69
+ };
70
+ card: {
71
+ /** Surface 土台の style。elevation は複合値(iOS shadow* + Android elevation)のまま保持 */
72
+ style: {
73
+ backgroundColor: string;
74
+ borderRadius: number;
75
+ borderWidth: number;
76
+ borderColor: string;
77
+ padding: number;
78
+ elevation: ElevationStyle;
79
+ };
80
+ barStyle: SkeletonBarStyle;
81
+ };
82
+ }
83
+
84
+ /**
85
+ * variant → style 解決(skeleton.recipe styleRefs の 1:1 写像)。
86
+ * バーの色は text / circle / card すべて border-default(contract に忠実、§1 Agent m2)。
87
+ * card の土台は CARD_SURFACE_SPEC のキーから解決する(component 側の Surface props と同源)。
88
+ */
89
+ export function resolveSkeletonVariants(theme: NativeTheme, mode: ThemeMode): SkeletonVariantStyles {
90
+ const sem = theme.color.semantic[mode];
91
+ const bar = sem["border-default"];
92
+ return {
93
+ text: {
94
+ style: {
95
+ height: SKELETON_METRICS.textBarHeight,
96
+ borderRadius: theme.radius.sm,
97
+ backgroundColor: bar,
98
+ gap: theme.spacing["2"],
99
+ },
100
+ },
101
+ circle: {
102
+ style: {
103
+ width: SKELETON_METRICS.circleSize,
104
+ height: SKELETON_METRICS.circleSize,
105
+ borderRadius: theme.radius.full,
106
+ backgroundColor: bar,
107
+ },
108
+ },
109
+ card: {
110
+ style: {
111
+ backgroundColor: sem[CARD_SURFACE_SPEC.bg],
112
+ borderRadius: theme.radius[CARD_SURFACE_SPEC.radius],
113
+ borderWidth: 1,
114
+ borderColor: bar,
115
+ padding: theme.spacing[CARD_SURFACE_SPEC.padding],
116
+ elevation: theme.elevation[CARD_SURFACE_SPEC.elevation],
117
+ },
118
+ barStyle: {
119
+ height: SKELETON_METRICS.cardBarHeight,
120
+ borderRadius: theme.radius.sm,
121
+ backgroundColor: bar,
122
+ },
123
+ },
124
+ };
125
+ }
126
+
127
+ /** states ごとの slot 構成(recipe の states.*.style / animation と 1:1)。 */
128
+ export interface SkeletonStateStyles {
129
+ loading: {
130
+ /** dim 側の見た目(pulse の下限) */
131
+ style: { opacity: number };
132
+ /** pulse アニメーション仕様(duration は motion token 由来の ms 数値) */
133
+ animation: { opacityFrom: number; opacityTo: number; duration: number };
134
+ };
135
+ /** loaded は Skeleton 自体をアンマウント(style 差分なし) */
136
+ loaded: { style: Record<string, never> };
137
+ }
138
+
139
+ /**
140
+ * states → 値解決。loading の pulse は opacity from↔to を motion.duration.slow で loop
141
+ * (reduce-motion ON 時の完全停止は component 側の責務)。
142
+ */
143
+ export function resolveSkeletonStates(theme: NativeTheme): SkeletonStateStyles {
144
+ return {
145
+ loading: {
146
+ style: { opacity: PULSE_OPACITY.to },
147
+ animation: {
148
+ opacityFrom: PULSE_OPACITY.from,
149
+ opacityTo: PULSE_OPACITY.to,
150
+ duration: theme.motion.duration.slow,
151
+ },
152
+ },
153
+ loaded: { style: {} },
154
+ };
155
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * surface.styles — Surface の pure style resolver(styleRefs conformance 対応で Surface.tsx から分離)。
3
+ *
4
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
5
+ * 直接実行できる。recipes/app/surface.recipe.json(melta-contracts の styleRefs)との
6
+ * 機械照合は scripts/lib/surface-conformance.test.ts が行う。
7
+ */
8
+
9
+ import type {
10
+ ElevationKey,
11
+ ElevationStyle,
12
+ NativeTheme,
13
+ RadiusKey,
14
+ SemanticColors,
15
+ SpacingKey,
16
+ ThemeMode,
17
+ } from "../theme";
18
+
19
+ /** Surface の見た目 props(すべて token キー限定。デフォルトは recipe default variant と 1:1)。 */
20
+ export interface SurfaceStyleProps {
21
+ bg?: keyof SemanticColors;
22
+ radius?: RadiusKey;
23
+ elevation?: ElevationKey;
24
+ padding?: SpacingKey;
25
+ }
26
+
27
+ /**
28
+ * props → 最終 style 値の解決。
29
+ * base(背景・角丸・padding)と elevation(iOS shadow* + Android elevation の複合値)を
30
+ * 分けて返し、呼び出し側が [base, elevation, style] の順で合成する(従来の適用順を維持)。
31
+ * デフォルト(bg=bg-surface / radius=lg / elevation=none、padding は無し)は
32
+ * recipe(surface.recipe.json)の default variant と一致させている。
33
+ */
34
+ export function resolveSurfaceStyle(
35
+ theme: NativeTheme,
36
+ mode: ThemeMode,
37
+ { bg = "bg-surface", radius = "lg", elevation = "none", padding }: SurfaceStyleProps = {},
38
+ ): {
39
+ base: { backgroundColor: string; borderRadius: number; padding?: number };
40
+ elevation: ElevationStyle;
41
+ } {
42
+ return {
43
+ base: {
44
+ backgroundColor: theme.color.semantic[mode][bg],
45
+ borderRadius: theme.radius[radius],
46
+ ...(padding != null ? { padding: theme.spacing[padding] } : null),
47
+ },
48
+ elevation: theme.elevation[elevation],
49
+ };
50
+ }
@@ -0,0 +1,135 @@
1
+ /**
2
+ * textfield.styles — TextField の pure style resolver(styleRefs conformance 対応で TextField.tsx から分離)。
3
+ *
4
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
5
+ * 直接実行できる。recipes/app/textfield.recipe.json(melta-contracts の styleRefs)との
6
+ * 機械照合は scripts/lib/textfield-conformance.test.ts が行う。
7
+ *
8
+ * - variant は入力の検証状態(default/error/success/disabled = 契約の variant 語彙)。
9
+ * disabled は component 側で prop disabled=true から上書きされる(TextField.tsx 参照)。
10
+ * - label/helperText/errorText は variant 非依存の共通部(recipe は default にのみ載せる規約、
11
+ * 実装は全 variant で同じものを返す)。
12
+ * - status 色(error の bg / errorText の文字色)は mode で subtle-light/dark・text-light/dark を
13
+ * 切り替える(semantic 色を semantic[mode] で引くのと同じ規約。recipe は light 側を encode)。
14
+ * - focus は state 差分(borderColor のみ)。resolveTextFieldFocusStyle で別関数にし、
15
+ * conformance が recipe states.focus と照合する。
16
+ */
17
+
18
+ import type {
19
+ NativeTheme,
20
+ ThemeMode,
21
+ FontSizeKey,
22
+ FontWeightValue,
23
+ SpacingKey,
24
+ } from "../theme";
25
+
26
+ /** 検証状態(textfield.contract の variant 語彙と 1:1)。 */
27
+ export type TextFieldVariant = "default" | "error" | "success" | "disabled";
28
+ export type TextFieldSize = "small" | "medium" | "large";
29
+
30
+ /**
31
+ * size → height / 横 padding / 入力文字 fontSize(textfield.recipe sizes と整合)。
32
+ * height の literal は recipe の値を直書きし、conformance で recipe と照合する。
33
+ */
34
+ export const TEXTFIELD_SIZE_SPEC: Record<
35
+ TextFieldSize,
36
+ { height: number; px: SpacingKey; font: FontSizeKey }
37
+ > = {
38
+ small: { height: 36, px: "3", font: "sm" },
39
+ medium: { height: 42, px: "3", font: "base" },
40
+ large: { height: 48, px: "3", font: "lg" },
41
+ };
42
+
43
+ /** resolver の出力(label → input → helperText / errorText の縦構成の各パート)。 */
44
+ export interface TextFieldResolvedStyle {
45
+ input: {
46
+ height: number;
47
+ paddingHorizontal: number;
48
+ fontSize: number;
49
+ borderWidth: number;
50
+ borderColor: string;
51
+ backgroundColor: string;
52
+ borderRadius: number;
53
+ /** 入力文字色。recipe description の「disabled のテキスト色は text-muted」を担う。 */
54
+ color: string;
55
+ };
56
+ label: {
57
+ fontSize: number;
58
+ fontWeight: FontWeightValue;
59
+ color: string;
60
+ marginBottom: number;
61
+ };
62
+ helperText: { fontSize: number; color: string; marginTop: number };
63
+ errorText: { fontSize: number; color: string; marginTop: number };
64
+ }
65
+
66
+ /**
67
+ * variant / size → 最終 style 値の解決(textfield.recipe styleRefs の 1:1 写像)。
68
+ * デフォルト(variant=default / size=medium)は component の prop デフォルトと一致させている。
69
+ */
70
+ export function resolveTextFieldStyle(
71
+ theme: NativeTheme,
72
+ mode: ThemeMode,
73
+ {
74
+ variant = "default",
75
+ size = "medium",
76
+ }: { variant?: TextFieldVariant; size?: TextFieldSize } = {},
77
+ ): TextFieldResolvedStyle {
78
+ const c = theme.color;
79
+ const sem = c.semantic[mode];
80
+ const spec = TEXTFIELD_SIZE_SPEC[size];
81
+
82
+ // variant → border / bg(recipe variants.*.inputStyle の写像)
83
+ const colors = (() => {
84
+ switch (variant) {
85
+ case "default":
86
+ return { borderColor: sem["input-border"], backgroundColor: sem["input-bg"] };
87
+ case "error":
88
+ return {
89
+ borderColor: c.status.danger.base,
90
+ backgroundColor:
91
+ mode === "light" ? c.status.danger.subtleLight : c.status.danger.subtleDark,
92
+ };
93
+ case "success":
94
+ return { borderColor: c.status.success.base, backgroundColor: sem["input-bg"] };
95
+ case "disabled":
96
+ return { borderColor: sem["border-default"], backgroundColor: sem["bg-page-alt"] };
97
+ }
98
+ })();
99
+
100
+ return {
101
+ input: {
102
+ height: spec.height,
103
+ paddingHorizontal: theme.spacing[spec.px],
104
+ fontSize: theme.typography.fontSize[spec.font].fontSize,
105
+ borderWidth: 1,
106
+ borderRadius: theme.radius.md,
107
+ color: variant === "disabled" ? sem["text-muted"] : sem["text-default"],
108
+ ...colors,
109
+ },
110
+ label: {
111
+ fontSize: theme.typography.fontSize.sm.fontSize,
112
+ fontWeight: theme.typography.fontWeight.medium,
113
+ color: sem["text-heading"],
114
+ marginBottom: theme.spacing["2"],
115
+ },
116
+ helperText: {
117
+ fontSize: theme.typography.fontSize.xs.fontSize,
118
+ color: sem["text-muted"],
119
+ marginTop: theme.spacing["1"],
120
+ },
121
+ errorText: {
122
+ fontSize: theme.typography.fontSize.xs.fontSize,
123
+ color: mode === "light" ? c.status.danger.textLight : c.status.danger.textDark,
124
+ marginTop: theme.spacing["1"],
125
+ },
126
+ };
127
+ }
128
+
129
+ /**
130
+ * focus state の inputStyle 差分(recipe states.focus の写像。borderColor のみ —
131
+ * web の ring は RN 非対応、border 幅を変えるとレイアウトシフトするため色だけ)。
132
+ */
133
+ export function resolveTextFieldFocusStyle(theme: NativeTheme): { borderColor: string } {
134
+ return { borderColor: theme.color.primary["500"] };
135
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * toast.styles — Toast の pure style resolver(styleRefs conformance 対応で Toast.tsx から分離)。
3
+ *
4
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
5
+ * 直接実行できる。recipes/app/toast.recipe.json(melta-contracts の styleRefs)との
6
+ * 機械照合は scripts/lib/toast-conformance.test.ts が行う。
7
+ *
8
+ * - Alert と同系の bg subtle + text 色に elevation.sm を重ねる(浮いている通知、recipe description)。
9
+ * elevation は iOS shadow* + Android elevation の複合 token のため containerStyle と分けて返し、
10
+ * 呼び出し側が [containerStyle, elevation, style] の順で合成する(Surface と同じ扱い)。
11
+ * - dark mode は status.*.subtleDark / textDark 側を解決する。info variant のみ primary 固定
12
+ * (dark token が無い既知の割り切り、alert と同じ)。
13
+ */
14
+
15
+ import type {
16
+ ElevationKey,
17
+ ElevationStyle,
18
+ FontSizeKey,
19
+ FontWeightKey,
20
+ FontWeightValue,
21
+ NativeTheme,
22
+ RadiusKey,
23
+ SpacingKey,
24
+ ThemeMode,
25
+ } from "../theme";
26
+
27
+ export type ToastVariant = "success" | "error" | "warning" | "info";
28
+
29
+ /**
30
+ * 構成キー(token キー)。component は Text にこのキーをそのまま渡し、resolver は同じキーから
31
+ * style 値を解決する(component と resolver が別々のキーを持って drift する事故を防ぐ SSOT)。
32
+ */
33
+ export const TOAST_SPEC = {
34
+ padding: "4",
35
+ gap: "3",
36
+ radius: "md",
37
+ elevation: "sm",
38
+ messageFont: "sm",
39
+ messageWeight: "medium",
40
+ } as const satisfies {
41
+ padding: SpacingKey;
42
+ gap: SpacingKey;
43
+ radius: RadiusKey;
44
+ elevation: ElevationKey;
45
+ messageFont: FontSizeKey;
46
+ messageWeight: FontWeightKey;
47
+ };
48
+
49
+ /**
50
+ * slot 構成(toast.recipe 各 variant の containerStyle / messageStyle と 1:1。
51
+ * containerStyle 内の elevation 参照だけは複合 token のため別 slot に分離して返す)。
52
+ */
53
+ export interface ToastStyles {
54
+ containerStyle: {
55
+ backgroundColor: string;
56
+ borderRadius: number;
57
+ padding: number;
58
+ flexDirection: "row";
59
+ alignItems: "center";
60
+ gap: number;
61
+ };
62
+ /** iOS shadow* + Android elevation の複合値。container へ spread する。 */
63
+ elevation: ElevationStyle;
64
+ /** compose する Text primitive(message)へ渡す値の解決結果 */
65
+ messageStyle: {
66
+ color: string;
67
+ fontSize: number;
68
+ fontWeight: FontWeightValue;
69
+ };
70
+ }
71
+
72
+ /**
73
+ * variant → bg / text 色の解決。
74
+ * - info: primary.50 / primary.800 固定(mode 非依存)。
75
+ * - success / error / warning: status token(error は status キー上は danger)。
76
+ * light は subtleLight / textLight、dark は subtleDark / textDark(recipe description の写像)。
77
+ */
78
+ export function resolveToastColors(
79
+ theme: NativeTheme,
80
+ mode: ThemeMode,
81
+ variant: ToastVariant,
82
+ ): { bg: string; text: string } {
83
+ if (variant === "info") {
84
+ return { bg: theme.color.primary["50"], text: theme.color.primary["800"] };
85
+ }
86
+ const status = theme.color.status[variant === "error" ? "danger" : variant];
87
+ return mode === "dark"
88
+ ? { bg: status.subtleDark, text: status.textDark }
89
+ : { bg: status.subtleLight, text: status.textLight };
90
+ }
91
+
92
+ /** variant → 全 slot の style 解決(toast.recipe styleRefs の 1:1 写像)。 */
93
+ export function resolveToastStyles(
94
+ theme: NativeTheme,
95
+ mode: ThemeMode,
96
+ variant: ToastVariant,
97
+ ): ToastStyles {
98
+ const { bg, text } = resolveToastColors(theme, mode, variant);
99
+ return {
100
+ containerStyle: {
101
+ backgroundColor: bg,
102
+ borderRadius: theme.radius[TOAST_SPEC.radius],
103
+ padding: theme.spacing[TOAST_SPEC.padding],
104
+ flexDirection: "row",
105
+ alignItems: "center",
106
+ gap: theme.spacing[TOAST_SPEC.gap],
107
+ },
108
+ elevation: theme.elevation[TOAST_SPEC.elevation],
109
+ messageStyle: {
110
+ color: text,
111
+ fontSize: theme.typography.fontSize[TOAST_SPEC.messageFont].fontSize,
112
+ fontWeight: theme.typography.fontWeight[TOAST_SPEC.messageWeight],
113
+ },
114
+ };
115
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * toggle.styles — Toggle の pure style resolver(styleRefs conformance 対応で Toggle.tsx から分離)。
3
+ *
4
+ * react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
5
+ * 直接実行できる。recipes/app/toggle.recipe.json(melta-contracts の styleRefs)との
6
+ * 機械照合は scripts/lib/toggle-conformance.test.ts が行う。
7
+ *
8
+ * - variant = variantModeledStates(off/on)。component 側で value:boolean から暗黙決定する。
9
+ * - track の寸法・thumbOffset の literal は recipe の値を直書きし、conformance で照合する。
10
+ * thumb 位置は track に padding=thumbOffset を持たせ、component 側が justifyContent
11
+ * flex-start / flex-end で寄せる(recipe description の「on 時は右端へ」の RN 表現)。
12
+ * - disabled は state 差分(opacity)。TOGGLE_DISABLED_OPACITY を component が適用し、
13
+ * conformance が recipe states.disabled と照合する。
14
+ */
15
+
16
+ import type { NativeTheme, ThemeMode } from "../theme";
17
+
18
+ /** ON/OFF(toggle.contract の variantModeledStates と 1:1)。 */
19
+ export type ToggleVariant = "off" | "on";
20
+ export type ToggleSize = "medium" | "large";
21
+
22
+ /**
23
+ * size → track / thumb 寸法(toggle.recipe sizes と整合)。
24
+ * literal は recipe の値を直書きし、conformance で recipe と照合する。
25
+ */
26
+ export const TOGGLE_SIZE_SPEC: Record<
27
+ ToggleSize,
28
+ { trackWidth: number; trackHeight: number; thumbSize: number; thumbOffset: number }
29
+ > = {
30
+ medium: { trackWidth: 44, trackHeight: 24, thumbSize: 20, thumbOffset: 2 },
31
+ large: { trackWidth: 56, trackHeight: 28, thumbSize: 24, thumbOffset: 2 },
32
+ };
33
+
34
+ /** disabled state の opacity(recipe states.disabled.style.opacity と照合)。 */
35
+ export const TOGGLE_DISABLED_OPACITY = 0.5;
36
+
37
+ /**
38
+ * variant / size → track + thumb の最終 style 値の解決(toggle.recipe styleRefs の 1:1 写像)。
39
+ * track.padding = thumbOffset(thumb を track 内で浮かせる余白)。
40
+ */
41
+ export function resolveToggleStyle(
42
+ theme: NativeTheme,
43
+ mode: ThemeMode,
44
+ { variant, size = "medium" }: { variant: ToggleVariant; size?: ToggleSize },
45
+ ): {
46
+ track: {
47
+ width: number;
48
+ height: number;
49
+ backgroundColor: string;
50
+ borderRadius: number;
51
+ padding: number;
52
+ };
53
+ thumb: { width: number; height: number; backgroundColor: string; borderRadius: number };
54
+ } {
55
+ const c = theme.color;
56
+ const sem = c.semantic[mode];
57
+ const spec = TOGGLE_SIZE_SPEC[size];
58
+ return {
59
+ track: {
60
+ width: spec.trackWidth,
61
+ height: spec.trackHeight,
62
+ backgroundColor: variant === "on" ? c.primary["500"] : sem["border-strong"],
63
+ borderRadius: theme.radius.full,
64
+ padding: spec.thumbOffset,
65
+ },
66
+ thumb: {
67
+ width: spec.thumbSize,
68
+ height: spec.thumbSize,
69
+ backgroundColor: sem["bg-surface"],
70
+ borderRadius: theme.radius.full,
71
+ },
72
+ };
73
+ }