@multiplatform.one/theme 7.65.1 → 7.66.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/package.json +5 -5
- package/src/menuRow.spec.ts +7 -1
- package/src/menuRow.ts +10 -0
- package/src/theme/defaults/fonts.ts +49 -9
- package/src/theme/monoFamily.native.spec.ts +187 -0
- package/src/theme/nativeFontFamily.native.ts +14 -0
- package/src/theme/nativeFontFamily.ts +6 -0
- package/src/theme/nativeMonoFamily.ts +46 -0
- package/types/menuRow.d.ts +9 -0
- package/types/menuRow.d.ts.map +1 -1
- package/types/theme/defaults/fonts.d.ts.map +1 -1
- package/types/theme/nativeFontFamily.d.ts +4 -0
- package/types/theme/nativeFontFamily.d.ts.map +1 -0
- package/types/theme/nativeFontFamily.native.d.ts +8 -0
- package/types/theme/nativeFontFamily.native.d.ts.map +1 -0
- package/types/theme/nativeMonoFamily.d.ts +15 -0
- package/types/theme/nativeMonoFamily.d.ts.map +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/theme",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.66.0",
|
|
4
4
|
"description": "Tamagui theme system for multiplatform.one",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"multiplatform",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"access": "public"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@multiplatform.one/platform": "^7.
|
|
76
|
-
"@multiplatform.one/store": "^7.
|
|
75
|
+
"@multiplatform.one/platform": "^7.66.0",
|
|
76
|
+
"@multiplatform.one/store": "^7.66.0",
|
|
77
77
|
"@tamagui/animations-react-native": "2.7.6",
|
|
78
78
|
"@tamagui/colors": "2.7.6",
|
|
79
79
|
"@tamagui/config": "2.7.6",
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@expo/prebuild-config": "55.0.18",
|
|
92
|
-
"@multiplatform.one/config": "7.
|
|
93
|
-
"@multiplatform.one/test-utils": "7.
|
|
92
|
+
"@multiplatform.one/config": "7.66.0",
|
|
93
|
+
"@multiplatform.one/test-utils": "7.66.0",
|
|
94
94
|
"@tamagui/animations-css": "2.7.6",
|
|
95
95
|
"@tamagui/animations-reanimated": "2.7.6",
|
|
96
96
|
"@tamagui/font-inter": "2.7.6",
|
package/src/menuRow.spec.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { menuRowFrame } from "./menuRow";
|
|
2
|
+
import { menuRowChecked, menuRowFrame } from "./menuRow";
|
|
3
3
|
|
|
4
4
|
describe("menuRowFrame (LC-16 shared menu-row geometry)", () => {
|
|
5
5
|
it("spans the overlay edge-to-edge with its own horizontal padding (SP-EDGE)", () => {
|
|
@@ -30,3 +30,9 @@ describe("menuRowFrame (LC-16 shared menu-row geometry)", () => {
|
|
|
30
30
|
expect(menuRowFrame).not.toHaveProperty("paddingVertical");
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
|
+
|
|
34
|
+
describe("menuRowChecked (LC-262 / LC-172 checked row)", () => {
|
|
35
|
+
it("draws no fill: the check mark carries the selection (FZ-8355)", () => {
|
|
36
|
+
expect(menuRowChecked).toEqual({ backgroundColor: "transparent" });
|
|
37
|
+
});
|
|
38
|
+
});
|
package/src/menuRow.ts
CHANGED
|
@@ -33,3 +33,13 @@ export const menuRowFrame = {
|
|
|
33
33
|
userSelect: "none",
|
|
34
34
|
backgroundColor: "transparent",
|
|
35
35
|
} as const;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* LC-262 / LC-172: a checked or selected menu or picker row draws no fill in
|
|
39
|
+
* either scheme; the accent check alone marks it. A per-row `$color2` plate
|
|
40
|
+
* read as nothing in light and near-black in dark (FZ-8355). Hover, press and
|
|
41
|
+
* keyboard focus stay transient feedback, owned by each consumer.
|
|
42
|
+
*/
|
|
43
|
+
export const menuRowChecked = {
|
|
44
|
+
backgroundColor: "transparent",
|
|
45
|
+
} as const;
|
|
@@ -7,6 +7,7 @@ import { createFont, type GenericFont } from "@tamagui/web";
|
|
|
7
7
|
import { flooredLineHeight, fontCategoryMetrics } from "../fontCategoryMetrics";
|
|
8
8
|
import { fontCategoryStacks } from "../fontCategoryStacks";
|
|
9
9
|
import type { FontCategory } from "../knobs";
|
|
10
|
+
import { nativeCategoryFamily } from "../nativeFontFamily";
|
|
10
11
|
import { generateScale, type ScaleFonts } from "../scale/generateScale";
|
|
11
12
|
import { defaultScaleInputs } from "../scale/scaleInputs";
|
|
12
13
|
|
|
@@ -137,7 +138,7 @@ export function createCategoryFont(
|
|
|
137
138
|
): GenericFont {
|
|
138
139
|
const sizes = scope === "heading" ? tables.headingSizes : tables.bodySizes;
|
|
139
140
|
return createFont({
|
|
140
|
-
family,
|
|
141
|
+
family: nativeCategoryFamily(category, family),
|
|
141
142
|
size: { ...sizes },
|
|
142
143
|
lineHeight: categoryLineHeights(category, tables, scope),
|
|
143
144
|
weight: scope === "heading" ? headingWeights : bodyWeights,
|
|
@@ -310,6 +311,44 @@ function deriveHeading(source: HeadingSource, tables: ScaleFonts): GenericFont {
|
|
|
310
311
|
return font;
|
|
311
312
|
}
|
|
312
313
|
|
|
314
|
+
function familyOf(font: GenericFont): string | undefined {
|
|
315
|
+
const family = font.family as string | { val?: string } | undefined;
|
|
316
|
+
return typeof family === "string" ? family : family?.val;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
type FaceName = string | { val?: string } | undefined;
|
|
320
|
+
type FaceMap = Record<string, Record<string, FaceName> | undefined>;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* `createFont` fills every weight a face map lacks with `{ normal: family }`,
|
|
324
|
+
* and tamagui's native split swaps the family for that entry and drops the
|
|
325
|
+
* weight. Entries that only repeat the renamed family go, so the weight
|
|
326
|
+
* reaches the platform face; a named face (a bundled bold) stays.
|
|
327
|
+
*/
|
|
328
|
+
function withoutFamilyFill(face: GenericFont["face"], family: string): GenericFont["face"] {
|
|
329
|
+
if (!face) return face;
|
|
330
|
+
const kept: FaceMap = {};
|
|
331
|
+
for (const [weight, styles] of Object.entries(face as FaceMap)) {
|
|
332
|
+
const named = Object.entries(styles ?? {}).filter(([, name]) => {
|
|
333
|
+
const value = typeof name === "string" ? name : name?.val;
|
|
334
|
+
return value !== undefined && value !== family;
|
|
335
|
+
});
|
|
336
|
+
if (named.length) kept[weight] = Object.fromEntries(named);
|
|
337
|
+
}
|
|
338
|
+
return Object.keys(kept).length ? (kept as GenericFont["face"]) : undefined;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** A consumer category font keeps its object unless native must rename its family. */
|
|
342
|
+
function withNativeFamily(category: FontCategory, font: GenericFont | undefined) {
|
|
343
|
+
const family = font && familyOf(font);
|
|
344
|
+
if (!font || family === undefined) return font;
|
|
345
|
+
const resolved = nativeCategoryFamily(category, family);
|
|
346
|
+
if (resolved === family) return font;
|
|
347
|
+
const { face, ...rest } = font;
|
|
348
|
+
const kept = withoutFamilyFill(face, family);
|
|
349
|
+
return { ...rest, family: resolved, ...(kept ? { face: kept } : {}) } as GenericFont;
|
|
350
|
+
}
|
|
351
|
+
|
|
313
352
|
export function withDerivedHeadingCategories(
|
|
314
353
|
fonts: Record<string, GenericFont>,
|
|
315
354
|
tables: ScaleFonts = defaultTypeTables,
|
|
@@ -317,18 +356,19 @@ export function withDerivedHeadingCategories(
|
|
|
317
356
|
const result = { ...fonts };
|
|
318
357
|
for (const [category, key] of Object.entries(headingCategoryFontKeys)) {
|
|
319
358
|
const source = fonts[category];
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
359
|
+
const resolvedSource = withNativeFamily(category as FontCategory, source);
|
|
360
|
+
if (resolvedSource) result[category] = resolvedSource;
|
|
361
|
+
if (fonts[key] !== defaultFonts[key]) {
|
|
362
|
+
const heading = withNativeFamily(category as FontCategory, fonts[key]);
|
|
363
|
+
if (heading) result[key] = heading;
|
|
325
364
|
continue;
|
|
326
|
-
|
|
365
|
+
}
|
|
366
|
+
if (!resolvedSource || source === defaultFonts[category as keyof typeof defaultFonts]) continue;
|
|
327
367
|
result[key] = deriveHeading(
|
|
328
368
|
{
|
|
329
369
|
category: category as FontCategory,
|
|
330
|
-
family:
|
|
331
|
-
face:
|
|
370
|
+
family: familyOf(resolvedSource) ?? "",
|
|
371
|
+
face: resolvedSource.face,
|
|
332
372
|
},
|
|
333
373
|
tables,
|
|
334
374
|
);
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LC-137 NATIVE-FONT-FAMILY, the mono category on device (FZ-8143). The SHC
|
|
3
|
+
* console on an iPhone 16 sim drew every bold `$mono` hostname in the
|
|
4
|
+
* proportional system face: `$mono` reached React Native as a CSS stack, and
|
|
5
|
+
* iOS matches no family against a stack.
|
|
6
|
+
*
|
|
7
|
+
* Each registered mono font is resolved the way the device resolves it:
|
|
8
|
+
* tamagui's native `face` swap first, then iOS RCTFont (a known family's
|
|
9
|
+
* nearest-weight face, else the system face) or Android (`monospace` takes
|
|
10
|
+
* the weight, an unknown family falls to the default sans).
|
|
11
|
+
*/
|
|
12
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
13
|
+
|
|
14
|
+
vi.mock("tamagui", () => ({ createTamagui: (config: unknown) => config }));
|
|
15
|
+
vi.mock("./animations/index", () => ({ animations: {} }));
|
|
16
|
+
|
|
17
|
+
const os = vi.hoisted(() => ({ current: "ios" as "ios" | "android" }));
|
|
18
|
+
vi.mock("react-native", () => ({
|
|
19
|
+
Platform: {
|
|
20
|
+
get OS() {
|
|
21
|
+
return os.current;
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
// A glob, not an import: the spec has to load and fail its assertions on
|
|
27
|
+
// code that has no native twin yet.
|
|
28
|
+
const nativeTwin = import.meta.glob<Record<string, unknown>>("./nativeFontFamily.native.ts");
|
|
29
|
+
|
|
30
|
+
type Face = { family: string; weight: number; mono: boolean };
|
|
31
|
+
type Font = {
|
|
32
|
+
family?: string | { val?: string };
|
|
33
|
+
weight?: Record<string, string>;
|
|
34
|
+
face?: Record<string, { normal?: string | { val?: string } }>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/** Families iOS ships, by face: what `UIFont.fontNamesForFamilyName` returns. */
|
|
38
|
+
const iosFamilies: Record<string, { name: string; weight: number }[]> = {
|
|
39
|
+
Menlo: [
|
|
40
|
+
{ name: "Menlo-Regular", weight: 400 },
|
|
41
|
+
{ name: "Menlo-Bold", weight: 700 },
|
|
42
|
+
],
|
|
43
|
+
"Courier New": [
|
|
44
|
+
{ name: "CourierNewPSMT", weight: 400 },
|
|
45
|
+
{ name: "CourierNewPS-BoldMT", weight: 700 },
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
const iosMonoFaces = new Set([
|
|
49
|
+
"Menlo-Regular",
|
|
50
|
+
"Menlo-Bold",
|
|
51
|
+
"CourierNewPSMT",
|
|
52
|
+
"CourierNewPS-BoldMT",
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
/** The type ramp's weights: the v5 tables plus every weight a use site writes. */
|
|
56
|
+
const rampWeights = ["400", "500", "600", "700", "800"];
|
|
57
|
+
|
|
58
|
+
function plainFamily(font: Font): string | undefined {
|
|
59
|
+
return typeof font.family === "string" ? font.family : font.family?.val;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function resolveOnDevice(font: Font, fontWeight: string): Face {
|
|
63
|
+
let family = plainFamily(font) ?? "System";
|
|
64
|
+
let weight: string | undefined = fontWeight;
|
|
65
|
+
const swap = font.face?.[fontWeight]?.normal;
|
|
66
|
+
const swapped = typeof swap === "string" ? swap : swap?.val;
|
|
67
|
+
if (swapped) {
|
|
68
|
+
family = swapped;
|
|
69
|
+
weight = undefined;
|
|
70
|
+
}
|
|
71
|
+
const want = Number(weight ?? 400);
|
|
72
|
+
if (os.current === "android") {
|
|
73
|
+
if (family === "monospace") return { family, weight: want, mono: true };
|
|
74
|
+
return { family: "sans-serif", weight: want, mono: false };
|
|
75
|
+
}
|
|
76
|
+
const faces = iosFamilies[family];
|
|
77
|
+
if (!faces) return { family: "SF Pro (system)", weight: want, mono: false };
|
|
78
|
+
const face = faces.reduce((best, next) =>
|
|
79
|
+
Math.abs(next.weight - want) < Math.abs(best.weight - want) ? next : best,
|
|
80
|
+
);
|
|
81
|
+
return { family: face.name, weight: face.weight, mono: iosMonoFaces.has(face.name) };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function nativeFonts(
|
|
85
|
+
target: "ios" | "android",
|
|
86
|
+
consumerMono?: (createDefaultFont: typeof import("../font").createDefaultFont) => unknown,
|
|
87
|
+
) {
|
|
88
|
+
os.current = target;
|
|
89
|
+
vi.resetModules();
|
|
90
|
+
vi.doMock("./nativeFontFamily", () => nativeTwin["./nativeFontFamily.native.ts"]!());
|
|
91
|
+
const { createDefaultFont } = await import("../font");
|
|
92
|
+
const { createDefaultThemeConfig } = await import("./createDefaultThemeConfig");
|
|
93
|
+
const { densePreset } = await import("./presets");
|
|
94
|
+
const config = createDefaultThemeConfig({
|
|
95
|
+
presets: { dense: densePreset },
|
|
96
|
+
...(consumerMono ? { fonts: { mono: consumerMono(createDefaultFont) as never } } : {}),
|
|
97
|
+
});
|
|
98
|
+
const base = config.tamagui.fonts as unknown as Record<string, Font>;
|
|
99
|
+
const dense = config.scales?.dense?.tamagui().fonts as unknown as Record<string, Font>;
|
|
100
|
+
return { base, dense };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function expectMonoAtEveryWeight(fonts: Record<string, Font>, label: string) {
|
|
104
|
+
for (const key of ["mono", "headingMono"]) {
|
|
105
|
+
const font = fonts[key];
|
|
106
|
+
expect(font, `${label} ${key}`).toBeDefined();
|
|
107
|
+
for (const weight of rampWeights) {
|
|
108
|
+
const face = resolveOnDevice(font!, weight);
|
|
109
|
+
expect(face.mono, `${label} $${key} @${weight} -> ${face.family}`).toBe(true);
|
|
110
|
+
}
|
|
111
|
+
const bold = resolveOnDevice(font!, "700");
|
|
112
|
+
expect(bold.weight, `${label} $${key} @700 is bold`).toBeGreaterThanOrEqual(700);
|
|
113
|
+
const regular = resolveOnDevice(font!, "400");
|
|
114
|
+
expect(regular.weight, `${label} $${key} @400 is regular`).toBe(400);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
afterEach(() => {
|
|
119
|
+
vi.doUnmock("./nativeFontFamily");
|
|
120
|
+
vi.resetModules();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe("$mono resolves to a monospaced face at every weight on native (LC-137, FZ-8143)", () => {
|
|
124
|
+
it.each(["ios", "android"] as const)("MPO's own $mono on %s", async (target) => {
|
|
125
|
+
const { base, dense } = await nativeFonts(target);
|
|
126
|
+
expectMonoAtEveryWeight(base, `${target} default`);
|
|
127
|
+
expectMonoAtEveryWeight(dense, `${target} dense scale`);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it.each(["ios", "android"] as const)(
|
|
131
|
+
"a consumer $mono registered as a CSS stack on %s (the SHC console's)",
|
|
132
|
+
async (target) => {
|
|
133
|
+
// `face: {}` through createFont fills every weight with the stack, and
|
|
134
|
+
// the native face swap then drops the weight: proportional regular.
|
|
135
|
+
const { base, dense } = await nativeFonts(target, (createDefaultFont) =>
|
|
136
|
+
createDefaultFont({
|
|
137
|
+
family: "'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
138
|
+
weight: { 1: "400", 4: "400", true: "400", 5: "500", 7: "600" },
|
|
139
|
+
face: {},
|
|
140
|
+
}),
|
|
141
|
+
);
|
|
142
|
+
expectMonoAtEveryWeight(base, `${target} stack`);
|
|
143
|
+
expectMonoAtEveryWeight(dense, `${target} stack dense`);
|
|
144
|
+
},
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
it.each(["ios", "android"] as const)(
|
|
148
|
+
"a consumer $mono naming another platform's system mono on %s (Kitchen Sink's Menlo)",
|
|
149
|
+
async (target) => {
|
|
150
|
+
const { base } = await nativeFonts(target, (createDefaultFont) =>
|
|
151
|
+
createDefaultFont({ family: "Menlo" }),
|
|
152
|
+
);
|
|
153
|
+
expectMonoAtEveryWeight(base, `${target} Menlo`);
|
|
154
|
+
},
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
it("keeps a named face while dropping the stack fill", async () => {
|
|
158
|
+
const { base } = await nativeFonts("ios", (createDefaultFont) =>
|
|
159
|
+
createDefaultFont({
|
|
160
|
+
family: "'Plex', ui-monospace, monospace",
|
|
161
|
+
face: { 800: { normal: "IBMPlexMono-ExtraBold" } },
|
|
162
|
+
}),
|
|
163
|
+
);
|
|
164
|
+
const face = base.mono!.face!;
|
|
165
|
+
expect(Object.keys(face).filter((weight) => Number(weight) < 800)).toEqual([]);
|
|
166
|
+
expect(face["800"]?.normal).toBe("IBMPlexMono-ExtraBold");
|
|
167
|
+
expect(resolveOnDevice(base.mono!, "700")).toMatchObject({ family: "Menlo-Bold", mono: true });
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("keeps a single family the app bundles", async () => {
|
|
171
|
+
const { base } = await nativeFonts("ios", (createDefaultFont) =>
|
|
172
|
+
createDefaultFont({ family: "JetBrains Mono" }),
|
|
173
|
+
);
|
|
174
|
+
expect(plainFamily(base.mono!)).toBe("JetBrains Mono");
|
|
175
|
+
expect(plainFamily(base.headingMono!)).toBe("JetBrains Mono");
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("leaves the web stack and every other category untouched", async () => {
|
|
179
|
+
vi.resetModules();
|
|
180
|
+
const { defaultFonts } = await import("./defaults/fonts");
|
|
181
|
+
const { fontCategoryStacks } = await import("./fontCategoryStacks");
|
|
182
|
+
expect(defaultFonts.mono.family).toBe(fontCategoryStacks.mono);
|
|
183
|
+
const { base } = await nativeFonts("ios");
|
|
184
|
+
expect(plainFamily(base.pixel!)).toBe(fontCategoryStacks.pixel);
|
|
185
|
+
expect(plainFamily(base.serif!)).toBe(fontCategoryStacks.serif);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Platform } from "react-native";
|
|
2
|
+
import type { FontCategory } from "./knobs";
|
|
3
|
+
import { resolveNativeMonoFamily } from "./nativeMonoFamily";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One registered family per category on iOS and Android, never a CSS stack
|
|
7
|
+
* (LC-137). Other native hosts keep the stack: GNOME's Pango reads a
|
|
8
|
+
* comma-separated family list.
|
|
9
|
+
*/
|
|
10
|
+
export function nativeCategoryFamily(category: FontCategory, family: string): string {
|
|
11
|
+
if (category !== "mono") return family;
|
|
12
|
+
if (Platform.OS !== "ios" && Platform.OS !== "android") return family;
|
|
13
|
+
return resolveNativeMonoFamily(family, Platform.OS);
|
|
14
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LC-137 NATIVE-FONT-FAMILY for the mono category (FZ-8143).
|
|
3
|
+
*
|
|
4
|
+
* React Native takes one family name. A CSS stack, or a system mono that
|
|
5
|
+
* only another platform ships, matches nothing: iOS draws the proportional
|
|
6
|
+
* system face and Android its default sans, at whatever weight survives.
|
|
7
|
+
* Each native platform has one monospaced family with every weight the type
|
|
8
|
+
* ramp asks for reachable through `fontWeight`: Menlo on iOS (Regular and
|
|
9
|
+
* Bold, matched by nearest weight) and `monospace` on Android (weight
|
|
10
|
+
* applied by the platform). A single family the app bundles is kept.
|
|
11
|
+
*/
|
|
12
|
+
export type NativeOS = "ios" | "android";
|
|
13
|
+
|
|
14
|
+
export const platformMonoFamily: Record<NativeOS, string> = {
|
|
15
|
+
ios: "Menlo",
|
|
16
|
+
android: "monospace",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const shippedMono: Record<NativeOS, ReadonlySet<string>> = {
|
|
20
|
+
ios: new Set(["Menlo", "Courier", "Courier New"]),
|
|
21
|
+
android: new Set(["monospace"]),
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const systemMono = new Set([
|
|
25
|
+
"ui-monospace",
|
|
26
|
+
"monospace",
|
|
27
|
+
"SFMono-Regular",
|
|
28
|
+
"SF Mono",
|
|
29
|
+
"Menlo",
|
|
30
|
+
"Monaco",
|
|
31
|
+
"Consolas",
|
|
32
|
+
"Courier",
|
|
33
|
+
"Courier New",
|
|
34
|
+
"Liberation Mono",
|
|
35
|
+
"DejaVu Sans Mono",
|
|
36
|
+
"Cascadia Code",
|
|
37
|
+
"Cascadia Mono",
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
export function resolveNativeMonoFamily(family: string, os: NativeOS): string {
|
|
41
|
+
if (family.includes(",")) return platformMonoFamily[os];
|
|
42
|
+
const name = family.trim().replace(/^(['"])(.*)\1$/, "$2");
|
|
43
|
+
if (shippedMono[os].has(name)) return name;
|
|
44
|
+
if (systemMono.has(name)) return platformMonoFamily[os];
|
|
45
|
+
return name;
|
|
46
|
+
}
|
package/types/menuRow.d.ts
CHANGED
|
@@ -33,4 +33,13 @@ export declare const menuRowFrame: {
|
|
|
33
33
|
readonly userSelect: "none";
|
|
34
34
|
readonly backgroundColor: "transparent";
|
|
35
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* LC-262 / LC-172: a checked or selected menu or picker row draws no fill in
|
|
38
|
+
* either scheme; the accent check alone marks it. A per-row `$color2` plate
|
|
39
|
+
* read as nothing in light and near-black in dark (FZ-8355). Hover, press and
|
|
40
|
+
* keyboard focus stay transient feedback, owned by each consumer.
|
|
41
|
+
*/
|
|
42
|
+
export declare const menuRowChecked: {
|
|
43
|
+
readonly backgroundColor: "transparent";
|
|
44
|
+
};
|
|
36
45
|
//# sourceMappingURL=menuRow.d.ts.map
|
package/types/menuRow.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menuRow.d.ts","sourceRoot":"","sources":["../src/menuRow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,YAAY;;;;;;;;CAQf,CAAC"}
|
|
1
|
+
{"version":3,"file":"menuRow.d.ts","sourceRoot":"","sources":["../src/menuRow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,YAAY;;;;;;;;CAQf,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,cAAc;;CAEjB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../../src/theme/defaults/fonts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAG5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../../src/theme/defaults/fonts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FontCategory } from "./knobs";
|
|
2
|
+
/** Web keeps the CSS stack; the native twin resolves it to one family (LC-137). */
|
|
3
|
+
export declare function nativeCategoryFamily(_category: FontCategory, family: string): string;
|
|
4
|
+
//# sourceMappingURL=nativeFontFamily.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativeFontFamily.d.ts","sourceRoot":"","sources":["../../src/theme/nativeFontFamily.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FontCategory } from "./knobs";
|
|
2
|
+
/**
|
|
3
|
+
* One registered family per category on iOS and Android, never a CSS stack
|
|
4
|
+
* (LC-137). Other native hosts keep the stack: GNOME's Pango reads a
|
|
5
|
+
* comma-separated family list.
|
|
6
|
+
*/
|
|
7
|
+
export declare function nativeCategoryFamily(category: FontCategory, family: string): string;
|
|
8
|
+
//# sourceMappingURL=nativeFontFamily.native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativeFontFamily.native.d.ts","sourceRoot":"","sources":["../../src/theme/nativeFontFamily.native.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG5C;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAInF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LC-137 NATIVE-FONT-FAMILY for the mono category (FZ-8143).
|
|
3
|
+
*
|
|
4
|
+
* React Native takes one family name. A CSS stack, or a system mono that
|
|
5
|
+
* only another platform ships, matches nothing: iOS draws the proportional
|
|
6
|
+
* system face and Android its default sans, at whatever weight survives.
|
|
7
|
+
* Each native platform has one monospaced family with every weight the type
|
|
8
|
+
* ramp asks for reachable through `fontWeight`: Menlo on iOS (Regular and
|
|
9
|
+
* Bold, matched by nearest weight) and `monospace` on Android (weight
|
|
10
|
+
* applied by the platform). A single family the app bundles is kept.
|
|
11
|
+
*/
|
|
12
|
+
export type NativeOS = "ios" | "android";
|
|
13
|
+
export declare const platformMonoFamily: Record<NativeOS, string>;
|
|
14
|
+
export declare function resolveNativeMonoFamily(family: string, os: NativeOS): string;
|
|
15
|
+
//# sourceMappingURL=nativeMonoFamily.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativeMonoFamily.d.ts","sourceRoot":"","sources":["../../src/theme/nativeMonoFamily.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;AAEzC,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAGvD,CAAC;AAuBF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,MAAM,CAM5E"}
|