melta-app 0.5.2 → 0.6.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/README.md +288 -152
- package/docs/architecture.md +92 -0
- package/eslint-rules/melta.mjs +26 -0
- package/lib/module/primitives/Text.js +18 -5
- package/lib/module/primitives/Text.js.map +1 -1
- package/lib/module/primitives/metric.styles.js +4 -1
- package/lib/module/primitives/metric.styles.js.map +1 -1
- package/lib/module/primitives/text.styles.js +7 -1
- package/lib/module/primitives/text.styles.js.map +1 -1
- package/lib/module/theme/define-theme.js +13 -0
- package/lib/module/theme/define-theme.js.map +1 -1
- package/lib/module/theme/index.js +1 -0
- package/lib/module/theme/index.js.map +1 -1
- package/lib/module/theme/line-height.js +43 -0
- package/lib/module/theme/line-height.js.map +1 -0
- package/lib/module/theme/native-theme.js +7 -6
- package/lib/module/theme/native-theme.js.map +1 -1
- package/lib/typescript/src/primitives/Text.d.ts.map +1 -1
- package/lib/typescript/src/primitives/metric.styles.d.ts.map +1 -1
- package/lib/typescript/src/primitives/text.styles.d.ts.map +1 -1
- package/lib/typescript/src/theme/define-theme.d.ts.map +1 -1
- package/lib/typescript/src/theme/index.d.ts +1 -0
- package/lib/typescript/src/theme/index.d.ts.map +1 -1
- package/lib/typescript/src/theme/line-height.d.ts +34 -0
- package/lib/typescript/src/theme/line-height.d.ts.map +1 -0
- package/lib/typescript/src/theme/native-theme.d.ts.map +1 -1
- package/lib/typescript/src/theme/types.d.ts +9 -0
- package/lib/typescript/src/theme/types.d.ts.map +1 -1
- package/llms.txt +2 -1
- package/package.json +1 -1
- package/src/primitives/Text.tsx +19 -3
- package/src/primitives/metric.styles.ts +8 -1
- package/src/primitives/text.styles.ts +10 -1
- package/src/theme/define-theme.ts +18 -0
- package/src/theme/index.ts +5 -0
- package/src/theme/line-height.ts +44 -0
- package/src/theme/native-theme.ts +7 -6
- package/src/theme/types.ts +9 -0
|
@@ -373,6 +373,24 @@ export function validateTheme(options: ThemeOptions): string[] {
|
|
|
373
373
|
}
|
|
374
374
|
}
|
|
375
375
|
|
|
376
|
+
// minLineHeightRatio は任意欄だが、書くなら実在しうる比率であること
|
|
377
|
+
// (0.9 のような「詰め」を宣言されると clamp が下限の意味を失う。上限は設けない——
|
|
378
|
+
// 行間をいくら広げても字形は欠けないので、広い分には嘘にならない)。
|
|
379
|
+
// missingKeys と同じ方針で **accessor は呼ばない**(値の直読みは消費者の開発用プローブを
|
|
380
|
+
// 発火させ、「defineTheme は accessor を1度も呼ばない」契約を破る)。data property のみ検査する。
|
|
381
|
+
const minRatioDesc =
|
|
382
|
+
options.typography !== null && typeof options.typography === "object"
|
|
383
|
+
? Object.getOwnPropertyDescriptor(options.typography, "minLineHeightRatio")
|
|
384
|
+
: undefined;
|
|
385
|
+
if (minRatioDesc !== undefined && "value" in minRatioDesc && minRatioDesc.value !== undefined) {
|
|
386
|
+
const minRatio: unknown = minRatioDesc.value;
|
|
387
|
+
if (typeof minRatio !== "number" || !Number.isFinite(minRatio) || minRatio < 1) {
|
|
388
|
+
problems.push(
|
|
389
|
+
`${where}: typography.minLineHeightRatio が不正 — ${String(minRatio)}(フォント実測の 1 以上の有限数を宣言する。根拠は theme/line-height.ts)`,
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
376
394
|
const status = options.color?.status;
|
|
377
395
|
if (status !== null && typeof status === "object") {
|
|
378
396
|
for (const kind of STATUS_KINDS) {
|
package/src/theme/index.ts
CHANGED
|
@@ -9,6 +9,11 @@ export { nativeTheme } from "./native-theme";
|
|
|
9
9
|
export { ThemeProvider, useTheme } from "./ThemeProvider";
|
|
10
10
|
export type { ThemeContextValue, ThemeMode } from "./ThemeProvider";
|
|
11
11
|
export { defineTheme } from "./define-theme";
|
|
12
|
+
export {
|
|
13
|
+
DEFAULT_MIN_LINE_HEIGHT_RATIO,
|
|
14
|
+
minLineHeightFor,
|
|
15
|
+
clampLineHeight,
|
|
16
|
+
} from "./line-height";
|
|
12
17
|
/**
|
|
13
18
|
* 以下は theme の解決規則を外から検証・再利用するためのヘルパ。
|
|
14
19
|
* **@experimental — 安定 API ではない。** 挙動・シグネチャ・メッセージは予告なく変わりうる。
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* line-height — 行間の安全下限(フォントの字形を欠かせない最小 lineHeight)。
|
|
3
|
+
*
|
|
4
|
+
* なぜ要るか(2026-08-05 modelog dogfood で実害):
|
|
5
|
+
* RN Android の CustomLineHeightSpan は `leading = lineHeight - (ascent + descent)` を計算し、
|
|
6
|
+
* leading が負になると不足分を行の上下から半分ずつ削って帳尻を合わせる。削られた領域の字形
|
|
7
|
+
* (濁点は行の上端にある)は Text 既定の overflow: hidden で消える——「ギ」が「チ」に見える。
|
|
8
|
+
* web はこの機序を持たないため、web の実描画検査では検出できない(Android 実機のみで発現)。
|
|
9
|
+
*
|
|
10
|
+
* 下限は使用フォントのメトリクス(ascent + descent)に依存するが、melta はフォントを同梱しない
|
|
11
|
+
* (system フォント運用)ので、既定は **Android の日本語 system フォント Noto Sans CJK JP の
|
|
12
|
+
* 実測 1.448**(hhea: (1160 + 288) / 1000。AOSP 版・Google Fonts 版とも同値、2026-08-06 実測)
|
|
13
|
+
* を切り上げた 1.45 とする。iOS(Hiragino 1.50 相当)にはこの clip 機序が無いので基準にしない。
|
|
14
|
+
*
|
|
15
|
+
* フォントを同梱する消費者は、そのフォントの実測比率を theme の
|
|
16
|
+
* `typography.minLineHeightRatio` で宣言する(例: LINE Seed JP = 1.61)。
|
|
17
|
+
* 宣言が既定より小さいラテン専用フォント(例: Inter 1.21)も同じ口で下げられる。
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 既定の最小行間比。Android system 日本語フォント(Noto Sans CJK JP)の実測 1.448 の切り上げ。
|
|
22
|
+
* theme が `typography.minLineHeightRatio` を宣言しない場合にこの値へ倒れる(日本語安全側)。
|
|
23
|
+
*/
|
|
24
|
+
export const DEFAULT_MIN_LINE_HEIGHT_RATIO = 1.45;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* fontSize に対する安全な最小 lineHeight(px)。
|
|
28
|
+
* **切り上げ**であることが要点: 四捨五入だと 32 × 1.45 = 46.4 → 46 で下限を割る。
|
|
29
|
+
*/
|
|
30
|
+
export function minLineHeightFor(fontSize: number, minRatio: number): number {
|
|
31
|
+
return Math.ceil(fontSize * minRatio);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 宣言された lineHeight を安全下限でクランプする。
|
|
36
|
+
* 宣言値が下限以上ならそのまま(意匠の行間はどこまでも広げられる。詰める方向だけを止める)。
|
|
37
|
+
*/
|
|
38
|
+
export function clampLineHeight(
|
|
39
|
+
fontSize: number,
|
|
40
|
+
declaredLineHeight: number,
|
|
41
|
+
minRatio: number,
|
|
42
|
+
): number {
|
|
43
|
+
return Math.max(declaredLineHeight, minLineHeightFor(fontSize, minRatio));
|
|
44
|
+
}
|
|
@@ -81,11 +81,11 @@ export const nativeTheme: NativeTheme = {
|
|
|
81
81
|
"fontSize": {
|
|
82
82
|
"xxs": {
|
|
83
83
|
"fontSize": 10,
|
|
84
|
-
"lineHeight":
|
|
84
|
+
"lineHeight": 15
|
|
85
85
|
},
|
|
86
86
|
"xs": {
|
|
87
87
|
"fontSize": 13,
|
|
88
|
-
"lineHeight":
|
|
88
|
+
"lineHeight": 19
|
|
89
89
|
},
|
|
90
90
|
"sm": {
|
|
91
91
|
"fontSize": 15,
|
|
@@ -101,15 +101,15 @@ export const nativeTheme: NativeTheme = {
|
|
|
101
101
|
},
|
|
102
102
|
"xl": {
|
|
103
103
|
"fontSize": 22,
|
|
104
|
-
"lineHeight":
|
|
104
|
+
"lineHeight": 32
|
|
105
105
|
},
|
|
106
106
|
"2xl": {
|
|
107
107
|
"fontSize": 26,
|
|
108
|
-
"lineHeight":
|
|
108
|
+
"lineHeight": 38
|
|
109
109
|
},
|
|
110
110
|
"3xl": {
|
|
111
111
|
"fontSize": 32,
|
|
112
|
-
"lineHeight":
|
|
112
|
+
"lineHeight": 47
|
|
113
113
|
}
|
|
114
114
|
},
|
|
115
115
|
"fontWeight": {
|
|
@@ -121,7 +121,8 @@ export const nativeTheme: NativeTheme = {
|
|
|
121
121
|
"letterSpacingRatio": {
|
|
122
122
|
"heading": 0.01,
|
|
123
123
|
"body": 0.02
|
|
124
|
-
}
|
|
124
|
+
},
|
|
125
|
+
"minLineHeightRatio": 1.45
|
|
125
126
|
},
|
|
126
127
|
"spacing": {
|
|
127
128
|
"1": 4,
|
package/src/theme/types.ts
CHANGED
|
@@ -91,6 +91,15 @@ export interface ThemeTypography {
|
|
|
91
91
|
* (requirements §4 の「px に換算」からの意図的な乖離。理由はこのコメントの通り)
|
|
92
92
|
*/
|
|
93
93
|
letterSpacingRatio: { heading: number; body: number };
|
|
94
|
+
/**
|
|
95
|
+
* 使用フォントが要求する最小行間比((ascent + descent) / unitsPerEm)。
|
|
96
|
+
* これを下回る lineHeight は RN Android で字形の描画領域を削り、濁点などが欠ける
|
|
97
|
+
* (機序と既定値 1.45 の根拠は theme/line-height.ts のコメント)。
|
|
98
|
+
* style resolver は `clampLineHeight()` でこの比率を下限として適用する。
|
|
99
|
+
* 未宣言は DEFAULT_MIN_LINE_HEIGHT_RATIO(1.45 = Android system 日本語フォント基準)へ倒れる。
|
|
100
|
+
* フォントを同梱する消費者は実測値を宣言する(例: LINE Seed JP = 1.61)。
|
|
101
|
+
*/
|
|
102
|
+
minLineHeightRatio?: number;
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
/**
|