melta-app 0.2.3 → 0.4.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 +2 -2
- package/README.md +39 -0
- package/docs/patterns.md +263 -0
- package/lib/module/components/Radio.js +11 -7
- package/lib/module/components/Radio.js.map +1 -1
- package/lib/module/components/TextField.js +31 -5
- package/lib/module/components/TextField.js.map +1 -1
- package/lib/module/safe-area/index.js +29 -24
- package/lib/module/safe-area/index.js.map +1 -1
- package/lib/module/theme/ThemeProvider.js +45 -6
- package/lib/module/theme/ThemeProvider.js.map +1 -1
- package/lib/module/theme/define-theme.js +360 -0
- package/lib/module/theme/define-theme.js.map +1 -0
- package/lib/module/theme/index.js +2 -0
- package/lib/module/theme/index.js.map +1 -1
- package/lib/typescript/src/components/Radio.d.ts.map +1 -1
- package/lib/typescript/src/components/TextField.d.ts +21 -4
- package/lib/typescript/src/components/TextField.d.ts.map +1 -1
- package/lib/typescript/src/safe-area/index.d.ts +7 -3
- package/lib/typescript/src/safe-area/index.d.ts.map +1 -1
- package/lib/typescript/src/theme/ThemeProvider.d.ts +26 -5
- package/lib/typescript/src/theme/ThemeProvider.d.ts.map +1 -1
- package/lib/typescript/src/theme/define-theme.d.ts +113 -0
- package/lib/typescript/src/theme/define-theme.d.ts.map +1 -0
- package/lib/typescript/src/theme/index.d.ts +3 -0
- package/lib/typescript/src/theme/index.d.ts.map +1 -1
- package/lib/typescript/src/theme/types.d.ts +5 -0
- package/lib/typescript/src/theme/types.d.ts.map +1 -1
- package/llms.txt +62 -0
- package/package.json +5 -2
- package/src/components/Radio.tsx +9 -6
- package/src/components/TextField.tsx +48 -6
- package/src/theme/ThemeProvider.tsx +74 -12
- package/src/theme/define-theme.ts +426 -0
- package/src/theme/index.ts +16 -0
- package/src/theme/types.ts +6 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createContext","useContext","useMemo","useColorScheme","nativeTheme","jsx","_jsx","ThemeContext","ThemeProvider","children","forcedMode","system","mode","
|
|
1
|
+
{"version":3,"names":["createContext","useContext","useMemo","useColorScheme","nativeTheme","defineTheme","isDev","resolveMode","jsx","_jsx","ThemeContext","DEFAULT_THEME","id","reportedViolations","Set","reportViolation","themeId","violation","key","requested","has","add","console","error","colorScheme","resolved","ThemeProvider","children","forcedMode","theme","system","activeTheme","mode","capabilities","value","colors","color","semantic","Error","Provider","useTheme","ctx"],"sourceRoot":"../../../src","sources":["theme/ThemeProvider.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,aAAa,EAAEC,UAAU,EAAEC,OAAO,QAAwB,OAAO;AAC1E,SAASC,cAAc,QAAQ,cAAc;AAC7C,SAASC,WAAW,QAAQ,mBAAgB;AAC5C,SAASC,WAAW,EAAEC,KAAK,EAAEC,WAAW,QAAsF,mBAAgB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAsB/I,MAAMC,YAAY,gBAAGV,aAAa,CAA2B,IAAI,CAAC;;AAElE;AACA,MAAMW,aAAkC,GAAGN,WAAW,CAAC;EAAE,GAAGD,WAAW;EAAEQ,EAAE,EAAE;AAAQ,CAAC,CAAC;;AAEvF;AACA,MAAMC,kBAAkB,GAAG,IAAIC,GAAG,CAAS,CAAC;AAE5C,SAASC,eAAeA,CAACC,OAA2B,EAAEC,SAA6B,EAAQ;EACzF,MAAMC,GAAG,GAAG,GAAGF,OAAO,IAAI,UAAU,IAAIC,SAAS,CAACE,SAAS,EAAE;EAC7D,IAAIN,kBAAkB,CAACO,GAAG,CAACF,GAAG,CAAC,EAAE;EACjCL,kBAAkB,CAACQ,GAAG,CAACH,GAAG,CAAC;EAC3BI,OAAO,CAACC,KAAK,CACX,sBAAsBN,SAAS,CAACE,SAAS,uBAAuB,GAC9D,eAAeF,SAAS,CAACO,WAAW,SAASP,SAAS,CAACQ,QAAQ,UAAU,GACzE,qEACJ,CAAC;AACH;AAoBA,OAAO,SAASC,aAAaA,CAAC;EAAEC,QAAQ;EAAEC,UAAU;EAAEC;AAA0B,CAAC,EAAE;EACjF,MAAMC,MAAM,GAAG3B,cAAc,CAAC,CAAC;EAC/B,MAAM4B,WAAW,GAAGF,KAAK,IAAIlB,aAAa;EAE1C,MAAM;IAAEqB,IAAI;IAAEf;EAAU,CAAC,GAAGV,WAAW,CACrCwB,WAAW,CAACE,YAAY,CAACT,WAAW,EACpCI,UAAU,EACVE,MAAM,KAAK,MAAM,GAAG,MAAM,GAAG,OAC/B,CAAC;EACD,IAAIxB,KAAK,IAAIW,SAAS,EAAEF,eAAe,CAACgB,WAAW,CAACnB,EAAE,EAAEK,SAAS,CAAC;EAElE,MAAMiB,KAAK,GAAGhC,OAAO,CAAoB,MAAM;IAC7C,MAAMiC,MAAM,GAAGJ,WAAW,CAACK,KAAK,CAACC,QAAQ,CAACL,IAAI,CAAC;IAC/C,IAAI,CAACG,MAAM,EAAE;MACX;MACA;MACA,MAAM,IAAIG,KAAK,CACb,iBAAiBP,WAAW,CAACnB,EAAE,IAAI,UAAU,aAAaoB,IAAI,oBAChE,CAAC;IACH;IACA,OAAO;MACL;MACA;MACA;MACA;MACAH,KAAK,EAAEE,WAAqC;MAC5CC,IAAI;MACJG,MAAM;MACNF,YAAY,EAAEF,WAAW,CAACE;IAC5B,CAAC;EACH,CAAC,EAAE,CAACF,WAAW,EAAEC,IAAI,CAAC,CAAC;EAEvB,oBAAOvB,IAAA,CAACC,YAAY,CAAC6B,QAAQ;IAACL,KAAK,EAAEA,KAAM;IAAAP,QAAA,EAAEA;EAAQ,CAAwB,CAAC;AAChF;AAEA,OAAO,SAASa,QAAQA,CAAA,EAAsB;EAC5C,MAAMC,GAAG,GAAGxC,UAAU,CAACS,YAAY,CAAC;EACpC,IAAI,CAAC+B,GAAG,EAAE;IACR,MAAM,IAAIH,KAAK,CAAC,yCAAyC,CAAC;EAC5D;EACA,OAAOG,GAAG;AACZ","ignoreList":[]}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* define-theme — 消費者ブランドの theme を注入するための入口(設計書 Step 2-①)。
|
|
5
|
+
*
|
|
6
|
+
* melta 既定の theme は melta-contracts から codegen した `nativeTheme` だが、消費者が自分の
|
|
7
|
+
* ブランドトークンで塗り替えられる正規の口をここで提供する。`defineTheme()` を通した成果物だけを
|
|
8
|
+
* `<ThemeProvider theme={...}>` が受け取る(Chakra の `$$chakra` と同じ brand 方式。
|
|
9
|
+
* 生オブジェクトの直渡しを型で塞ぎ、validation を必ず1回通すため)。
|
|
10
|
+
*
|
|
11
|
+
* 設計の要点:
|
|
12
|
+
* - **capability は宣言でなく導出する**。「この theme は dark しか持たない」は
|
|
13
|
+
* `color.semantic` のキー集合そのものが語る(Primer の colorSchemes / DTCG Resolver の contexts と同じ流儀)。
|
|
14
|
+
* 別欄で宣言すると「宣言と実体の不一致」という新種の嘘が生まれ、それを警備する検査が要るだけになる。
|
|
15
|
+
* - **嘘の値で埋めない**。単一 colorScheme の theme は存在しない mode を **書かない**。
|
|
16
|
+
* ゼロ埋め・他 mode のコピー・センチネル値はいずれも「その mode が存在する」という嘘をトークンに残す。
|
|
17
|
+
* - **Proxy は使わない**。Hermes は Proxy が使われていなくても全プロパティアクセスに分岐が入る
|
|
18
|
+
* (hermes#33)。存在しない mode の検出は non-enumerable な getter で行う(下記)。
|
|
19
|
+
*
|
|
20
|
+
* 注: accent(primary パレット / text-accent)・elevation・status の light 値は、単一 dark の
|
|
21
|
+
* theme でも現状 **必須のまま**。①の射程は colorScheme 軸だけで、それらの capability 化は
|
|
22
|
+
* 後続(accent 依存の除去)で扱う。
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// dev 判定
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 開発ビルドか。**裸の `__DEV__` を直接書かないこと。**
|
|
31
|
+
*
|
|
32
|
+
* `__DEV__` は Metro のグローバルで、Metro なら prod ビルド時に `false` へ畳み込まれて
|
|
33
|
+
* dev ブロックごと消える。一方 melta は package.json の exports の `import` / `default` 条件で
|
|
34
|
+
* 同じ ESM を非 Metro の web バンドラにも配っており、react-native-web は `__DEV__` を
|
|
35
|
+
* **定義しない**(vendored 側で `process.env.NODE_ENV` にローカル shim している)。
|
|
36
|
+
* そこで `typeof` で存在を確かめ、無い環境では `NODE_ENV === "development"` のときだけ有効にする
|
|
37
|
+
* (判定不能なら dev 機能を**切る**側に倒す = 本番に dev コストを漏らさない)。
|
|
38
|
+
* `process` を識別子として直接参照しないのは、それを書くと tsconfig.build.json(bob build)だけが
|
|
39
|
+
* TS2591 で落ちるため(typecheck は通ってしまうので気づけない)。
|
|
40
|
+
*/
|
|
41
|
+
export const isDev = typeof __DEV__ !== "undefined" ? __DEV__ : globalThis.process?.env?.NODE_ENV === "development";
|
|
42
|
+
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// 型
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
/** theme が持つ配色の能力。`color.semantic` のキー集合から導出される(宣言ではない)。 */
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 解決済みの capability 集合。context 経由で全 component が読める。
|
|
51
|
+
* 後続で accent / elevation の軸が増えるのもこの器(それらはキー集合から導出できないので宣言になる)。
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* `defineTheme()` の入力。`NativeTheme` との差は `color.semantic` が mode ごとに任意な点だけ。
|
|
56
|
+
* 持っていない mode は **書かない**(capability はキー集合から導出される)。
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* `defineTheme()` の成果物。`ThemeProvider` の `theme` prop が受け取れる唯一の形。
|
|
61
|
+
* `$$melta` brand により生オブジェクトの直渡しを型で塞ぐ(= validation を必ず1回通す)。
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/** 解決した mode が theme の能力と食い違ったこと。ThemeProvider は dev で報告し、値は clamp する。 */
|
|
65
|
+
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// キー集合(型と実行時の二重管理を防ぐ: Record<K, true> で網羅性を tsc に検査させる)
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
function keysOf(map) {
|
|
71
|
+
return Object.keys(map);
|
|
72
|
+
}
|
|
73
|
+
const MODES = keysOf({
|
|
74
|
+
light: true,
|
|
75
|
+
dark: true
|
|
76
|
+
});
|
|
77
|
+
const SEMANTIC_KEYS = keysOf({
|
|
78
|
+
"bg-page": true,
|
|
79
|
+
"bg-page-alt": true,
|
|
80
|
+
"bg-surface": true,
|
|
81
|
+
"bg-surface-alt": true,
|
|
82
|
+
"text-heading": true,
|
|
83
|
+
"text-default": true,
|
|
84
|
+
"text-muted": true,
|
|
85
|
+
"border-default": true,
|
|
86
|
+
"border-strong": true,
|
|
87
|
+
"input-bg": true,
|
|
88
|
+
"input-border": true,
|
|
89
|
+
"text-accent": true,
|
|
90
|
+
"text-on-accent": true
|
|
91
|
+
});
|
|
92
|
+
const PRIMARY_KEYS = keysOf({
|
|
93
|
+
"50": true,
|
|
94
|
+
"100": true,
|
|
95
|
+
"200": true,
|
|
96
|
+
"300": true,
|
|
97
|
+
"400": true,
|
|
98
|
+
"500": true,
|
|
99
|
+
"600": true,
|
|
100
|
+
"700": true,
|
|
101
|
+
"800": true,
|
|
102
|
+
"900": true,
|
|
103
|
+
"950": true
|
|
104
|
+
});
|
|
105
|
+
const STATUS_KINDS = keysOf({
|
|
106
|
+
success: true,
|
|
107
|
+
warning: true,
|
|
108
|
+
danger: true
|
|
109
|
+
});
|
|
110
|
+
const STATUS_COLOR_KEYS = keysOf({
|
|
111
|
+
base: true,
|
|
112
|
+
subtleLight: true,
|
|
113
|
+
textLight: true,
|
|
114
|
+
subtleDark: true,
|
|
115
|
+
textDark: true
|
|
116
|
+
});
|
|
117
|
+
const SPACING_KEYS = keysOf({
|
|
118
|
+
"1": true,
|
|
119
|
+
"2": true,
|
|
120
|
+
"3": true,
|
|
121
|
+
"4": true,
|
|
122
|
+
"5": true,
|
|
123
|
+
"6": true,
|
|
124
|
+
"8": true,
|
|
125
|
+
"10": true,
|
|
126
|
+
"12": true,
|
|
127
|
+
"14": true,
|
|
128
|
+
"16": true
|
|
129
|
+
});
|
|
130
|
+
const RADIUS_KEYS = keysOf({
|
|
131
|
+
sm: true,
|
|
132
|
+
md: true,
|
|
133
|
+
lg: true,
|
|
134
|
+
full: true
|
|
135
|
+
});
|
|
136
|
+
const ELEVATION_KEYS = keysOf({
|
|
137
|
+
none: true,
|
|
138
|
+
sm: true,
|
|
139
|
+
md: true,
|
|
140
|
+
overlay: true
|
|
141
|
+
});
|
|
142
|
+
const FONT_SIZE_KEYS = keysOf({
|
|
143
|
+
xxs: true,
|
|
144
|
+
xs: true,
|
|
145
|
+
sm: true,
|
|
146
|
+
base: true,
|
|
147
|
+
lg: true,
|
|
148
|
+
xl: true,
|
|
149
|
+
"2xl": true,
|
|
150
|
+
"3xl": true
|
|
151
|
+
});
|
|
152
|
+
const FONT_WEIGHT_KEYS = keysOf({
|
|
153
|
+
normal: true,
|
|
154
|
+
medium: true,
|
|
155
|
+
semibold: true,
|
|
156
|
+
bold: true
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// capability の導出
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
|
|
163
|
+
/** theme が実際に値を持っている mode(enumerable なキーのみ = dev getter を踏まない)。 */
|
|
164
|
+
export function declaredModes(semantic) {
|
|
165
|
+
return MODES.filter(mode => Object.prototype.hasOwnProperty.call(semantic, mode));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** colorScheme capability を `color.semantic` のキー集合から導出する。 */
|
|
169
|
+
export function deriveColorScheme(semantic) {
|
|
170
|
+
const modes = declaredModes(semantic);
|
|
171
|
+
if (modes.length === 2) return "light-dark";
|
|
172
|
+
if (modes[0] === "dark") return "single-dark";
|
|
173
|
+
if (modes[0] === "light") return "single-light";
|
|
174
|
+
throw new Error("melta: theme.color.semantic に light / dark のどちらも無い。最低1つの mode が要る。");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** capability が実際に描ける mode。 */
|
|
178
|
+
export function supportedModes(colorScheme) {
|
|
179
|
+
if (colorScheme === "single-dark") return ["dark"];
|
|
180
|
+
if (colorScheme === "single-light") return ["light"];
|
|
181
|
+
return ["light", "dark"];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
// mode 解決
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* 表示 mode を解決する(純関数。ThemeProvider はこの結果に従うだけで判定はしない)。
|
|
190
|
+
*
|
|
191
|
+
* - **OS 由来の不一致は無反応で clamp する**。「light テーマを作らない」は消費者の意図的な設計判断で、
|
|
192
|
+
* OS が light なのは環境の事実にすぎない。ここで警告を出すと light 設定のユーザ全員に出てしまう
|
|
193
|
+
* (CSS の `color-scheme` / Expo の `userInterfaceStyle` も黙って clamp する)。
|
|
194
|
+
* - **`forcedMode` との不一致は報告する**。宣言同士の矛盾=呼び出し側の間違いなので violation を返す。
|
|
195
|
+
* ただし throw はしない(clamp して描き続ける)。厳格に落としたいテストや compiler が
|
|
196
|
+
* violation を error に昇格させる側の責務にする。
|
|
197
|
+
*/
|
|
198
|
+
export function resolveMode(colorScheme, forcedMode, systemMode) {
|
|
199
|
+
const supported = supportedModes(colorScheme);
|
|
200
|
+
const requested = forcedMode ?? systemMode;
|
|
201
|
+
if (supported.includes(requested)) return {
|
|
202
|
+
mode: requested
|
|
203
|
+
};
|
|
204
|
+
const resolved = supported[0];
|
|
205
|
+
// OS 由来の clamp は「事故」ではないので violation を立てない。
|
|
206
|
+
if (forcedMode === undefined) return {
|
|
207
|
+
mode: resolved
|
|
208
|
+
};
|
|
209
|
+
return {
|
|
210
|
+
mode: resolved,
|
|
211
|
+
violation: {
|
|
212
|
+
kind: "forced-mode-unsupported",
|
|
213
|
+
requested,
|
|
214
|
+
resolved,
|
|
215
|
+
colorScheme
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ---------------------------------------------------------------------------
|
|
221
|
+
// validation(開発時のみ。純関数なのでテストからも直接呼べる)
|
|
222
|
+
// ---------------------------------------------------------------------------
|
|
223
|
+
|
|
224
|
+
function missingKeys(target, keys) {
|
|
225
|
+
if (target === null || typeof target !== "object") return [...keys].map(String);
|
|
226
|
+
return keys.filter(key => !Object.prototype.hasOwnProperty.call(target, key)).map(String);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* theme の形を検査して問題の一覧を返す(空配列 = 問題なし)。
|
|
231
|
+
*
|
|
232
|
+
* 「宣言した mode の色が欠けている」「as キャストでキーが抜けた」といった、型を通り抜けた欠落を拾う。
|
|
233
|
+
* `defineTheme()` が dev で1回だけ呼ぶ。**render 中に呼ばないこと**(theme-ui は Provider の
|
|
234
|
+
* render body で毎レンダー全色を再帰走査して性能を落とした前例がある)。
|
|
235
|
+
*/
|
|
236
|
+
export function validateTheme(options) {
|
|
237
|
+
const problems = [];
|
|
238
|
+
const where = options.id ? `theme "${options.id}"` : "theme";
|
|
239
|
+
const semantic = options.color?.semantic;
|
|
240
|
+
if (semantic === null || typeof semantic !== "object") {
|
|
241
|
+
problems.push(`${where}: color.semantic が無い`);
|
|
242
|
+
return problems;
|
|
243
|
+
}
|
|
244
|
+
const unknownModes = Object.keys(semantic).filter(key => !MODES.includes(key));
|
|
245
|
+
for (const key of unknownModes) {
|
|
246
|
+
problems.push(`${where}: color.semantic の未知のキー "${key}"(light / dark のみ)`);
|
|
247
|
+
}
|
|
248
|
+
const modes = declaredModes(semantic);
|
|
249
|
+
if (modes.length === 0) {
|
|
250
|
+
problems.push(`${where}: color.semantic に light / dark のどちらも無い`);
|
|
251
|
+
}
|
|
252
|
+
for (const mode of modes) {
|
|
253
|
+
const missing = missingKeys(semantic[mode], SEMANTIC_KEYS);
|
|
254
|
+
if (missing.length > 0) {
|
|
255
|
+
problems.push(`${where}: color.semantic.${mode} に欠けている色 — ${missing.join(", ")}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const groups = [["color.primary", options.color?.primary, PRIMARY_KEYS], ["spacing", options.spacing, SPACING_KEYS], ["radius", options.radius, RADIUS_KEYS], ["elevation", options.elevation, ELEVATION_KEYS], ["typography.fontSize", options.typography?.fontSize, FONT_SIZE_KEYS], ["typography.fontWeight", options.typography?.fontWeight, FONT_WEIGHT_KEYS], ["color.status", options.color?.status, STATUS_KINDS]];
|
|
259
|
+
for (const [label, target, keys] of groups) {
|
|
260
|
+
const missing = missingKeys(target, keys);
|
|
261
|
+
if (missing.length > 0) {
|
|
262
|
+
problems.push(`${where}: ${label} に欠けているキー — ${missing.join(", ")}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const status = options.color?.status;
|
|
266
|
+
if (status !== null && typeof status === "object") {
|
|
267
|
+
for (const kind of STATUS_KINDS) {
|
|
268
|
+
if (!Object.prototype.hasOwnProperty.call(status, kind)) continue;
|
|
269
|
+
const missing = missingKeys(status[kind], STATUS_COLOR_KEYS);
|
|
270
|
+
if (missing.length > 0) {
|
|
271
|
+
problems.push(`${where}: color.status.${kind} に欠けているキー — ${missing.join(", ")}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return problems;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
// defineTheme
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* 持っていない mode に「読んだら落ちる」getter を置く(**dev / production 共通**)。
|
|
284
|
+
*
|
|
285
|
+
* 値は捏造しない(他 mode のコピーもゼロ埋めもしない)。放置して `undefined` にすると
|
|
286
|
+
* 実際に踏んだとき `Cannot read properties of undefined (reading 'bg-page')` としか出ず、
|
|
287
|
+
* どの theme のどの mode の話か分からない。**落ちること自体は getter の有無に関わらず同じ**なので、
|
|
288
|
+
* 原因を名指しするメッセージを本番のクラッシュレポートにも残す方を選ぶ。
|
|
289
|
+
*
|
|
290
|
+
* **non-enumerable にするのが要点**: spread / `Object.keys` / `JSON.stringify` /
|
|
291
|
+
* React DevTools の context 列挙では踏まれない。`theme.color.semantic.light` と
|
|
292
|
+
* 明示的に書いたときだけ落ちる。
|
|
293
|
+
*
|
|
294
|
+
* ホットパス(全 style resolver が引く `semantic[mode]`)にアクセサを混ぜることになるが、
|
|
295
|
+
* getter が付くのは **単一 colorScheme の theme を注入した場合だけ**。既定の light-dark theme
|
|
296
|
+
* には1つも付かないので、既存消費者の実行経路は変わらない。
|
|
297
|
+
*/
|
|
298
|
+
function installMissingModeGuards(semantic, where, colorScheme) {
|
|
299
|
+
for (const mode of MODES) {
|
|
300
|
+
if (Object.prototype.hasOwnProperty.call(semantic, mode)) continue;
|
|
301
|
+
Object.defineProperty(semantic, mode, {
|
|
302
|
+
enumerable: false,
|
|
303
|
+
configurable: true,
|
|
304
|
+
get() {
|
|
305
|
+
throw new Error(`melta: ${where} は colorScheme=${colorScheme} なので color.semantic.${mode} を持たない。` + `現在の mode の色は useTheme().colors(または color.semantic[mode])から取ること。`);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/** dev 限定の再帰 freeze。enumerable なキーだけ辿るので上の guard getter は踏まない。 */
|
|
312
|
+
function deepFreeze(value) {
|
|
313
|
+
if (value === null || typeof value !== "object") return;
|
|
314
|
+
if (Object.isFrozen(value)) return;
|
|
315
|
+
Object.freeze(value);
|
|
316
|
+
for (const key of Object.keys(value)) {
|
|
317
|
+
deepFreeze(value[key]);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* ブランド theme を組み立てる。`ThemeProvider` の `theme` prop に渡せるのはこの戻り値だけ。
|
|
323
|
+
*
|
|
324
|
+
* **module スコープで1回だけ呼ぶこと**(render の中で呼ぶと毎レンダー新しい参照になり、
|
|
325
|
+
* context の consumer が全部再レンダーする)。styled-components / Emotion が docs で
|
|
326
|
+
* 同じことを求めているのと同じ理由。
|
|
327
|
+
*
|
|
328
|
+
* dev では validateTheme を1回通し、問題があれば throw する(構造が壊れた theme は
|
|
329
|
+
* 後段で必ず事故になるので早く落とす)。production では検査ごと省く。
|
|
330
|
+
*/
|
|
331
|
+
export function defineTheme(options) {
|
|
332
|
+
if (isDev) {
|
|
333
|
+
const problems = validateTheme(options);
|
|
334
|
+
if (problems.length > 0) {
|
|
335
|
+
throw new Error(`melta: theme の形が不正。\n- ${problems.join("\n- ")}`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
const semantic = {
|
|
339
|
+
...options.color.semantic
|
|
340
|
+
};
|
|
341
|
+
const colorScheme = deriveColorScheme(semantic);
|
|
342
|
+
const theme = {
|
|
343
|
+
...options,
|
|
344
|
+
color: {
|
|
345
|
+
...options.color,
|
|
346
|
+
semantic
|
|
347
|
+
},
|
|
348
|
+
capabilities: {
|
|
349
|
+
colorScheme
|
|
350
|
+
},
|
|
351
|
+
$$melta: true
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// guard は本番でも置く(値は捏造せず、踏んだときのメッセージだけ良くする)。
|
|
355
|
+
// freeze より先に置くこと(freeze 後は defineProperty できない)。
|
|
356
|
+
installMissingModeGuards(semantic, options.id ? `theme "${options.id}"` : "theme", colorScheme);
|
|
357
|
+
if (isDev) deepFreeze(theme);
|
|
358
|
+
return theme;
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=define-theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["isDev","__DEV__","globalThis","process","env","NODE_ENV","keysOf","map","Object","keys","MODES","light","dark","SEMANTIC_KEYS","PRIMARY_KEYS","STATUS_KINDS","success","warning","danger","STATUS_COLOR_KEYS","base","subtleLight","textLight","subtleDark","textDark","SPACING_KEYS","RADIUS_KEYS","sm","md","lg","full","ELEVATION_KEYS","none","overlay","FONT_SIZE_KEYS","xxs","xs","xl","FONT_WEIGHT_KEYS","normal","medium","semibold","bold","declaredModes","semantic","filter","mode","prototype","hasOwnProperty","call","deriveColorScheme","modes","length","Error","supportedModes","colorScheme","resolveMode","forcedMode","systemMode","supported","requested","includes","resolved","undefined","violation","kind","missingKeys","target","String","key","validateTheme","options","problems","where","id","color","push","unknownModes","missing","join","groups","primary","spacing","radius","elevation","typography","fontSize","fontWeight","status","label","installMissingModeGuards","defineProperty","enumerable","configurable","get","deepFreeze","value","isFrozen","freeze","defineTheme","theme","capabilities","$$melta"],"sourceRoot":"../../../src","sources":["theme/define-theme.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAgBA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,KAAc,GACzB,OAAOC,OAAO,KAAK,WAAW,GAC1BA,OAAO,GACNC,UAAU,CAAmDC,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KACpF,aAAa;;AAEnB;AACA;AACA;;AAEA;;AAGA;AACA;AACA;AACA;;AAKA;AACA;AACA;AACA;;AAUA;AACA;AACA;AACA;;AAMA;;AAUA;AACA;AACA;;AAEA,SAASC,MAAMA,CAAmBC,GAAM,EAAe;EACrD,OAAOC,MAAM,CAACC,IAAI,CAACF,GAAG,CAAC;AACzB;AAEA,MAAMG,KAAK,GAAGJ,MAAM,CAA0B;EAAEK,KAAK,EAAE,IAAI;EAAEC,IAAI,EAAE;AAAK,CAAC,CAAC;AAE1E,MAAMC,aAAa,GAAGP,MAAM,CAAqC;EAC/D,SAAS,EAAE,IAAI;EACf,aAAa,EAAE,IAAI;EACnB,YAAY,EAAE,IAAI;EAClB,gBAAgB,EAAE,IAAI;EACtB,cAAc,EAAE,IAAI;EACpB,cAAc,EAAE,IAAI;EACpB,YAAY,EAAE,IAAI;EAClB,gBAAgB,EAAE,IAAI;EACtB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,IAAI;EAChB,cAAc,EAAE,IAAI;EACpB,aAAa,EAAE,IAAI;EACnB,gBAAgB,EAAE;AACpB,CAAC,CAAC;AAEF,MAAMQ,YAAY,GAAGR,MAAM,CAA6B;EACtD,IAAI,EAAE,IAAI;EACV,KAAK,EAAE,IAAI;EACX,KAAK,EAAE,IAAI;EACX,KAAK,EAAE,IAAI;EACX,KAAK,EAAE,IAAI;EACX,KAAK,EAAE,IAAI;EACX,KAAK,EAAE,IAAI;EACX,KAAK,EAAE,IAAI;EACX,KAAK,EAAE,IAAI;EACX,KAAK,EAAE,IAAI;EACX,KAAK,EAAE;AACT,CAAC,CAAC;AAEF,MAAMS,YAAY,GAAGT,MAAM,CAA2C;EACpEU,OAAO,EAAE,IAAI;EACbC,OAAO,EAAE,IAAI;EACbC,MAAM,EAAE;AACV,CAAC,CAAC;AAEF,MAAMC,iBAAiB,GAAGb,MAAM,CAAmC;EACjEc,IAAI,EAAE,IAAI;EACVC,WAAW,EAAE,IAAI;EACjBC,SAAS,EAAE,IAAI;EACfC,UAAU,EAAE,IAAI;EAChBC,QAAQ,EAAE;AACZ,CAAC,CAAC;AAEF,MAAMC,YAAY,GAAGnB,MAAM,CAA2B;EACpD,GAAG,EAAE,IAAI;EACT,GAAG,EAAE,IAAI;EACT,GAAG,EAAE,IAAI;EACT,GAAG,EAAE,IAAI;EACT,GAAG,EAAE,IAAI;EACT,GAAG,EAAE,IAAI;EACT,GAAG,EAAE,IAAI;EACT,IAAI,EAAE,IAAI;EACV,IAAI,EAAE,IAAI;EACV,IAAI,EAAE,IAAI;EACV,IAAI,EAAE;AACR,CAAC,CAAC;AAEF,MAAMoB,WAAW,GAAGpB,MAAM,CAA0B;EAClDqB,EAAE,EAAE,IAAI;EACRC,EAAE,EAAE,IAAI;EACRC,EAAE,EAAE,IAAI;EACRC,IAAI,EAAE;AACR,CAAC,CAAC;AAEF,MAAMC,cAAc,GAAGzB,MAAM,CAA6B;EACxD0B,IAAI,EAAE,IAAI;EACVL,EAAE,EAAE,IAAI;EACRC,EAAE,EAAE,IAAI;EACRK,OAAO,EAAE;AACX,CAAC,CAAC;AAEF,MAAMC,cAAc,GAAG5B,MAAM,CAA4B;EACvD6B,GAAG,EAAE,IAAI;EACTC,EAAE,EAAE,IAAI;EACRT,EAAE,EAAE,IAAI;EACRP,IAAI,EAAE,IAAI;EACVS,EAAE,EAAE,IAAI;EACRQ,EAAE,EAAE,IAAI;EACR,KAAK,EAAE,IAAI;EACX,KAAK,EAAE;AACT,CAAC,CAAC;AAEF,MAAMC,gBAAgB,GAAGhC,MAAM,CAA8B;EAC3DiC,MAAM,EAAE,IAAI;EACZC,MAAM,EAAE,IAAI;EACZC,QAAQ,EAAE,IAAI;EACdC,IAAI,EAAE;AACR,CAAC,CAAC;;AAEF;AACA;AACA;;AAEA;AACA,OAAO,SAASC,aAAaA,CAACC,QAAoD,EAAe;EAC/F,OAAOlC,KAAK,CAACmC,MAAM,CAAEC,IAAI,IAAKtC,MAAM,CAACuC,SAAS,CAACC,cAAc,CAACC,IAAI,CAACL,QAAQ,EAAEE,IAAI,CAAC,CAAC;AACrF;;AAEA;AACA,OAAO,SAASI,iBAAiBA,CAC/BN,QAAoD,EAC7B;EACvB,MAAMO,KAAK,GAAGR,aAAa,CAACC,QAAQ,CAAC;EACrC,IAAIO,KAAK,CAACC,MAAM,KAAK,CAAC,EAAE,OAAO,YAAY;EAC3C,IAAID,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,OAAO,aAAa;EAC7C,IAAIA,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,OAAO,cAAc;EAC/C,MAAM,IAAIE,KAAK,CACb,oEACF,CAAC;AACH;;AAEA;AACA,OAAO,SAASC,cAAcA,CAACC,WAAkC,EAAe;EAC9E,IAAIA,WAAW,KAAK,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC;EAClD,IAAIA,WAAW,KAAK,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC;EACpD,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC;AAC1B;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CACzBD,WAAkC,EAClCE,UAAiC,EACjCC,UAAqB,EACgC;EACrD,MAAMC,SAAS,GAAGL,cAAc,CAACC,WAAW,CAAC;EAC7C,MAAMK,SAAS,GAAGH,UAAU,IAAIC,UAAU;EAC1C,IAAIC,SAAS,CAACE,QAAQ,CAACD,SAAS,CAAC,EAAE,OAAO;IAAEd,IAAI,EAAEc;EAAU,CAAC;EAE7D,MAAME,QAAQ,GAAGH,SAAS,CAAC,CAAC,CAAC;EAC7B;EACA,IAAIF,UAAU,KAAKM,SAAS,EAAE,OAAO;IAAEjB,IAAI,EAAEgB;EAAS,CAAC;EACvD,OAAO;IACLhB,IAAI,EAAEgB,QAAQ;IACdE,SAAS,EAAE;MAAEC,IAAI,EAAE,yBAAyB;MAAEL,SAAS;MAAEE,QAAQ;MAAEP;IAAY;EACjF,CAAC;AACH;;AAEA;AACA;AACA;;AAEA,SAASW,WAAWA,CAACC,MAA0B,EAAE1D,IAAkC,EAAY;EAC7F,IAAI0D,MAAM,KAAK,IAAI,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE,OAAO,CAAC,GAAG1D,IAAI,CAAC,CAACF,GAAG,CAAC6D,MAAM,CAAC;EAC/E,OAAO3D,IAAI,CAACoC,MAAM,CAAEwB,GAAG,IAAK,CAAC7D,MAAM,CAACuC,SAAS,CAACC,cAAc,CAACC,IAAI,CAACkB,MAAM,EAAEE,GAAG,CAAC,CAAC,CAAC9D,GAAG,CAAC6D,MAAM,CAAC;AAC7F;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,aAAaA,CAACC,OAAqB,EAAY;EAC7D,MAAMC,QAAkB,GAAG,EAAE;EAC7B,MAAMC,KAAK,GAAGF,OAAO,CAACG,EAAE,GAAG,UAAUH,OAAO,CAACG,EAAE,GAAG,GAAG,OAAO;EAE5D,MAAM9B,QAAQ,GAAG2B,OAAO,CAACI,KAAK,EAAE/B,QAAQ;EACxC,IAAIA,QAAQ,KAAK,IAAI,IAAI,OAAOA,QAAQ,KAAK,QAAQ,EAAE;IACrD4B,QAAQ,CAACI,IAAI,CAAC,GAAGH,KAAK,sBAAsB,CAAC;IAC7C,OAAOD,QAAQ;EACjB;EAEA,MAAMK,YAAY,GAAGrE,MAAM,CAACC,IAAI,CAACmC,QAAQ,CAAC,CAACC,MAAM,CAC9CwB,GAAG,IAAK,CAAE3D,KAAK,CAAcmD,QAAQ,CAACQ,GAAG,CAC5C,CAAC;EACD,KAAK,MAAMA,GAAG,IAAIQ,YAAY,EAAE;IAC9BL,QAAQ,CAACI,IAAI,CAAC,GAAGH,KAAK,4BAA4BJ,GAAG,oBAAoB,CAAC;EAC5E;EAEA,MAAMlB,KAAK,GAAGR,aAAa,CAACC,QAAQ,CAAC;EACrC,IAAIO,KAAK,CAACC,MAAM,KAAK,CAAC,EAAE;IACtBoB,QAAQ,CAACI,IAAI,CAAC,GAAGH,KAAK,yCAAyC,CAAC;EAClE;EACA,KAAK,MAAM3B,IAAI,IAAIK,KAAK,EAAE;IACxB,MAAM2B,OAAO,GAAGZ,WAAW,CAACtB,QAAQ,CAACE,IAAI,CAAC,EAAEjC,aAAa,CAAC;IAC1D,IAAIiE,OAAO,CAAC1B,MAAM,GAAG,CAAC,EAAE;MACtBoB,QAAQ,CAACI,IAAI,CAAC,GAAGH,KAAK,oBAAoB3B,IAAI,cAAcgC,OAAO,CAACC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACnF;EACF;EAEA,MAAMC,MAAyD,GAAG,CAChE,CAAC,eAAe,EAAET,OAAO,CAACI,KAAK,EAAEM,OAAO,EAAEnE,YAAY,CAAC,EACvD,CAAC,SAAS,EAAEyD,OAAO,CAACW,OAAO,EAAEzD,YAAY,CAAC,EAC1C,CAAC,QAAQ,EAAE8C,OAAO,CAACY,MAAM,EAAEzD,WAAW,CAAC,EACvC,CAAC,WAAW,EAAE6C,OAAO,CAACa,SAAS,EAAErD,cAAc,CAAC,EAChD,CAAC,qBAAqB,EAAEwC,OAAO,CAACc,UAAU,EAAEC,QAAQ,EAAEpD,cAAc,CAAC,EACrE,CAAC,uBAAuB,EAAEqC,OAAO,CAACc,UAAU,EAAEE,UAAU,EAAEjD,gBAAgB,CAAC,EAC3E,CAAC,cAAc,EAAEiC,OAAO,CAACI,KAAK,EAAEa,MAAM,EAAEzE,YAAY,CAAC,CACtD;EACD,KAAK,MAAM,CAAC0E,KAAK,EAAEtB,MAAM,EAAE1D,IAAI,CAAC,IAAIuE,MAAM,EAAE;IAC1C,MAAMF,OAAO,GAAGZ,WAAW,CAACC,MAAM,EAAE1D,IAAI,CAAC;IACzC,IAAIqE,OAAO,CAAC1B,MAAM,GAAG,CAAC,EAAE;MACtBoB,QAAQ,CAACI,IAAI,CAAC,GAAGH,KAAK,KAAKgB,KAAK,eAAeX,OAAO,CAACC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACtE;EACF;EAEA,MAAMS,MAAM,GAAGjB,OAAO,CAACI,KAAK,EAAEa,MAAM;EACpC,IAAIA,MAAM,KAAK,IAAI,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE;IACjD,KAAK,MAAMvB,IAAI,IAAIlD,YAAY,EAAE;MAC/B,IAAI,CAACP,MAAM,CAACuC,SAAS,CAACC,cAAc,CAACC,IAAI,CAACuC,MAAM,EAAEvB,IAAI,CAAC,EAAE;MACzD,MAAMa,OAAO,GAAGZ,WAAW,CAACsB,MAAM,CAACvB,IAAI,CAAC,EAAE9C,iBAAiB,CAAC;MAC5D,IAAI2D,OAAO,CAAC1B,MAAM,GAAG,CAAC,EAAE;QACtBoB,QAAQ,CAACI,IAAI,CAAC,GAAGH,KAAK,kBAAkBR,IAAI,eAAea,OAAO,CAACC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;MAClF;IACF;EACF;EAEA,OAAOP,QAAQ;AACjB;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASkB,wBAAwBA,CAC/B9C,QAAoD,EACpD6B,KAAa,EACblB,WAAkC,EAC5B;EACN,KAAK,MAAMT,IAAI,IAAIpC,KAAK,EAAE;IACxB,IAAIF,MAAM,CAACuC,SAAS,CAACC,cAAc,CAACC,IAAI,CAACL,QAAQ,EAAEE,IAAI,CAAC,EAAE;IAC1DtC,MAAM,CAACmF,cAAc,CAAC/C,QAAQ,EAAEE,IAAI,EAAE;MACpC8C,UAAU,EAAE,KAAK;MACjBC,YAAY,EAAE,IAAI;MAClBC,GAAGA,CAAA,EAAU;QACX,MAAM,IAAIzC,KAAK,CACb,UAAUoB,KAAK,kBAAkBlB,WAAW,uBAAuBT,IAAI,SAAS,GAC9E,iEACJ,CAAC;MACH;IACF,CAAC,CAAC;EACJ;AACF;;AAEA;AACA,SAASiD,UAAUA,CAACC,KAAc,EAAQ;EACxC,IAAIA,KAAK,KAAK,IAAI,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE;EACjD,IAAIxF,MAAM,CAACyF,QAAQ,CAACD,KAAK,CAAC,EAAE;EAC5BxF,MAAM,CAAC0F,MAAM,CAACF,KAAK,CAAC;EACpB,KAAK,MAAM3B,GAAG,IAAI7D,MAAM,CAACC,IAAI,CAACuF,KAAK,CAAC,EAAE;IACpCD,UAAU,CAAEC,KAAK,CAA6B3B,GAAG,CAAC,CAAC;EACrD;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAAS8B,WAAWA,CAAC5B,OAAqB,EAAuB;EACtE,IAAIvE,KAAK,EAAE;IACT,MAAMwE,QAAQ,GAAGF,aAAa,CAACC,OAAO,CAAC;IACvC,IAAIC,QAAQ,CAACpB,MAAM,GAAG,CAAC,EAAE;MACvB,MAAM,IAAIC,KAAK,CAAC,0BAA0BmB,QAAQ,CAACO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACpE;EACF;EAEA,MAAMnC,QAAoD,GAAG;IAAE,GAAG2B,OAAO,CAACI,KAAK,CAAC/B;EAAS,CAAC;EAC1F,MAAMW,WAAW,GAAGL,iBAAiB,CAACN,QAAQ,CAAC;EAE/C,MAAMwD,KAA0B,GAAG;IACjC,GAAG7B,OAAO;IACVI,KAAK,EAAE;MAAE,GAAGJ,OAAO,CAACI,KAAK;MAAE/B;IAAS,CAAC;IACrCyD,YAAY,EAAE;MAAE9C;IAAY,CAAC;IAC7B+C,OAAO,EAAE;EACX,CAAC;;EAED;EACA;EACAZ,wBAAwB,CAAC9C,QAAQ,EAAE2B,OAAO,CAACG,EAAE,GAAG,UAAUH,OAAO,CAACG,EAAE,GAAG,GAAG,OAAO,EAAEnB,WAAW,CAAC;EAE/F,IAAIvD,KAAK,EAAE+F,UAAU,CAACK,KAAK,CAAC;EAE5B,OAAOA,KAAK;AACd","ignoreList":[]}
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* melta-app theme エントリ。
|
|
5
5
|
* 型は types.ts、値は native-theme.ts(melta-contracts から自動生成)。
|
|
6
|
+
* 消費者ブランドの theme を注入する口は define-theme.ts(`defineTheme`)。
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
export * from "./types.js";
|
|
9
10
|
export { nativeTheme } from "./native-theme.js";
|
|
10
11
|
export { ThemeProvider, useTheme } from "./ThemeProvider.js";
|
|
12
|
+
export { defineTheme, validateTheme, resolveMode, supportedModes, deriveColorScheme, declaredModes } from "./define-theme.js";
|
|
11
13
|
/**
|
|
12
14
|
* letterSpacingRatio(em 相当の比率)を、適用先の fontSize から RN の letterSpacing(pt) に解決する。
|
|
13
15
|
* 例: resolveLetterSpacing(18, theme.typography.letterSpacingRatio.body)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["nativeTheme","ThemeProvider","useTheme","resolveLetterSpacing","fontSize","ratio"],"sourceRoot":"../../../src","sources":["theme/index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;;AAEA,cAAc,YAAS;AACvB,SAASA,WAAW,QAAQ,mBAAgB;AAC5C,SAASC,aAAa,EAAEC,QAAQ,QAAQ,oBAAiB;
|
|
1
|
+
{"version":3,"names":["nativeTheme","ThemeProvider","useTheme","defineTheme","validateTheme","resolveMode","supportedModes","deriveColorScheme","declaredModes","resolveLetterSpacing","fontSize","ratio"],"sourceRoot":"../../../src","sources":["theme/index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;;AAEA,cAAc,YAAS;AACvB,SAASA,WAAW,QAAQ,mBAAgB;AAC5C,SAASC,aAAa,EAAEC,QAAQ,QAAQ,oBAAiB;AAEzD,SACEC,WAAW,EACXC,aAAa,EACbC,WAAW,EACXC,cAAc,EACdC,iBAAiB,EACjBC,aAAa,QACR,mBAAgB;AASvB;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAACC,QAAgB,EAAEC,KAAa,EAAU;EAC5E,OAAOD,QAAQ,GAAGC,KAAK;AACzB","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../../src/components/Radio.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,OAAO,EACP,KAAK,EACL,QAAQ,EACR,OAAoB,EACpB,KAAK,EACL,QAAgB,EAChB,MAAM,GACP,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../../src/components/Radio.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,OAAO,EACP,KAAK,EACL,QAAQ,EACR,OAAoB,EACpB,KAAK,EACL,QAAgB,EAChB,MAAM,GACP,EAAE,UAAU,2CAsFZ;yBA/Fe,KAAK"}
|
|
@@ -5,13 +5,20 @@
|
|
|
5
5
|
* - variant は検証状態(default/error/success)。disabled=true で variant を "disabled" に上書きし、
|
|
6
6
|
* editable=false + accessibilityState.disabled を併せて適用する(recipe description の規約)。
|
|
7
7
|
* - error 時は errorText を必ずテキストで表示する(FORM_NO_COLOR_ONLY_ERROR = 色だけで伝えない)。
|
|
8
|
-
* RN には aria-describedby 相当が無いため、
|
|
8
|
+
* RN には aria-describedby 相当が無いため、(a) errorText を input の accessibilityLabel に合成
|
|
9
|
+
* (再フォーカス時に読み上げ)、(b) errorText 側に accessibilityLiveRegion="polite"(Android は
|
|
10
|
+
* 出現時に通知。iOS の即時通知が要る画面は submit 時に announceForAccessibility を併用する —
|
|
11
|
+
* docs/patterns.md 参照)。
|
|
9
12
|
* - focus は内部 state(onFocus/onBlur)で recipe states.focus の inputStyle 差分
|
|
10
|
-
* (borderColor=primary.500)を重ねる。disabled 時は focus
|
|
13
|
+
* (borderColor=primary.500)を重ねる。disabled 時は focus スタイルを付けない。
|
|
14
|
+
* 外部の onFocus/onBlur は RN の event ごと常に透過する(内部の視覚 state と分離)。
|
|
11
15
|
* - 色・寸法の決定は pure resolver(textfield.styles.ts)に分離。
|
|
12
16
|
* recipes/app/textfield.recipe.json との機械照合は scripts/lib/textfield-conformance.test.ts が行う。
|
|
17
|
+
* - RN TextInput へ透過するのは入力メソッド系 props(keyboardType / autoCapitalize / autoCorrect /
|
|
18
|
+
* maxLength / returnKeyType / onSubmitEditing / onBlur / onFocus)のみ。style 系 props は
|
|
19
|
+
* 透過しない(token 純度維持)。
|
|
13
20
|
*/
|
|
14
|
-
import { Platform, type StyleProp, type TextStyle, type ViewStyle } from "react-native";
|
|
21
|
+
import { Platform, type KeyboardTypeOptions, type ReturnKeyTypeOptions, type TextInputProps, type StyleProp, type TextStyle, type ViewStyle } from "react-native";
|
|
15
22
|
import { type TextFieldSize } from "./textfield.styles";
|
|
16
23
|
/**
|
|
17
24
|
* Android の EditText は固定 height と組み合わさると既定の縦 padding で文字が
|
|
@@ -42,10 +49,20 @@ interface TextFieldProps {
|
|
|
42
49
|
helperText?: string;
|
|
43
50
|
/** variant="error" 時に表示するエラーメッセージ(色だけでなくテキストで伝える)。 */
|
|
44
51
|
errorText?: string;
|
|
52
|
+
/** キーボード種別(RN TextInput へ透過)。 */
|
|
53
|
+
keyboardType?: KeyboardTypeOptions;
|
|
54
|
+
autoCapitalize?: "none" | "sentences" | "words" | "characters";
|
|
55
|
+
autoCorrect?: boolean;
|
|
56
|
+
maxLength?: number;
|
|
57
|
+
returnKeyType?: ReturnKeyTypeOptions;
|
|
58
|
+
onSubmitEditing?: TextInputProps["onSubmitEditing"];
|
|
59
|
+
/** blur 時コールバック(blur 検証用)。RN の event ごと透過し、内部の focus スタイル制御と分離。 */
|
|
60
|
+
onBlur?: TextInputProps["onBlur"];
|
|
61
|
+
onFocus?: TextInputProps["onFocus"];
|
|
45
62
|
style?: StyleProp<ViewStyle>;
|
|
46
63
|
testID?: string;
|
|
47
64
|
}
|
|
48
|
-
export declare function TextField({ label, value, onChangeText, placeholder, variant, disabled, size, helperText, errorText, style, testID, }: TextFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
65
|
+
export declare function TextField({ label, value, onChangeText, placeholder, variant, disabled, size, helperText, errorText, keyboardType, autoCapitalize, autoCorrect, maxLength, returnKeyType, onSubmitEditing, onBlur, onFocus, style, testID, }: TextFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
49
66
|
export declare namespace TextField {
|
|
50
67
|
var __contract: {
|
|
51
68
|
readonly id: "textfield";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextField.d.ts","sourceRoot":"","sources":["../../../../src/components/TextField.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"TextField.d.ts","sourceRoot":"","sources":["../../../../src/components/TextField.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EACL,QAAQ,EAIR,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAGtB,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;GAWG;AAEH,sEAAsE;AACtE,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,OAAO,QAAQ,CAAC,EAAE,GAAG,SAAS,CAMzE;AAKD,UAAU,cAAc;IACtB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAC1C,uFAAuF;IACvF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,CAAC;IAC/D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IACpD,mEAAmE;IACnE,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,YAAY,EACZ,WAAW,EACX,OAAmB,EACnB,QAAgB,EAChB,IAAe,EACf,UAAU,EACV,SAAS,EACT,YAAY,EACZ,cAAc,EACd,WAAW,EACX,SAAS,EACT,aAAa,EACb,eAAe,EACf,MAAM,EACN,OAAO,EACP,KAAK,EACL,MAAM,GACP,EAAE,cAAc,2CAmDhB;yBAvEe,SAAS"}
|
|
@@ -15,9 +15,13 @@
|
|
|
15
15
|
* Provider の context 値を render 中に同期参照して padding を付けるため、native
|
|
16
16
|
* SafeAreaView の layout/state 更新を待たず、初回 render から inset が反映される。
|
|
17
17
|
*
|
|
18
|
-
* ⚠️ 前提: アプリの root に SafeAreaProvider
|
|
19
|
-
*
|
|
20
|
-
* Provider が設置済みのことが多い。
|
|
18
|
+
* ⚠️ 前提: アプリの root に SafeAreaProvider が必要(無いと useSafeAreaInsets が throw
|
|
19
|
+
* する)。初回 render から正しい inset を使うには Provider に initialMetrics も渡す。
|
|
20
|
+
* React Navigation / Expo Router 利用時は Provider が設置済みのことが多い。
|
|
21
|
+
*
|
|
22
|
+
* ⚠️ 公開契約: safe-area と合成する padding は数値のみサポート。"5%" 等の非数値は
|
|
23
|
+
* 基底値として扱えず、対象 edge の padding は inset 値に置き換わる(RNSAC native も
|
|
24
|
+
* percentage padding 未サポートのため、より弱い保証を契約化はしない)。
|
|
21
25
|
*/
|
|
22
26
|
import { type Edge } from "react-native-safe-area-context";
|
|
23
27
|
/** enableSafeAreaContext() の設定。edges 省略時は従来相当の全 edge。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/safe-area/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/safe-area/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,EAEL,KAAK,IAAI,EAEV,MAAM,gCAAgC,CAAC;AASxC,yDAAyD;AACzD,MAAM,WAAW,4BAA4B;IAC3C,mDAAmD;IACnD,KAAK,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;CACzB;AAyDD,6DAA6D;AAC7D,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,4BAAiC,GAAG,IAAI,CAEtF"}
|
|
@@ -6,27 +6,48 @@
|
|
|
6
6
|
* useColorScheme() を Provider 内で1回だけ読む(RN コア、追加依存なし)。
|
|
7
7
|
*
|
|
8
8
|
* context value は useMemo 必須(§3): 毎レンダで新オブジェクトを配ると全 consumer が再レンダする。
|
|
9
|
+
*
|
|
10
|
+
* theme 注入(Step 2-①): `theme` を渡すと消費者ブランドの theme で塗り替わる。未指定なら
|
|
11
|
+
* 従来どおり codegen 済みの `nativeTheme`(=既存消費者に破壊的変更なし)。渡せるのは
|
|
12
|
+
* `defineTheme()` の戻り値だけ(define-theme.ts 参照)。
|
|
9
13
|
*/
|
|
10
14
|
import { type ReactNode } from "react";
|
|
11
|
-
import type
|
|
12
|
-
|
|
15
|
+
import { type ResolvedCapabilities, type ResolvedNativeTheme } from "./define-theme";
|
|
16
|
+
import type { NativeTheme, SemanticColors, ThemeMode } from "./types";
|
|
17
|
+
export type { ThemeMode };
|
|
13
18
|
export interface ThemeContextValue {
|
|
14
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* 正規化済み theme 全体(色以外の形状トークンもここから取る)。
|
|
21
|
+
*
|
|
22
|
+
* 注: 単一 colorScheme の theme を注入した場合、`color.semantic` は**宣言された mode しか持たない**
|
|
23
|
+
* (型は両方あるように見える)。持たない側を直接読むと原因を名指しするエラーで落ちる。
|
|
24
|
+
* 現在 mode の色は `colors` を使うこと。
|
|
25
|
+
*/
|
|
15
26
|
theme: NativeTheme;
|
|
16
27
|
/** 現在の表示モード。 */
|
|
17
28
|
mode: ThemeMode;
|
|
18
29
|
/** 現在 mode の semantic 色(= theme.color.semantic[mode])。最頻アクセスなので展開済みで配る。 */
|
|
19
30
|
colors: SemanticColors;
|
|
31
|
+
/** theme が持つ能力(`color.semantic` のキー集合などから導出済み)。 */
|
|
32
|
+
capabilities: ResolvedCapabilities;
|
|
20
33
|
}
|
|
21
34
|
interface ThemeProviderProps {
|
|
22
35
|
children: ReactNode;
|
|
23
36
|
/**
|
|
24
37
|
* 明示モード。指定時は OS の colorScheme を無視して固定する。
|
|
25
38
|
* カタログの light/dark トグル(§6)や、特定画面の固定表示に使う。
|
|
39
|
+
*
|
|
40
|
+
* theme が対応していない mode を渡した場合は theme 側の mode に clamp する(描画は止めない)。
|
|
41
|
+
* dev ではその矛盾を console.error で1回だけ報告する。
|
|
26
42
|
*/
|
|
27
43
|
forcedMode?: ThemeMode;
|
|
44
|
+
/**
|
|
45
|
+
* 消費者ブランドの theme。未指定なら melta 既定(`nativeTheme`)。
|
|
46
|
+
* `defineTheme()` の戻り値を **module スコープで保持したもの**を渡すこと
|
|
47
|
+
* (render 中に組み立てると毎レンダー参照が変わり、全 consumer が再レンダする)。
|
|
48
|
+
*/
|
|
49
|
+
theme?: ResolvedNativeTheme;
|
|
28
50
|
}
|
|
29
|
-
export declare function ThemeProvider({ children, forcedMode }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
export declare function ThemeProvider({ children, forcedMode, theme }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
30
52
|
export declare function useTheme(): ThemeContextValue;
|
|
31
|
-
export {};
|
|
32
53
|
//# sourceMappingURL=ThemeProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/ThemeProvider.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/ThemeProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG3E,OAAO,EAAmC,KAAK,oBAAoB,EAAE,KAAK,mBAAmB,EAA2B,MAAM,gBAAgB,CAAC;AAC/I,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEtE,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,KAAK,EAAE,WAAW,CAAC;IACnB,gBAAgB;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,2EAA2E;IAC3E,MAAM,EAAE,cAAc,CAAC;IACvB,mDAAmD;IACnD,YAAY,EAAE,oBAAoB,CAAC;CACpC;AAqBD,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;OAIG;IACH,KAAK,CAAC,EAAE,mBAAmB,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,kBAAkB,2CAiChF;AAED,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C"}
|