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.
- package/LICENSE +21 -0
- package/README.md +197 -0
- package/THIRD_PARTY_LICENSES.md +198 -0
- package/lib/module/components/ActionSheet.js +87 -0
- package/lib/module/components/ActionSheet.js.map +1 -0
- package/lib/module/components/Alert.js +93 -0
- package/lib/module/components/Alert.js.map +1 -0
- package/lib/module/components/Avatar.js +93 -0
- package/lib/module/components/Avatar.js.map +1 -0
- package/lib/module/components/BottomSheet.js +69 -0
- package/lib/module/components/BottomSheet.js.map +1 -0
- package/lib/module/components/Card.js +93 -0
- package/lib/module/components/Card.js.map +1 -0
- package/lib/module/components/Checkbox.js +115 -0
- package/lib/module/components/Checkbox.js.map +1 -0
- package/lib/module/components/EmptyState.js +70 -0
- package/lib/module/components/EmptyState.js.map +1 -0
- package/lib/module/components/Header.js +53 -0
- package/lib/module/components/Header.js.map +1 -0
- package/lib/module/components/Image.js +67 -0
- package/lib/module/components/Image.js.map +1 -0
- package/lib/module/components/Modal.js +95 -0
- package/lib/module/components/Modal.js.map +1 -0
- package/lib/module/components/Progress.js +113 -0
- package/lib/module/components/Progress.js.map +1 -0
- package/lib/module/components/Radio.js +134 -0
- package/lib/module/components/Radio.js.map +1 -0
- package/lib/module/components/Screen.js +57 -0
- package/lib/module/components/Screen.js.map +1 -0
- package/lib/module/components/Skeleton.js +169 -0
- package/lib/module/components/Skeleton.js.map +1 -0
- package/lib/module/components/Surface.js +49 -0
- package/lib/module/components/Surface.js.map +1 -0
- package/lib/module/components/TextField.js +84 -0
- package/lib/module/components/TextField.js.map +1 -0
- package/lib/module/components/Toast.js +105 -0
- package/lib/module/components/Toast.js.map +1 -0
- package/lib/module/components/Toggle.js +77 -0
- package/lib/module/components/Toggle.js.map +1 -0
- package/lib/module/components/action-sheet.styles.js +70 -0
- package/lib/module/components/action-sheet.styles.js.map +1 -0
- package/lib/module/components/alert.styles.js +80 -0
- package/lib/module/components/alert.styles.js.map +1 -0
- package/lib/module/components/avatar.styles.js +94 -0
- package/lib/module/components/avatar.styles.js.map +1 -0
- package/lib/module/components/bottom-sheet.styles.js +55 -0
- package/lib/module/components/bottom-sheet.styles.js.map +1 -0
- package/lib/module/components/card.styles.js +50 -0
- package/lib/module/components/card.styles.js.map +1 -0
- package/lib/module/components/checkbox.styles.js +55 -0
- package/lib/module/components/checkbox.styles.js.map +1 -0
- package/lib/module/components/empty-state.styles.js +60 -0
- package/lib/module/components/empty-state.styles.js.map +1 -0
- package/lib/module/components/header.styles.js +33 -0
- package/lib/module/components/header.styles.js.map +1 -0
- package/lib/module/components/image.styles.js +37 -0
- package/lib/module/components/image.styles.js.map +1 -0
- package/lib/module/components/index.js +26 -0
- package/lib/module/components/index.js.map +1 -0
- package/lib/module/components/modal.styles.js +68 -0
- package/lib/module/components/modal.styles.js.map +1 -0
- package/lib/module/components/progress.styles.js +55 -0
- package/lib/module/components/progress.styles.js.map +1 -0
- package/lib/module/components/radio.styles.js +96 -0
- package/lib/module/components/radio.styles.js.map +1 -0
- package/lib/module/components/screen.styles.js +38 -0
- package/lib/module/components/screen.styles.js.map +1 -0
- package/lib/module/components/skeleton.styles.js +114 -0
- package/lib/module/components/skeleton.styles.js.map +1 -0
- package/lib/module/components/surface.styles.js +37 -0
- package/lib/module/components/surface.styles.js.map +1 -0
- package/lib/module/components/textfield.styles.js +121 -0
- package/lib/module/components/textfield.styles.js.map +1 -0
- package/lib/module/components/toast.styles.js +81 -0
- package/lib/module/components/toast.styles.js.map +1 -0
- package/lib/module/components/toggle.styles.js +69 -0
- package/lib/module/components/toggle.styles.js.map +1 -0
- package/lib/module/contracts/contract-types.js +192 -0
- package/lib/module/contracts/contract-types.js.map +1 -0
- package/lib/module/icons/Icon.js +57 -0
- package/lib/module/icons/Icon.js.map +1 -0
- package/lib/module/icons/glyphs.js +257 -0
- package/lib/module/icons/glyphs.js.map +1 -0
- package/lib/module/icons/icon.styles.js +28 -0
- package/lib/module/icons/icon.styles.js.map +1 -0
- package/lib/module/icons/index.js +14 -0
- package/lib/module/icons/index.js.map +1 -0
- package/lib/module/index.js +20 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/primitives/Button.js +105 -0
- package/lib/module/primitives/Button.js.map +1 -0
- package/lib/module/primitives/Metric.js +68 -0
- package/lib/module/primitives/Metric.js.map +1 -0
- package/lib/module/primitives/Row.js +43 -0
- package/lib/module/primitives/Row.js.map +1 -0
- package/lib/module/primitives/Stack.js +39 -0
- package/lib/module/primitives/Stack.js.map +1 -0
- package/lib/module/primitives/Tag.js +160 -0
- package/lib/module/primitives/Tag.js.map +1 -0
- package/lib/module/primitives/Text.js +54 -0
- package/lib/module/primitives/Text.js.map +1 -0
- package/lib/module/primitives/_internal/focus-ring.js +57 -0
- package/lib/module/primitives/_internal/focus-ring.js.map +1 -0
- package/lib/module/primitives/button.styles.js +88 -0
- package/lib/module/primitives/button.styles.js.map +1 -0
- package/lib/module/primitives/index.js +11 -0
- package/lib/module/primitives/index.js.map +1 -0
- package/lib/module/primitives/metric.styles.js +54 -0
- package/lib/module/primitives/metric.styles.js.map +1 -0
- package/lib/module/primitives/row.styles.js +53 -0
- package/lib/module/primitives/row.styles.js.map +1 -0
- package/lib/module/primitives/stack.styles.js +37 -0
- package/lib/module/primitives/stack.styles.js.map +1 -0
- package/lib/module/primitives/tag.styles.js +56 -0
- package/lib/module/primitives/tag.styles.js.map +1 -0
- package/lib/module/primitives/text.styles.js +33 -0
- package/lib/module/primitives/text.styles.js.map +1 -0
- package/lib/module/theme/ThemeProvider.js +41 -0
- package/lib/module/theme/ThemeProvider.js.map +1 -0
- package/lib/module/theme/index.js +19 -0
- package/lib/module/theme/index.js.map +1 -0
- package/lib/module/theme/native-theme.js +201 -0
- package/lib/module/theme/native-theme.js.map +1 -0
- package/lib/module/theme/types.js +4 -0
- package/lib/module/theme/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/components/ActionSheet.d.ts +45 -0
- package/lib/typescript/src/components/ActionSheet.d.ts.map +1 -0
- package/lib/typescript/src/components/Alert.d.ts +43 -0
- package/lib/typescript/src/components/Alert.d.ts.map +1 -0
- package/lib/typescript/src/components/Avatar.d.ts +45 -0
- package/lib/typescript/src/components/Avatar.d.ts.map +1 -0
- package/lib/typescript/src/components/BottomSheet.d.ts +36 -0
- package/lib/typescript/src/components/BottomSheet.d.ts.map +1 -0
- package/lib/typescript/src/components/Card.d.ts +46 -0
- package/lib/typescript/src/components/Card.d.ts.map +1 -0
- package/lib/typescript/src/components/Checkbox.d.ts +40 -0
- package/lib/typescript/src/components/Checkbox.d.ts.map +1 -0
- package/lib/typescript/src/components/EmptyState.d.ts +36 -0
- package/lib/typescript/src/components/EmptyState.d.ts.map +1 -0
- package/lib/typescript/src/components/Header.d.ts +34 -0
- package/lib/typescript/src/components/Header.d.ts.map +1 -0
- package/lib/typescript/src/components/Image.d.ts +41 -0
- package/lib/typescript/src/components/Image.d.ts.map +1 -0
- package/lib/typescript/src/components/Modal.d.ts +46 -0
- package/lib/typescript/src/components/Modal.d.ts.map +1 -0
- package/lib/typescript/src/components/Progress.d.ts +39 -0
- package/lib/typescript/src/components/Progress.d.ts.map +1 -0
- package/lib/typescript/src/components/Radio.d.ts +52 -0
- package/lib/typescript/src/components/Radio.d.ts.map +1 -0
- package/lib/typescript/src/components/Screen.d.ts +42 -0
- package/lib/typescript/src/components/Screen.d.ts.map +1 -0
- package/lib/typescript/src/components/Skeleton.d.ts +37 -0
- package/lib/typescript/src/components/Skeleton.d.ts.map +1 -0
- package/lib/typescript/src/components/Surface.d.ts +31 -0
- package/lib/typescript/src/components/Surface.d.ts.map +1 -0
- package/lib/typescript/src/components/TextField.d.ts +45 -0
- package/lib/typescript/src/components/TextField.d.ts.map +1 -0
- package/lib/typescript/src/components/Toast.d.ts +45 -0
- package/lib/typescript/src/components/Toast.d.ts.map +1 -0
- package/lib/typescript/src/components/Toggle.d.ts +39 -0
- package/lib/typescript/src/components/Toggle.d.ts.map +1 -0
- package/lib/typescript/src/components/action-sheet.styles.d.ts +65 -0
- package/lib/typescript/src/components/action-sheet.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/alert.styles.d.ts +61 -0
- package/lib/typescript/src/components/alert.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/avatar.styles.d.ts +60 -0
- package/lib/typescript/src/components/avatar.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/bottom-sheet.styles.d.ts +50 -0
- package/lib/typescript/src/components/bottom-sheet.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/card.styles.d.ts +27 -0
- package/lib/typescript/src/components/card.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/checkbox.styles.d.ts +55 -0
- package/lib/typescript/src/components/checkbox.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/empty-state.styles.d.ts +58 -0
- package/lib/typescript/src/components/empty-state.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/header.styles.d.ts +30 -0
- package/lib/typescript/src/components/header.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/image.styles.d.ts +28 -0
- package/lib/typescript/src/components/image.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/index.d.ts +23 -0
- package/lib/typescript/src/components/index.d.ts.map +1 -0
- package/lib/typescript/src/components/modal.styles.d.ts +66 -0
- package/lib/typescript/src/components/modal.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/progress.styles.d.ts +44 -0
- package/lib/typescript/src/components/progress.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/radio.styles.d.ts +91 -0
- package/lib/typescript/src/components/radio.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/screen.styles.d.ts +34 -0
- package/lib/typescript/src/components/screen.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/skeleton.styles.d.ts +105 -0
- package/lib/typescript/src/components/skeleton.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/surface.styles.d.ts +31 -0
- package/lib/typescript/src/components/surface.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/textfield.styles.d.ts +75 -0
- package/lib/typescript/src/components/textfield.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/toast.styles.d.ts +62 -0
- package/lib/typescript/src/components/toast.styles.d.ts.map +1 -0
- package/lib/typescript/src/components/toggle.styles.d.ts +53 -0
- package/lib/typescript/src/components/toggle.styles.d.ts.map +1 -0
- package/lib/typescript/src/contracts/contract-types.d.ts +193 -0
- package/lib/typescript/src/contracts/contract-types.d.ts.map +1 -0
- package/lib/typescript/src/icons/Icon.d.ts +40 -0
- package/lib/typescript/src/icons/Icon.d.ts.map +1 -0
- package/lib/typescript/src/icons/glyphs.d.ts +259 -0
- package/lib/typescript/src/icons/glyphs.d.ts.map +1 -0
- package/lib/typescript/src/icons/icon.styles.d.ts +20 -0
- package/lib/typescript/src/icons/icon.styles.d.ts.map +1 -0
- package/lib/typescript/src/icons/index.d.ts +12 -0
- package/lib/typescript/src/icons/index.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +12 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/primitives/Button.d.ts +48 -0
- package/lib/typescript/src/primitives/Button.d.ts.map +1 -0
- package/lib/typescript/src/primitives/Metric.d.ts +38 -0
- package/lib/typescript/src/primitives/Metric.d.ts.map +1 -0
- package/lib/typescript/src/primitives/Row.d.ts +37 -0
- package/lib/typescript/src/primitives/Row.d.ts.map +1 -0
- package/lib/typescript/src/primitives/Stack.d.ts +33 -0
- package/lib/typescript/src/primitives/Stack.d.ts.map +1 -0
- package/lib/typescript/src/primitives/Tag.d.ts +43 -0
- package/lib/typescript/src/primitives/Tag.d.ts.map +1 -0
- package/lib/typescript/src/primitives/Text.d.ts +45 -0
- package/lib/typescript/src/primitives/Text.d.ts.map +1 -0
- package/lib/typescript/src/primitives/_internal/focus-ring.d.ts +31 -0
- package/lib/typescript/src/primitives/_internal/focus-ring.d.ts.map +1 -0
- package/lib/typescript/src/primitives/button.styles.d.ts +29 -0
- package/lib/typescript/src/primitives/button.styles.d.ts.map +1 -0
- package/lib/typescript/src/primitives/index.d.ts +8 -0
- package/lib/typescript/src/primitives/index.d.ts.map +1 -0
- package/lib/typescript/src/primitives/metric.styles.d.ts +43 -0
- package/lib/typescript/src/primitives/metric.styles.d.ts.map +1 -0
- package/lib/typescript/src/primitives/row.styles.d.ts +50 -0
- package/lib/typescript/src/primitives/row.styles.d.ts.map +1 -0
- package/lib/typescript/src/primitives/stack.styles.d.ts +34 -0
- package/lib/typescript/src/primitives/stack.styles.d.ts.map +1 -0
- package/lib/typescript/src/primitives/tag.styles.d.ts +32 -0
- package/lib/typescript/src/primitives/tag.styles.d.ts.map +1 -0
- package/lib/typescript/src/primitives/text.styles.d.ts +26 -0
- package/lib/typescript/src/primitives/text.styles.d.ts.map +1 -0
- package/lib/typescript/src/theme/ThemeProvider.d.ts +32 -0
- package/lib/typescript/src/theme/ThemeProvider.d.ts.map +1 -0
- package/lib/typescript/src/theme/index.d.ts +15 -0
- package/lib/typescript/src/theme/index.d.ts.map +1 -0
- package/lib/typescript/src/theme/native-theme.d.ts +3 -0
- package/lib/typescript/src/theme/native-theme.d.ts.map +1 -0
- package/lib/typescript/src/theme/types.d.ts +121 -0
- package/lib/typescript/src/theme/types.d.ts.map +1 -0
- package/package.json +120 -0
- package/src/components/ActionSheet.tsx +112 -0
- package/src/components/Alert.tsx +84 -0
- package/src/components/Avatar.tsx +110 -0
- package/src/components/BottomSheet.tsx +81 -0
- package/src/components/Card.tsx +102 -0
- package/src/components/Checkbox.tsx +107 -0
- package/src/components/EmptyState.tsx +64 -0
- package/src/components/Header.tsx +51 -0
- package/src/components/Image.tsx +89 -0
- package/src/components/Modal.tsx +113 -0
- package/src/components/Progress.tsx +124 -0
- package/src/components/Radio.tsx +151 -0
- package/src/components/Screen.tsx +62 -0
- package/src/components/Skeleton.tsx +154 -0
- package/src/components/Surface.tsx +37 -0
- package/src/components/TextField.tsx +102 -0
- package/src/components/Toast.tsx +103 -0
- package/src/components/Toggle.tsx +94 -0
- package/src/components/action-sheet.styles.ts +102 -0
- package/src/components/alert.styles.ts +115 -0
- package/src/components/avatar.styles.ts +110 -0
- package/src/components/bottom-sheet.styles.ts +78 -0
- package/src/components/card.styles.ts +56 -0
- package/src/components/checkbox.styles.ts +83 -0
- package/src/components/empty-state.styles.ts +98 -0
- package/src/components/header.styles.ts +44 -0
- package/src/components/image.styles.ts +36 -0
- package/src/components/index.ts +23 -0
- package/src/components/modal.styles.ts +106 -0
- package/src/components/progress.styles.ts +74 -0
- package/src/components/radio.styles.ts +132 -0
- package/src/components/screen.styles.ts +44 -0
- package/src/components/skeleton.styles.ts +155 -0
- package/src/components/surface.styles.ts +50 -0
- package/src/components/textfield.styles.ts +135 -0
- package/src/components/toast.styles.ts +115 -0
- package/src/components/toggle.styles.ts +73 -0
- package/src/contracts/contract-types.ts +199 -0
- package/src/icons/Icon.tsx +65 -0
- package/src/icons/glyphs.ts +54 -0
- package/src/icons/icon.styles.ts +37 -0
- package/src/icons/index.ts +12 -0
- package/src/index.ts +24 -0
- package/src/primitives/Button.tsx +114 -0
- package/src/primitives/Metric.tsx +67 -0
- package/src/primitives/Row.tsx +54 -0
- package/src/primitives/Stack.tsx +42 -0
- package/src/primitives/Tag.tsx +126 -0
- package/src/primitives/Text.tsx +71 -0
- package/src/primitives/_internal/focus-ring.tsx +59 -0
- package/src/primitives/button.styles.ts +69 -0
- package/src/primitives/index.ts +8 -0
- package/src/primitives/metric.styles.ts +75 -0
- package/src/primitives/row.styles.ts +66 -0
- package/src/primitives/stack.styles.ts +47 -0
- package/src/primitives/tag.styles.ts +65 -0
- package/src/primitives/text.styles.ts +42 -0
- package/src/theme/ThemeProvider.tsx +60 -0
- package/src/theme/index.ts +18 -0
- package/src/theme/native-theme.ts +215 -0
- package/src/theme/types.ts +137 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// ⚠️ 自動生成ファイル — 手で編集しないこと。
|
|
2
|
+
// 生成元: scripts/generate-contract-types.ts(入力 melta-contracts/components/*.contract.json)
|
|
3
|
+
// 各 component の variant/size/state を contract から codegen した型 + 実行時メタ(__contract 用)。
|
|
4
|
+
|
|
5
|
+
/** 各 contract メタの shape(§2 A-3: 生成結果が shape から逸脱したら型で検知する)。 */
|
|
6
|
+
export interface ContractShape {
|
|
7
|
+
id: string;
|
|
8
|
+
version: string;
|
|
9
|
+
variants: readonly string[];
|
|
10
|
+
sizes: readonly string[];
|
|
11
|
+
states: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const CONTRACTS = {
|
|
15
|
+
text: {
|
|
16
|
+
id: "text",
|
|
17
|
+
version: "0.1.0",
|
|
18
|
+
variants: ["xs", "sm", "base", "lg", "xl", "2xl", "3xl"],
|
|
19
|
+
sizes: [],
|
|
20
|
+
states: ["default"],
|
|
21
|
+
},
|
|
22
|
+
button: {
|
|
23
|
+
id: "button",
|
|
24
|
+
version: "2.0.0",
|
|
25
|
+
variants: ["contained", "outlined", "brand-outline", "neutral", "lighted", "danger", "subtle"],
|
|
26
|
+
sizes: ["small", "medium", "large"],
|
|
27
|
+
states: ["default", "hover", "focus", "disabled", "loading"],
|
|
28
|
+
},
|
|
29
|
+
tag: {
|
|
30
|
+
id: "tag",
|
|
31
|
+
version: "2.0.0",
|
|
32
|
+
variants: ["basic", "removable", "filter-chip"],
|
|
33
|
+
sizes: [],
|
|
34
|
+
states: ["default", "active", "inactive", "hover", "focus"],
|
|
35
|
+
},
|
|
36
|
+
card: {
|
|
37
|
+
id: "card",
|
|
38
|
+
version: "2.0.0",
|
|
39
|
+
variants: ["basic", "media", "action", "link"],
|
|
40
|
+
sizes: [],
|
|
41
|
+
states: ["default", "hover", "focus-within"],
|
|
42
|
+
},
|
|
43
|
+
image: {
|
|
44
|
+
id: "image",
|
|
45
|
+
version: "0.1.0",
|
|
46
|
+
variants: ["default"],
|
|
47
|
+
sizes: [],
|
|
48
|
+
states: ["default", "error"],
|
|
49
|
+
},
|
|
50
|
+
surface: {
|
|
51
|
+
id: "surface",
|
|
52
|
+
version: "0.1.0",
|
|
53
|
+
variants: ["default"],
|
|
54
|
+
sizes: [],
|
|
55
|
+
states: ["default"],
|
|
56
|
+
},
|
|
57
|
+
skeleton: {
|
|
58
|
+
id: "skeleton",
|
|
59
|
+
version: "2.0.0",
|
|
60
|
+
variants: ["text", "card", "circle"],
|
|
61
|
+
sizes: [],
|
|
62
|
+
states: ["default", "loading", "loaded"],
|
|
63
|
+
},
|
|
64
|
+
emptyState: {
|
|
65
|
+
id: "empty-state",
|
|
66
|
+
version: "0.1.0",
|
|
67
|
+
variants: ["default"],
|
|
68
|
+
sizes: [],
|
|
69
|
+
states: ["default"],
|
|
70
|
+
},
|
|
71
|
+
metric: {
|
|
72
|
+
id: "metric",
|
|
73
|
+
version: "0.1.0",
|
|
74
|
+
variants: ["default"],
|
|
75
|
+
sizes: ["sm", "md", "lg"],
|
|
76
|
+
states: ["default"],
|
|
77
|
+
},
|
|
78
|
+
stack: {
|
|
79
|
+
id: "stack",
|
|
80
|
+
version: "0.1.0",
|
|
81
|
+
variants: ["default"],
|
|
82
|
+
sizes: [],
|
|
83
|
+
states: ["default"],
|
|
84
|
+
},
|
|
85
|
+
row: {
|
|
86
|
+
id: "row",
|
|
87
|
+
version: "0.1.0",
|
|
88
|
+
variants: ["default"],
|
|
89
|
+
sizes: [],
|
|
90
|
+
states: ["default"],
|
|
91
|
+
},
|
|
92
|
+
screen: {
|
|
93
|
+
id: "screen",
|
|
94
|
+
version: "0.1.0",
|
|
95
|
+
variants: ["fixed", "scroll"],
|
|
96
|
+
sizes: [],
|
|
97
|
+
states: ["default"],
|
|
98
|
+
},
|
|
99
|
+
header: {
|
|
100
|
+
id: "header",
|
|
101
|
+
version: "0.1.0",
|
|
102
|
+
variants: ["default"],
|
|
103
|
+
sizes: [],
|
|
104
|
+
states: ["default"],
|
|
105
|
+
},
|
|
106
|
+
icon: {
|
|
107
|
+
id: "icon",
|
|
108
|
+
version: "0.1.0",
|
|
109
|
+
variants: ["default"],
|
|
110
|
+
sizes: ["sm", "md", "lg"],
|
|
111
|
+
states: ["default"],
|
|
112
|
+
},
|
|
113
|
+
avatar: {
|
|
114
|
+
id: "avatar",
|
|
115
|
+
version: "2.0.0",
|
|
116
|
+
variants: ["image", "initials", "group"],
|
|
117
|
+
sizes: ["small", "medium", "large"],
|
|
118
|
+
states: ["default", "online", "away", "offline"],
|
|
119
|
+
},
|
|
120
|
+
textfield: {
|
|
121
|
+
id: "textfield",
|
|
122
|
+
version: "2.0.0",
|
|
123
|
+
variants: ["default", "error", "disabled", "success"],
|
|
124
|
+
sizes: ["small", "medium", "large"],
|
|
125
|
+
states: ["default", "hover", "focus", "error", "disabled", "success"],
|
|
126
|
+
},
|
|
127
|
+
toggle: {
|
|
128
|
+
id: "toggle",
|
|
129
|
+
version: "2.0.0",
|
|
130
|
+
variants: ["off", "on"],
|
|
131
|
+
sizes: ["medium", "large"],
|
|
132
|
+
states: ["off", "on", "hover", "focus", "disabled"],
|
|
133
|
+
},
|
|
134
|
+
checkbox: {
|
|
135
|
+
id: "checkbox",
|
|
136
|
+
version: "2.0.0",
|
|
137
|
+
variants: ["default", "disabled", "indeterminate"],
|
|
138
|
+
sizes: [],
|
|
139
|
+
states: ["default", "checked", "unchecked", "indeterminate", "disabled", "error", "focus"],
|
|
140
|
+
},
|
|
141
|
+
radio: {
|
|
142
|
+
id: "radio",
|
|
143
|
+
version: "2.0.0",
|
|
144
|
+
variants: ["vertical", "horizontal", "card-style"],
|
|
145
|
+
sizes: [],
|
|
146
|
+
states: ["default", "selected", "unselected", "disabled", "error", "focus"],
|
|
147
|
+
},
|
|
148
|
+
alert: {
|
|
149
|
+
id: "alert",
|
|
150
|
+
version: "2.0.0",
|
|
151
|
+
variants: ["info", "success", "warning", "error"],
|
|
152
|
+
sizes: [],
|
|
153
|
+
states: ["default", "dismissing"],
|
|
154
|
+
},
|
|
155
|
+
toast: {
|
|
156
|
+
id: "toast",
|
|
157
|
+
version: "2.0.0",
|
|
158
|
+
variants: ["success", "error", "warning", "info"],
|
|
159
|
+
sizes: [],
|
|
160
|
+
states: ["default", "entering", "visible", "dismissing", "hover"],
|
|
161
|
+
},
|
|
162
|
+
progress: {
|
|
163
|
+
id: "progress",
|
|
164
|
+
version: "2.0.0",
|
|
165
|
+
variants: ["primary", "success", "indeterminate"],
|
|
166
|
+
sizes: [],
|
|
167
|
+
states: ["default", "determinate", "indeterminate", "complete"],
|
|
168
|
+
},
|
|
169
|
+
modal: {
|
|
170
|
+
id: "modal",
|
|
171
|
+
version: "2.0.0",
|
|
172
|
+
variants: ["confirmation", "form", "alert"],
|
|
173
|
+
sizes: ["small", "medium", "large"],
|
|
174
|
+
states: ["default", "open", "closing"],
|
|
175
|
+
},
|
|
176
|
+
actionSheet: {
|
|
177
|
+
id: "action-sheet",
|
|
178
|
+
version: "0.1.0",
|
|
179
|
+
variants: ["default"],
|
|
180
|
+
sizes: [],
|
|
181
|
+
states: ["default"],
|
|
182
|
+
},
|
|
183
|
+
bottomSheet: {
|
|
184
|
+
id: "bottom-sheet",
|
|
185
|
+
version: "0.1.0",
|
|
186
|
+
variants: ["default"],
|
|
187
|
+
sizes: [],
|
|
188
|
+
states: ["default"],
|
|
189
|
+
},
|
|
190
|
+
} as const satisfies Record<string, ContractShape>;
|
|
191
|
+
|
|
192
|
+
export type ContractId = keyof typeof CONTRACTS;
|
|
193
|
+
|
|
194
|
+
/** contract の variant キー union(例: VariantOf<"text"> = "xs" | ... | "3xl")。空なら never。 */
|
|
195
|
+
export type VariantOf<K extends ContractId> = (typeof CONTRACTS)[K]["variants"][number];
|
|
196
|
+
/** contract の size キー union(空なら never)。 */
|
|
197
|
+
export type SizeOf<K extends ContractId> = (typeof CONTRACTS)[K]["sizes"][number];
|
|
198
|
+
/** contract の state キー union。 */
|
|
199
|
+
export type StateOf<K extends ContractId> = (typeof CONTRACTS)[K]["states"][number];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon — 統一アイコン primitive(Charcoal Icons、単色 tint)。
|
|
3
|
+
* contract: icon(app 先行定義、melta-contracts)。dogfood 不足-2(絵文字・生 Text 代用)の解消。
|
|
4
|
+
*
|
|
5
|
+
* ⚠️ 依存境界: このファイルだけが react-native-svg を import する。melta-app 本体エントリ
|
|
6
|
+
* ("melta-app")は依存ゼロを維持し、Icon は subpath エントリ "melta-app/icons" からだけ
|
|
7
|
+
* export される(optional peerDependency。利用者は `npx expo install react-native-svg` が必要)。
|
|
8
|
+
*
|
|
9
|
+
* - name は glyphs.ts(assets/icons/*.svg からの codegen、commit 済み配布)のキー。
|
|
10
|
+
* - color は semantic token キー限定(default "text-default")、size は contract sizes(sm/md/lg)。
|
|
11
|
+
* - a11y: 意味を持つ場合は accessibilityLabel を渡す。無指定は装飾扱いで a11y ツリーから除外
|
|
12
|
+
* (contract a11y required の両ケース)。
|
|
13
|
+
* - 決定ロジックは pure resolver(icon.styles.ts)に分離 — recipe との機械照合対象。
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { useMemo } from "react";
|
|
17
|
+
import Svg, { Path } from "react-native-svg";
|
|
18
|
+
import { useTheme } from "../theme";
|
|
19
|
+
import type { SemanticColors } from "../theme";
|
|
20
|
+
import { CONTRACTS, type SizeOf } from "../contracts/contract-types";
|
|
21
|
+
import { resolveIconStyle, type IconStyle } from "./icon.styles";
|
|
22
|
+
import { GLYPHS, type IconName } from "./glyphs";
|
|
23
|
+
|
|
24
|
+
interface IconProps {
|
|
25
|
+
/** グリフ名(glyphs.ts のキー。例 "close" / "share-ios")。 */
|
|
26
|
+
name: IconName;
|
|
27
|
+
/** サイズ(contract sizes)。default "md"(20px)。 */
|
|
28
|
+
size?: SizeOf<"icon">;
|
|
29
|
+
/** 色(semantic token キーのみ)。default "text-default"。 */
|
|
30
|
+
color?: keyof SemanticColors;
|
|
31
|
+
/** 意味を持つ icon は必須。省略時は装飾扱い(a11y ツリーから除外)。 */
|
|
32
|
+
accessibilityLabel?: string;
|
|
33
|
+
testID?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function Icon({ name, size = "md", color = "text-default", accessibilityLabel, testID }: IconProps) {
|
|
37
|
+
const { theme, mode } = useTheme();
|
|
38
|
+
|
|
39
|
+
const resolved = useMemo<IconStyle>(
|
|
40
|
+
() => resolveIconStyle(theme, mode, size, color),
|
|
41
|
+
[theme, mode, size, color],
|
|
42
|
+
);
|
|
43
|
+
const glyph = GLYPHS[name];
|
|
44
|
+
const decorative = accessibilityLabel == null;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Svg
|
|
48
|
+
width={resolved.width}
|
|
49
|
+
height={resolved.height}
|
|
50
|
+
viewBox={glyph.viewBox}
|
|
51
|
+
accessible={!decorative}
|
|
52
|
+
accessibilityRole="image"
|
|
53
|
+
accessibilityLabel={accessibilityLabel}
|
|
54
|
+
accessibilityElementsHidden={decorative}
|
|
55
|
+
importantForAccessibility={decorative ? "no-hide-descendants" : "yes"}
|
|
56
|
+
testID={testID}
|
|
57
|
+
>
|
|
58
|
+
{glyph.paths.map((p, i) => (
|
|
59
|
+
<Path key={i} d={p.d} fillRule={p.fillRule} fill={resolved.color} />
|
|
60
|
+
))}
|
|
61
|
+
</Svg>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Icon.__contract = CONTRACTS.icon;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// ⚠️ 自動生成ファイル — 手で編集しないこと。
|
|
2
|
+
// 生成元: scripts/generate-icons.ts(入力 assets/icons/*.svg = Charcoal Icons, Apache-2.0)
|
|
3
|
+
// 帰属表示は THIRD_PARTY_LICENSES.md を参照。
|
|
4
|
+
|
|
5
|
+
export interface Glyph {
|
|
6
|
+
viewBox: string;
|
|
7
|
+
paths: readonly { d: string; fillRule?: "evenodd" }[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const GLYPHS_SOURCE = {
|
|
11
|
+
"add": { viewBox: "0 0 24 24", paths: [{ d: "M14 10h4a2 2 0 110 4h-4v4a2 2 0 11-4 0v-4H6a2 2 0 110-4h4V6a2 2 0 114 0v4z" }] },
|
|
12
|
+
"back": { viewBox: "0 0 16 16", paths: [{ d: "M9.961 11.043a1 1 0 01-1.414 1.414L4.09 8l4.457-4.457a1 1 0 011.414 1.414L6.918 8l3.043 3.043z" }] },
|
|
13
|
+
"calendar": { viewBox: "0 0 24 24", paths: [{ d: "M8 3a1 1 0 00-2 0v1.126C4.275 4.57 3 6.136 3 8v10a4 4 0 004 4h10a4 4 0 004-4V8a4.002 4.002 0 00-3-3.874V3a1 1 0 10-2 0v1H8V3zm-3 7v8a2 2 0 002 2h10a2 2 0 002-2v-8H5z", fillRule: "evenodd" as const }] },
|
|
14
|
+
"camera": { viewBox: "0 0 24 24", paths: [{ d: "M8.5 13.5a3.5 3.5 0 117 0 3.5 3.5 0 01-7 0z" }, { d: "M9.295 3.557A2 2 0 0110.68 3h2.742a2 2 0 011.414.586L17.25 6H20a2 2 0 012 2v11a2 2 0 01-2 2H4a2 2 0 01-2-2V8a2 2 0 012-2h2.75l2.545-2.443zM12 8a5.5 5.5 0 100 11 5.5 5.5 0 000-11z", fillRule: "evenodd" as const }] },
|
|
15
|
+
"check": { viewBox: "0 0 24 24", paths: [{ d: "M15.848 7.449a2 2 0 012.804 2.853l-8.664 8.514-4.402-4.402a2 2 0 112.828-2.828l1.598 1.598 5.836-5.735z" }] },
|
|
16
|
+
"close": { viewBox: "0 0 24 24", paths: [{ d: "M8.414 5.586a2 2 0 10-2.828 2.828L9.172 12l-3.586 3.586a2 2 0 102.828 2.828L12 14.828l3.586 3.586a2 2 0 102.828-2.828L14.828 12l3.586-3.586a2 2 0 10-2.828-2.828L12 9.172 8.414 5.586z" }] },
|
|
17
|
+
"comment": { viewBox: "0 0 16 16", paths: [{ d: "M5.4 13.409l-2.64.377.333-2.332a6 6 0 112.306 1.955z" }] },
|
|
18
|
+
"copy": { viewBox: "0 0 24 24", paths: [{ d: "M3 7a1 1 0 011 1v10a2 2 0 002 2h11a1 1 0 110 2H6a4 4 0 01-4-4V8a1 1 0 011-1z" }, { d: "M19 2a3 3 0 013 3v10a3 3 0 01-3 3H9a3 3 0 01-3-3V5a3 3 0 013-3h10zM9 4a1 1 0 00-1 1v10a1 1 0 001 1h10a1 1 0 001-1V5a1 1 0 00-1-1H9z", fillRule: "evenodd" as const }] },
|
|
19
|
+
"discovery": { viewBox: "0 0 24 24", paths: [{ d: "M22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10zM6 18l4-8 8-4-4 8-8 4zm6-5a1 1 0 100-2 1 1 0 000 2z", fillRule: "evenodd" as const }] },
|
|
20
|
+
"down": { viewBox: "0 0 24 24", paths: [{ d: "M16.125 12V5a1 1 0 00-1-1h-6a1 1 0 00-1 1v7H4.539c-.89 0-1.337 1.077-.707 1.707L12.125 22l8.194-8.297c.623-.632.176-1.703-.712-1.703h-3.482z", fillRule: "evenodd" as const }] },
|
|
21
|
+
"edit": { viewBox: "0 0 32 32", paths: [{ d: "M7.26 23.537l1.12-5.6 7.955-7.955 5.657 5.657 1.768-1.768-5.657-5.657 2.121-2.121a2 2 0 012.828 0l2.829 2.828a2 2 0 010 2.829L14.037 23.594l-5.6 1.12a1 1 0 01-1.177-1.177z", fillRule: "evenodd" as const }] },
|
|
22
|
+
"error": { viewBox: "0 0 24 24", paths: [{ d: "M12 4a2 2 0 00-2 2v6.5a2 2 0 104 0V6a2 2 0 00-2-2zm2.25 13.75a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z", fillRule: "evenodd" as const }] },
|
|
23
|
+
"filter": { viewBox: "0 0 24 24", paths: [{ d: "M10.5 13.468L3.574 6.4C2.335 5.133 3.232 3 5.005 3h13.99c1.773 0 2.67 2.133 1.43 3.4L13.5 13.467V19a3 3 0 01-3.002 3v-8.532z" }] },
|
|
24
|
+
"home": { viewBox: "0 0 24 24", paths: [{ d: "M9 19a1 1 0 01-1 1H4a1 1 0 01-1-1v-7.586a1 1 0 01.293-.707l8-8a1 1 0 011.414 0l8 8a1 1 0 01.293.707V19a1 1 0 01-1 1h-4a1 1 0 01-1-1v-3.5a3 3 0 10-6 0V19z", fillRule: "evenodd" as const }] },
|
|
25
|
+
"image": { viewBox: "0 0 24 24", paths: [{ d: "M6 4a3 3 0 00-3 3v10a3 3 0 003 3h12a3 3 0 003-3V7a3 3 0 00-3-3H6zm13 8.5l-4 2-6-3-4 2V17a1 1 0 001 1h12a1 1 0 001-1v-4.5zM18 9a2 2 0 11-4 0 2 2 0 014 0z", fillRule: "evenodd" as const }] },
|
|
26
|
+
"info": { viewBox: "0 0 24 24", paths: [{ d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2.5 9a1 1 0 011-1H12a1 1 0 011 1v5h1a1 1 0 110 2h-4a1 1 0 110-2h1v-4h-.5a1 1 0 01-1-1zM12 5a1.5 1.5 0 100 3 1.5 1.5 0 000-3z", fillRule: "evenodd" as const }] },
|
|
27
|
+
"like-off": { viewBox: "0 0 24 24", paths: [{ d: "M13.087 21.021C18.792 17.831 22 13.81 22 8.91A5.91 5.91 0 0016.09 3c-1.529 0-2.976.747-4.09 1.834C10.886 3.747 9.439 3 7.91 3A5.91 5.91 0 002 8.91c0 4.9 3.208 8.92 8.913 12.111a2.227 2.227 0 002.174 0zM16.09 5A3.91 3.91 0 0120 8.91c0 3.86-2.482 7.342-7.889 10.366a.229.229 0 01-.222 0C6.482 16.252 4 12.77 4 8.91A3.91 3.91 0 017.91 5c1.115 0 2.38.723 3.287 1.943L12 8.021l.803-1.078C13.71 5.723 14.975 5 16.09 5z", fillRule: "evenodd" as const }] },
|
|
28
|
+
"like-on": { viewBox: "0 0 24 24", paths: [{ d: "M2 9.023A6.023 6.023 0 018.023 3c1.486 0 2.88.68 3.977 1.677C13.096 3.68 14.49 3 15.977 3A6.023 6.023 0 0122 9.023c0 4.908-3.22 8.893-8.807 12.018a2.443 2.443 0 01-2.386 0C5.22 17.916 2 13.931 2 9.023z", fillRule: "evenodd" as const }] },
|
|
29
|
+
"link": { viewBox: "0 0 24 24", paths: [{ d: "M14.031 3.367a4.666 4.666 0 116.6 6.598l-4.243 4.243a4.665 4.665 0 01-2.163 1.226h-.037l-.193.04-.107.02-.23.034h-.113c-.05 0-.097.005-.142.01a1.296 1.296 0 01-.095.01l-.2.023h-.253a4.616 4.616 0 01-.497-.047 5.356 5.356 0 01-.403-.083l-.197-.053a2.64 2.64 0 01-.213-.07l-.078-.029c-.045-.016-.09-.032-.135-.051a4.71 4.71 0 00-.07-.03 4.627 4.627 0 01-1.473-.994 1.333 1.333 0 010-1.879 1.366 1.366 0 011.873 0 2 2 0 002.826 0l1.093-1.086.027-.03 3.126-3.123a2 2 0 00-2.83-2.83l-2.51 2.507a.333.333 0 01-.362.073 5.6 5.6 0 00-2.13-.417h-.123a.333.333 0 01-.243-.57l3.495-3.492z" }, { d: "M13.418 9.166c.284.18.547.391.784.63.27.27.41.644.386 1.026-.023.32-.16.62-.386.847a1.366 1.366 0 01-1.873 0 2 2 0 00-2.827 0L5.246 15.92a2 2 0 002.83 2.83l2.516-2.52a.333.333 0 01.363-.073 5.612 5.612 0 002.133.413h.134a.333.333 0 01.236.57l-3.5 3.5A4.636 4.636 0 016.664 22a4.666 4.666 0 01-3.3-7.962l4.24-4.242a4.666 4.666 0 015.816-.63z" }] },
|
|
30
|
+
"menu": { viewBox: "0 0 24 24", paths: [{ d: "M4 7a1 1 0 011-1h14a1 1 0 110 2H5a1 1 0 01-1-1zM4 12a1 1 0 011-1h14a1 1 0 110 2H5a1 1 0 01-1-1zM5 16a1 1 0 100 2h14a1 1 0 100-2H5z" }] },
|
|
31
|
+
"more": { viewBox: "0 0 16 16", paths: [{ d: "M6.043 4.957a1 1 0 011.414-1.414L11.914 8l-4.457 4.457a1 1 0 01-1.414-1.414L9.086 8 6.043 4.957z" }] },
|
|
32
|
+
"next": { viewBox: "0 0 24 24", paths: [{ d: "M8.086 16.586a2 2 0 102.828 2.828L18.328 12l-7.414-7.414a2 2 0 10-2.828 2.828L12.672 12l-4.586 4.586z" }] },
|
|
33
|
+
"notification": { viewBox: "0 0 24 24", paths: [{ d: "M18 9.25V12l1.561 4.684A1 1 0 0118.613 18H5.387a1 1 0 01-.948-1.316L6 12V9.25C6 5.798 8.686 3 12 3s6 2.798 6 6.25zM12 21a3.001 3.001 0 01-2.83-2h5.66A3.001 3.001 0 0112 21z" }] },
|
|
34
|
+
"prev": { viewBox: "0 0 24 24", paths: [{ d: "M15.913 16.586a2 2 0 01-2.829 2.828L5.67 12l7.414-7.414a2 2 0 012.829 2.828L11.327 12l4.586 4.586z" }] },
|
|
35
|
+
"question": { viewBox: "0 0 24 24", paths: [{ d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1.179 15.254a1.25 1.25 0 11-2.5 0 1.25 1.25 0 012.5 0zm.058-3.98c.01-.02.02-.04.03-.05.272-.4.651-.732 1.036-1.069.886-.777 1.8-1.579 1.494-3.281-.29-1.69-1.64-3.08-3.33-3.33-2.06-.3-3.88.97-4.43 2.79-.17.58.27 1.17.87 1.17h.2c.41 0 .74-.29.88-.65.32-.89 1.26-1.5 2.3-1.28.96.2 1.66 1.15 1.57 2.13-.068.763-.613 1.186-1.219 1.654-.377.293-.778.603-1.101 1.026l-.01-.01a.326.326 0 00-.046.066 1.302 1.302 0 01-.084.129 2.261 2.261 0 00-.27.515.156.156 0 01-.025.05c-.01.015-.02.03-.025.05-.01.01-.01.02-.01.03-.12.36-.2.79-.2 1.3h2.01a2.11 2.11 0 01.18-.89c.01-.04.02-.08.04-.11.04-.08.09-.16.14-.24z", fillRule: "evenodd" as const }] },
|
|
36
|
+
"reload": { viewBox: "0 0 24 24", paths: [{ d: "M12 7a6 6 0 106 6 1 1 0 112 0 8 8 0 11-8-8h1.42l-1.7-2.125a1 1 0 111.56-1.25l3 3.75a1 1 0 010 1.25l-3 3.75a1 1 0 01-1.56-1.25L13.42 7H12z" }] },
|
|
37
|
+
"search": { viewBox: "0 0 24 24", paths: [{ d: "M15.461 10.615c0-1.334-.474-2.475-1.422-3.423-.948-.949-2.09-1.423-3.424-1.423s-2.475.474-3.423 1.423c-.949.948-1.423 2.09-1.423 3.423 0 1.335.474 2.476 1.423 3.424.948.948 2.09 1.422 3.423 1.422 1.335 0 2.476-.474 3.424-1.422s1.422-2.09 1.422-3.424zm5.539 9c0 .375-.137.7-.411.974a1.33 1.33 0 01-.974.411c-.389 0-.714-.137-.973-.411l-3.71-3.7a7.407 7.407 0 01-4.317 1.342c-1.03 0-2.017-.2-2.958-.6a7.613 7.613 0 01-2.434-1.623A7.614 7.614 0 013.6 13.574c-.4-.941-.6-1.927-.6-2.959 0-1.03.2-2.017.6-2.958.4-.941.941-1.753 1.623-2.434A7.614 7.614 0 017.657 3.6c.941-.4 1.927-.6 2.958-.6 1.032 0 2.018.2 2.959.6.941.4 1.752.941 2.434 1.623a7.613 7.613 0 011.622 2.434c.4.941.6 1.927.6 2.958a7.407 7.407 0 01-1.34 4.316l3.71 3.71c.267.268.4.592.4.974z", fillRule: "evenodd" as const }] },
|
|
38
|
+
"send": { viewBox: "0 0 24 24", paths: [{ d: "M3 13.5h5a1.5 1.5 0 000-3H3V3.695a1 1 0 011.466-.885l15.853 8.343a1 1 0 010 1.77L4.466 21.267A1 1 0 013 20.382V13.5z", fillRule: "evenodd" as const }] },
|
|
39
|
+
"settings": { viewBox: "0 0 24 24", paths: [{ d: "M19.5 12c0 .61.224 1.21.704 1.586l1.336 1.044c.19.15.24.42.12.64l-2 3.46c-.12.22-.38.31-.61.22l-1.589-.638c-.56-.225-1.186-.13-1.705.176-.528.31-.94.814-1.026 1.42l-.24 1.672c-.03.24-.24.42-.49.42h-4c-.25 0-.46-.18-.49-.42l-.24-1.68c-.087-.6-.495-1.098-1.02-1.404-.524-.305-1.156-.407-1.718-.181l-1.582.635c-.22.08-.49 0-.61-.22l-2-3.46a.505.505 0 01.12-.64l1.335-1.044c.48-.376.705-.976.705-1.586 0-.61-.224-1.21-.705-1.586L2.46 9.37a.493.493 0 01-.12-.64l2-3.46c.12-.22.38-.31.61-.22l1.588.638c.56.225 1.186.13 1.706-.176.528-.31.94-.814 1.026-1.42l.24-1.672c.03-.24.24-.42.49-.42h4c.25 0 .46.18.49.42l.24 1.68c.087.6.494 1.098 1.02 1.404.524.306 1.155.407 1.718.181l1.582-.635c.22-.08.49 0 .61.22l2 3.46c.12.22.07.49-.12.64l-1.336 1.044c-.48.376-.704.976-.704 1.586zm-11 0c0 1.93 1.57 3.5 3.5 3.5s3.5-1.57 3.5-3.5-1.57-3.5-3.5-3.5-3.5 1.57-3.5 3.5z", fillRule: "evenodd" as const }] },
|
|
40
|
+
"share-android": { viewBox: "0 0 24 24", paths: [{ d: "M13 6.375a2.75 2.75 0 111.03 2.146L8.72 11.586a2.773 2.773 0 010 .828l5.312 3.065a2.75 2.75 0 11-1 1.732l-5.312-3.065a2.75 2.75 0 110-4.293l5.312-3.064A2.773 2.773 0 0113 6.375z" }] },
|
|
41
|
+
"share-ios": { viewBox: "0 0 24 24", paths: [{ d: "M12 2.586L7.293 7.293a1 1 0 001.414 1.414L11 6.414V13a1 1 0 102 0V6.414l2.293 2.293a1 1 0 101.414-1.414L12 2.586z" }, { d: "M6 18v-6H4v6a3 3 0 003 3h10a3 3 0 003-3v-6h-2v6a1 1 0 01-1 1H7a1 1 0 01-1-1z" }] },
|
|
42
|
+
"trash": { viewBox: "0 0 24 24", paths: [{ d: "M9 4h6v1h2.5a1 1 0 110 2h-11a1 1 0 010-2H9V4zM7.01 8a1 1 0 00-1 1.01l.105 10a1 1 0 001 .99H17a1 1 0 001-1V9a1 1 0 00-1-1H7.01z" }] },
|
|
43
|
+
"up": { viewBox: "0 0 24 24", paths: [{ d: "M16 12v7a1 1 0 01-1 1H9a1 1 0 01-1-1v-7H4.414c-.89 0-1.337-1.077-.707-1.707L12 2l8.194 8.297c.623.632.176 1.703-.712 1.703H16z", fillRule: "evenodd" as const }] },
|
|
44
|
+
"user": { viewBox: "0 0 32 32", paths: [{ d: "M21.39 11.357c0 2.959-2.386 5.357-5.328 5.357-2.941 0-5.326-2.398-5.326-5.357S13.12 6 16.062 6c2.942 0 5.327 2.398 5.327 5.357zm-5.328 5.357c4.315 0 7.813 3.402 7.813 7.598v.26c0 .788-.636 1.428-1.42 1.428H9.67c-.784 0-1.42-.64-1.42-1.429v-.26c0-4.195 3.498-7.597 7.813-7.597z", fillRule: "evenodd" as const }] },
|
|
45
|
+
"users": { viewBox: "0 0 24 24", paths: [{ d: "M7.507 10.5a3.75 3.75 0 10-.014 0C4.459 10.504 2 12.883 2 15.818 2 16.471 2.53 17 3.182 17h7.451a5.608 5.608 0 012.21-2.445c-.585-2.325-2.752-4.052-5.336-4.055zm8.993 4a3.75 3.75 0 100-7.5 3.75 3.75 0 000 7.5zm0 0c-3.038 0-5.5 2.381-5.5 5.318V20a1 1 0 001 1h9a1 1 0 001-1v-.182c0-2.937-2.462-5.318-5.5-5.318z", fillRule: "evenodd" as const }] },
|
|
46
|
+
"warning": { viewBox: "0 0 24 24", paths: [{ d: "M4.47 21h15.06c1.54 0 2.5-1.67 1.73-3L13.73 4.99c-.77-1.33-2.69-1.33-3.46 0L2.74 18c-.77 1.33.19 3 1.73 3zM11 9a1 1 0 112 0v4a1 1 0 11-2 0V9zm1 7a1.25 1.25 0 100 2.5 1.25 1.25 0 000-2.5z", fillRule: "evenodd" as const }] },
|
|
47
|
+
} as const;
|
|
48
|
+
|
|
49
|
+
export type IconName = keyof typeof GLYPHS_SOURCE;
|
|
50
|
+
|
|
51
|
+
export const GLYPHS: Record<IconName, Glyph> = GLYPHS_SOURCE;
|
|
52
|
+
|
|
53
|
+
/** 利用可能な icon name 一覧(catalog / ドキュメント生成用)。 */
|
|
54
|
+
export const ICON_NAMES = Object.keys(GLYPHS) as IconName[];
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* icon.styles — Icon の pure style resolver(styleRefs conformance 対応で Icon.tsx から分離)。
|
|
3
|
+
*
|
|
4
|
+
* react-native を import しない純粋モジュールにすることで node テスト(tsx --test)から
|
|
5
|
+
* 直接実行できる。recipes/app/icon.recipe.json(melta-contracts の styleRefs)との
|
|
6
|
+
* 機械照合は scripts/lib/icon-conformance.test.ts が行う。
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { NativeTheme, SemanticColors, ThemeMode } from "../theme";
|
|
10
|
+
|
|
11
|
+
export type IconSize = "sm" | "md" | "lg";
|
|
12
|
+
|
|
13
|
+
/** サイズ軸(contract sizes の height と 1:1。width=height の正方形)。 */
|
|
14
|
+
const SIZE_TABLE = { sm: 16, md: 20, lg: 24 } as const;
|
|
15
|
+
|
|
16
|
+
export interface IconStyle {
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
color: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* size / color → Icon style の解決(icon.recipe styleRefs の 1:1 写像)。
|
|
24
|
+
* デフォルト(size=md / color=text-default)は recipe の default variant と一致させている。
|
|
25
|
+
*/
|
|
26
|
+
export function resolveIconStyle(
|
|
27
|
+
theme: NativeTheme,
|
|
28
|
+
mode: ThemeMode,
|
|
29
|
+
size: IconSize = "md",
|
|
30
|
+
color: keyof SemanticColors = "text-default",
|
|
31
|
+
): IconStyle {
|
|
32
|
+
return {
|
|
33
|
+
width: SIZE_TABLE[size],
|
|
34
|
+
height: SIZE_TABLE[size],
|
|
35
|
+
color: theme.color.semantic[mode][color],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* melta-app/icons — Icon の subpath エントリ。
|
|
3
|
+
*
|
|
4
|
+
* 本体エントリ("melta-app")から分離している理由: Icon だけが react-native-svg
|
|
5
|
+
* (optional peerDependency)に依存するため。Metro は import を静的に解決するので、
|
|
6
|
+
* 本体エントリに Icon を含めると react-native-svg 未 install の利用者がバンドルできなくなる。
|
|
7
|
+
* この subpath を import する利用者だけが react-native-svg を要求される。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export { Icon } from "./Icon";
|
|
11
|
+
export { GLYPHS, ICON_NAMES } from "./glyphs";
|
|
12
|
+
export type { IconName, Glyph } from "./glyphs";
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* melta-app — melta デザインシステムの React Native 実装(公開エントリ)。
|
|
3
|
+
*
|
|
4
|
+
* 契約(npm: melta-contracts)を SSOT とし、theme(トークンの RN 正規化)/
|
|
5
|
+
* primitives / components がその契約を満たす。契約との整合は conformance テストが機械照合する。
|
|
6
|
+
* アプリ本体ではなく UI kit。使い方はルートを ThemeProvider で包み、コンポーネントを import する。
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// theme: トークン(melta-contracts/tokens.json 由来、codegen 済み)+ Provider + helpers
|
|
10
|
+
export * from "./theme";
|
|
11
|
+
|
|
12
|
+
// primitives / components(契約 appStatus=implemented の集合と一致。conformance が担保)
|
|
13
|
+
export * from "./primitives";
|
|
14
|
+
export * from "./components";
|
|
15
|
+
|
|
16
|
+
// 契約メタ(variant/size/state の実行時参照 + 型。__contract 照合にも使う)
|
|
17
|
+
export {
|
|
18
|
+
CONTRACTS,
|
|
19
|
+
type ContractId,
|
|
20
|
+
type ContractShape,
|
|
21
|
+
type VariantOf,
|
|
22
|
+
type SizeOf,
|
|
23
|
+
type StateOf,
|
|
24
|
+
} from "./contracts/contract-types";
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Button — CTA / セカンダリ / アイコンボタン(設計書 §1, §4 C-3)。contract: button。
|
|
3
|
+
*
|
|
4
|
+
* - variant 7(contained/outlined/brand-outline/neutral/lighted/danger/subtle)× size 3(small/medium/large)。
|
|
5
|
+
* - iconOnly は discriminated union で accessibilityLabel 必須を型強制(§4、label 排他)。
|
|
6
|
+
* - states(§2 mapping): hover→pressed(背景を pressed 色に)、focus→FocusRing overlay(共通 helper)、
|
|
7
|
+
* disabled→prop(opacity + 非活性)、loading→Spinner + disabled 相当。
|
|
8
|
+
* - 色は variant ごとに NativeTheme から解決(button.contract tokenRefs を 1:1 で写像)。
|
|
9
|
+
* contained の pressed は hover-bg=primary.700(contract に native readable token あり、唯一)。
|
|
10
|
+
* 他 variant の pressed 視覚変化は contract が Tailwind のみ=Phase1 non-conformant(§2 M-1)、
|
|
11
|
+
* ここでは pressed 時に薄い overlay を敷く近似に留め、Phase2 で contract に pressed-* token 追加。
|
|
12
|
+
* - height は contract sizes(small32/medium40/large48)。
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { useMemo, type ReactNode } from "react";
|
|
16
|
+
import {
|
|
17
|
+
ActivityIndicator,
|
|
18
|
+
Pressable,
|
|
19
|
+
View,
|
|
20
|
+
type StyleProp,
|
|
21
|
+
type ViewStyle,
|
|
22
|
+
} from "react-native";
|
|
23
|
+
import { Text } from "./Text";
|
|
24
|
+
import { useTheme } from "../theme";
|
|
25
|
+
import { useFocusRing, FocusRing } from "./_internal/focus-ring";
|
|
26
|
+
import { CONTRACTS } from "../contracts/contract-types";
|
|
27
|
+
import { SIZE_SPEC, resolveVariant, type ButtonVariant, type ButtonSize } from "./button.styles";
|
|
28
|
+
|
|
29
|
+
interface ButtonBase {
|
|
30
|
+
variant?: ButtonVariant;
|
|
31
|
+
size?: ButtonSize;
|
|
32
|
+
leadingIcon?: ReactNode;
|
|
33
|
+
trailingIcon?: ReactNode;
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
loading?: boolean;
|
|
36
|
+
onPress?: () => void;
|
|
37
|
+
style?: StyleProp<ViewStyle>;
|
|
38
|
+
testID?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type ButtonProps = ButtonBase &
|
|
42
|
+
(
|
|
43
|
+
// iconOnly は leadingIcon 必須(空ボタンを型で排除、§4 の最小 DU を保ちつつ icon 1個必須)。
|
|
44
|
+
| { iconOnly: true; accessibilityLabel: string; leadingIcon: ReactNode; label?: never }
|
|
45
|
+
| { iconOnly?: false; label: string }
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
export function Button(props: ButtonProps) {
|
|
49
|
+
const { theme, mode } = useTheme();
|
|
50
|
+
const {
|
|
51
|
+
variant = "contained",
|
|
52
|
+
size = "medium",
|
|
53
|
+
leadingIcon,
|
|
54
|
+
trailingIcon,
|
|
55
|
+
disabled = false,
|
|
56
|
+
loading = false,
|
|
57
|
+
onPress,
|
|
58
|
+
style,
|
|
59
|
+
testID,
|
|
60
|
+
} = props;
|
|
61
|
+
const { focused, focusHandlers } = useFocusRing();
|
|
62
|
+
|
|
63
|
+
const spec = SIZE_SPEC[size];
|
|
64
|
+
const colors = useMemo(() => resolveVariant(theme, mode, variant), [theme, mode, variant]);
|
|
65
|
+
const isDisabled = disabled || loading;
|
|
66
|
+
const iconOnly = props.iconOnly === true;
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<Pressable
|
|
70
|
+
{...focusHandlers}
|
|
71
|
+
onPress={onPress}
|
|
72
|
+
disabled={isDisabled}
|
|
73
|
+
accessibilityRole="button"
|
|
74
|
+
accessibilityState={{ disabled: isDisabled, busy: loading }}
|
|
75
|
+
accessibilityLabel={iconOnly ? props.accessibilityLabel : undefined}
|
|
76
|
+
testID={testID}
|
|
77
|
+
style={({ pressed }) => [
|
|
78
|
+
{
|
|
79
|
+
height: spec.height,
|
|
80
|
+
flexDirection: "row",
|
|
81
|
+
alignItems: "center",
|
|
82
|
+
justifyContent: "center",
|
|
83
|
+
gap: theme.spacing["2"],
|
|
84
|
+
borderRadius: theme.radius.md,
|
|
85
|
+
backgroundColor: pressed && !isDisabled ? colors.pressedBg : colors.bg,
|
|
86
|
+
...(iconOnly
|
|
87
|
+
? { width: spec.iconBox }
|
|
88
|
+
: { paddingHorizontal: theme.spacing[spec.px] }),
|
|
89
|
+
...(colors.border != null ? { borderWidth: 1, borderColor: colors.border } : null),
|
|
90
|
+
opacity: isDisabled ? 0.5 : 1,
|
|
91
|
+
},
|
|
92
|
+
style,
|
|
93
|
+
]}
|
|
94
|
+
>
|
|
95
|
+
{loading ? (
|
|
96
|
+
<ActivityIndicator color={colors.textColor} />
|
|
97
|
+
) : (
|
|
98
|
+
<>
|
|
99
|
+
{leadingIcon != null && <View>{leadingIcon}</View>}
|
|
100
|
+
{!iconOnly && (
|
|
101
|
+
<Text variant={spec.font} weight="medium" style={{ color: colors.textColor }}>
|
|
102
|
+
{props.label}
|
|
103
|
+
</Text>
|
|
104
|
+
)}
|
|
105
|
+
{trailingIcon != null && <View>{trailingIcon}</View>}
|
|
106
|
+
</>
|
|
107
|
+
)}
|
|
108
|
+
<FocusRing visible={focused && !isDisabled} radius={theme.radius.md} />
|
|
109
|
+
</Pressable>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Phase 2 conformance test 用の contract メタ(§2 A-3)。
|
|
114
|
+
Button.__contract = CONTRACTS.button;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metric — 数値 + 単位 + ラベルの指標表示 primitive(設計書 §1、意思決定3)。
|
|
3
|
+
* contract: metric(app 先行定義)。ツー活カードの主役(走行距離 / 時間 / 獲得標高 等)。
|
|
4
|
+
*
|
|
5
|
+
* - value は tabular(fontVariant:["tabular-nums"])で桁揃え。Text primitive は fontVariant を
|
|
6
|
+
* 公開しないので、value は RN Text を直接使う。
|
|
7
|
+
* - size(sm/md/lg) は value の fontSize token にマップ(contract の height は想定行高、実 fontSize は
|
|
8
|
+
* pure resolver(metric.styles.ts)で token 解決する。metric.contract intent 参照)。
|
|
9
|
+
* - unit は value の1段下の fontSize でベースライン揃え。label は muted。
|
|
10
|
+
* - a11y: value+unit+label を1つの accessibilityLabel に合成して読み上げる(contract a11y)。
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { useMemo } from "react";
|
|
14
|
+
import { Text as RNText, View, type StyleProp, type ViewStyle } from "react-native";
|
|
15
|
+
import { useTheme } from "../theme";
|
|
16
|
+
import { CONTRACTS, type SizeOf } from "../contracts/contract-types";
|
|
17
|
+
import { resolveMetricStyles } from "./metric.styles";
|
|
18
|
+
|
|
19
|
+
type MetricSize = SizeOf<"metric">; // "sm" | "md" | "lg"
|
|
20
|
+
|
|
21
|
+
interface MetricProps {
|
|
22
|
+
/** 整形済みの数値文字列(整形は呼び出し側)。 */
|
|
23
|
+
value: string;
|
|
24
|
+
/** 単位("km" / "m" / "h:mm" 等)。 */
|
|
25
|
+
unit?: string;
|
|
26
|
+
/** ラベル("走行距離" 等)。 */
|
|
27
|
+
label?: string;
|
|
28
|
+
size?: MetricSize;
|
|
29
|
+
align?: "start" | "center";
|
|
30
|
+
style?: StyleProp<ViewStyle>;
|
|
31
|
+
testID?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function Metric({
|
|
35
|
+
value,
|
|
36
|
+
unit,
|
|
37
|
+
label,
|
|
38
|
+
size = "md",
|
|
39
|
+
align = "start",
|
|
40
|
+
style,
|
|
41
|
+
testID,
|
|
42
|
+
}: MetricProps) {
|
|
43
|
+
const { theme, mode } = useTheme();
|
|
44
|
+
|
|
45
|
+
// 決定ロジックは pure resolver(metric.styles.ts)に分離済み — recipe との機械照合対象。
|
|
46
|
+
const styles = useMemo(() => resolveMetricStyles(theme, mode, size), [theme, mode, size]);
|
|
47
|
+
|
|
48
|
+
const a11yLabel = [value, unit, label].filter(Boolean).join(" ");
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<View
|
|
52
|
+
testID={testID}
|
|
53
|
+
accessible
|
|
54
|
+
accessibilityLabel={a11yLabel}
|
|
55
|
+
style={[{ alignItems: align === "center" ? "center" : "flex-start" }, style]}
|
|
56
|
+
>
|
|
57
|
+
<View style={{ flexDirection: "row", alignItems: "baseline" }}>
|
|
58
|
+
<RNText style={styles.valueStyle}>{value}</RNText>
|
|
59
|
+
{unit != null && <RNText style={styles.unitStyle}>{unit}</RNText>}
|
|
60
|
+
</View>
|
|
61
|
+
{label != null && <RNText style={styles.labelStyle}>{label}</RNText>}
|
|
62
|
+
</View>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Phase 2 conformance test 用の contract メタ(§2 A-3)。
|
|
67
|
+
Metric.__contract = CONTRACTS.metric;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Row — 横並び layout primitive。RN コア View の薄いラッパ。
|
|
3
|
+
* contract: row(app 先行定義、melta-contracts)。dogfood 不足-1(生 flexbox 手書き)の解消。
|
|
4
|
+
*
|
|
5
|
+
* - gap は spacing token キー限定(生数値不可、§5 lint の意味を保つ)。
|
|
6
|
+
* - align(交差軸、default center)/ justify(主軸、default start)/ wrap(折返し)。
|
|
7
|
+
* - 決定ロジックは pure resolver(row.styles.ts)に分離 — recipe との機械照合対象。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { useMemo, type ReactNode } from "react";
|
|
11
|
+
import { View, type StyleProp, type ViewStyle } from "react-native";
|
|
12
|
+
import { useTheme } from "../theme";
|
|
13
|
+
import type { SpacingKey } from "../theme";
|
|
14
|
+
import { CONTRACTS } from "../contracts/contract-types";
|
|
15
|
+
import { resolveRowStyle, type RowAlign, type RowJustify, type RowStyle } from "./row.styles";
|
|
16
|
+
|
|
17
|
+
interface RowProps {
|
|
18
|
+
/** 子要素間の gap(spacing token キー限定)。省略時 gap なし。 */
|
|
19
|
+
gap?: SpacingKey;
|
|
20
|
+
/** 交差軸の配置。default "center"。 */
|
|
21
|
+
align?: RowAlign;
|
|
22
|
+
/** 主軸の配置。default "start"。 */
|
|
23
|
+
justify?: RowJustify;
|
|
24
|
+
/** 折返し。default false。 */
|
|
25
|
+
wrap?: boolean;
|
|
26
|
+
style?: StyleProp<ViewStyle>;
|
|
27
|
+
testID?: string;
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function Row({
|
|
32
|
+
gap,
|
|
33
|
+
align = "center",
|
|
34
|
+
justify = "start",
|
|
35
|
+
wrap = false,
|
|
36
|
+
style,
|
|
37
|
+
testID,
|
|
38
|
+
children,
|
|
39
|
+
}: RowProps) {
|
|
40
|
+
const { theme } = useTheme();
|
|
41
|
+
|
|
42
|
+
const layout = useMemo<RowStyle>(
|
|
43
|
+
() => resolveRowStyle(theme, { gap, align, justify, wrap }),
|
|
44
|
+
[theme, gap, align, justify, wrap],
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<View style={[layout, style]} testID={testID}>
|
|
49
|
+
{children}
|
|
50
|
+
</View>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
Row.__contract = CONTRACTS.row;
|