@agent-native/toolkit 0.17.6 → 0.18.0-nightly-20260828160610
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/agent-native.eject.json +1 -0
- package/dist/design-tweaks/font-family.d.ts +46 -0
- package/dist/design-tweaks/font-family.d.ts.map +1 -0
- package/dist/design-tweaks/font-family.js +94 -0
- package/dist/design-tweaks/font-family.js.map +1 -0
- package/dist/design-tweaks/font-family.spec.d.ts +2 -0
- package/dist/design-tweaks/font-family.spec.d.ts.map +1 -0
- package/dist/design-tweaks/font-family.spec.js +16 -0
- package/dist/design-tweaks/font-family.spec.js.map +1 -0
- package/dist/design-tweaks/index.d.ts +1 -0
- package/dist/design-tweaks/index.d.ts.map +1 -1
- package/dist/design-tweaks/index.js +1 -0
- package/dist/design-tweaks/index.js.map +1 -1
- package/package.json +1 -1
- package/src/design-tweaks/font-family.spec.ts +26 -0
- package/src/design-tweaks/font-family.tsx +170 -0
- package/src/design-tweaks/index.ts +1 -0
package/agent-native.eject.json
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
+
import { SelectContent } from "../ui/select.js";
|
|
3
|
+
export declare const FONT_FAMILY_OPTIONS: readonly [{
|
|
4
|
+
readonly value: "inherit";
|
|
5
|
+
readonly key: "inherit";
|
|
6
|
+
}, {
|
|
7
|
+
readonly value: "sans-serif";
|
|
8
|
+
readonly key: "sansSerif";
|
|
9
|
+
}, {
|
|
10
|
+
readonly value: "serif";
|
|
11
|
+
readonly key: "serif";
|
|
12
|
+
}, {
|
|
13
|
+
readonly value: "monospace";
|
|
14
|
+
readonly key: "monospace";
|
|
15
|
+
}, {
|
|
16
|
+
readonly value: "'Inter', sans-serif";
|
|
17
|
+
readonly key: "inter";
|
|
18
|
+
}, {
|
|
19
|
+
readonly value: "'Poppins', sans-serif";
|
|
20
|
+
readonly key: "poppins";
|
|
21
|
+
}, {
|
|
22
|
+
readonly value: "'Playfair Display', serif";
|
|
23
|
+
readonly key: "playfairDisplay";
|
|
24
|
+
}, {
|
|
25
|
+
readonly value: "'JetBrains Mono', monospace";
|
|
26
|
+
readonly key: "jetBrainsMono";
|
|
27
|
+
}];
|
|
28
|
+
export declare function splitFontFamilyList(value: string | undefined): string[];
|
|
29
|
+
export declare function displayFontFamilyName(value: string | undefined): string;
|
|
30
|
+
export declare function resolveFontFamilySelectValue(value: string | undefined): string;
|
|
31
|
+
export interface FontFamilySelectOption {
|
|
32
|
+
value: string;
|
|
33
|
+
label: string;
|
|
34
|
+
}
|
|
35
|
+
export interface VisualFontFamilyPickerProps {
|
|
36
|
+
label: string;
|
|
37
|
+
value: string;
|
|
38
|
+
options: readonly FontFamilySelectOption[];
|
|
39
|
+
onChange: (value: string) => void;
|
|
40
|
+
className?: string;
|
|
41
|
+
contentProps?: Omit<ComponentPropsWithoutRef<typeof SelectContent>, "children"> & Partial<Record<`data-${string}`, string | undefined>>;
|
|
42
|
+
mixed?: boolean;
|
|
43
|
+
mixedLabel: string;
|
|
44
|
+
}
|
|
45
|
+
export declare function VisualFontFamilyPicker({ label, value, options, onChange, className, contentProps, mixed, mixedLabel, }: VisualFontFamilyPickerProps): import("react").JSX.Element;
|
|
46
|
+
//# sourceMappingURL=font-family.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-family.d.ts","sourceRoot":"","sources":["../../src/design-tweaks/font-family.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,EAEL,aAAa,EAId,MAAM,iBAAiB,CAAC;AAGzB,eAAO,MAAM,mBAAmB;aAC5B,KAAK,EAAE,SAAS;aAAE,GAAG,EAAE,SAAS;;aAChC,KAAK,EAAE,YAAY;aAAE,GAAG,EAAE,WAAW;;aACrC,KAAK,EAAE,OAAO;aAAE,GAAG,EAAE,OAAO;;aAC5B,KAAK,EAAE,WAAW;aAAE,GAAG,EAAE,WAAW;;aACpC,KAAK,EAAE,qBAAqB;aAAE,GAAG,EAAE,OAAO;;aAC1C,KAAK,EAAE,uBAAuB;aAAE,GAAG,EAAE,SAAS;;aAC9C,KAAK,EAAE,2BAA2B;aAAE,GAAG,EAAE,iBAAiB;;aAC1D,KAAK,EAAE,6BAA6B;aAAE,GAAG,EAAE,eAAe;EACpD,CAAC;AAUX,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAoBvE;AAUD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAiBvE;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,MAAM,CAgBR;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC3C,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,IAAI,CACjB,wBAAwB,CAAC,OAAO,aAAa,CAAC,EAC9C,UAAU,CACX,GACC,OAAO,CAAC,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,KAAK,EACL,OAAO,EACP,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,KAAa,EACb,UAAU,GACX,EAAE,2BAA2B,+BAyC7B"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "../ui/select.js";
|
|
3
|
+
import { cn } from "../utils.js";
|
|
4
|
+
export const FONT_FAMILY_OPTIONS = [
|
|
5
|
+
{ value: "inherit", key: "inherit" },
|
|
6
|
+
{ value: "sans-serif", key: "sansSerif" },
|
|
7
|
+
{ value: "serif", key: "serif" },
|
|
8
|
+
{ value: "monospace", key: "monospace" },
|
|
9
|
+
{ value: "'Inter', sans-serif", key: "inter" },
|
|
10
|
+
{ value: "'Poppins', sans-serif", key: "poppins" },
|
|
11
|
+
{ value: "'Playfair Display', serif", key: "playfairDisplay" },
|
|
12
|
+
{ value: "'JetBrains Mono', monospace", key: "jetBrainsMono" },
|
|
13
|
+
];
|
|
14
|
+
function cleanFontFamilyName(value) {
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
return (trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
17
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'"))
|
|
18
|
+
? trimmed.slice(1, -1).trim()
|
|
19
|
+
: trimmed;
|
|
20
|
+
}
|
|
21
|
+
export function splitFontFamilyList(value) {
|
|
22
|
+
if (!value?.trim())
|
|
23
|
+
return [];
|
|
24
|
+
const families = [];
|
|
25
|
+
let token = "";
|
|
26
|
+
let quote = null;
|
|
27
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
28
|
+
const char = value[index];
|
|
29
|
+
if ((char === '"' || char === "'") && value[index - 1] !== "\\") {
|
|
30
|
+
if (quote === char)
|
|
31
|
+
quote = null;
|
|
32
|
+
else if (!quote)
|
|
33
|
+
quote = char;
|
|
34
|
+
}
|
|
35
|
+
if (char === "," && !quote) {
|
|
36
|
+
const family = cleanFontFamilyName(token);
|
|
37
|
+
if (family)
|
|
38
|
+
families.push(family);
|
|
39
|
+
token = "";
|
|
40
|
+
}
|
|
41
|
+
else
|
|
42
|
+
token += char;
|
|
43
|
+
}
|
|
44
|
+
const family = cleanFontFamilyName(token);
|
|
45
|
+
if (family)
|
|
46
|
+
families.push(family);
|
|
47
|
+
return families;
|
|
48
|
+
}
|
|
49
|
+
function normalizeFontFamilyName(value) {
|
|
50
|
+
return cleanFontFamilyName(value).replace(/\s+/g, " ").toLowerCase();
|
|
51
|
+
}
|
|
52
|
+
function normalizeFontFamilyStack(value) {
|
|
53
|
+
return splitFontFamilyList(value).map(normalizeFontFamilyName).join(",");
|
|
54
|
+
}
|
|
55
|
+
export function displayFontFamilyName(value) {
|
|
56
|
+
const first = splitFontFamilyList(value)[0];
|
|
57
|
+
if (!first)
|
|
58
|
+
return "Sans Serif"; // i18n-ignore shared generic font label
|
|
59
|
+
const normalized = normalizeFontFamilyName(first);
|
|
60
|
+
if (normalized === "sans-serif") {
|
|
61
|
+
return "Sans Serif"; // i18n-ignore shared generic font label
|
|
62
|
+
}
|
|
63
|
+
if (normalized === "serif")
|
|
64
|
+
return "Serif"; // i18n-ignore shared generic font label
|
|
65
|
+
if (normalized === "monospace") {
|
|
66
|
+
return "Monospace"; // i18n-ignore shared generic font label
|
|
67
|
+
}
|
|
68
|
+
if (normalized === "system-ui" || normalized === "-apple-system")
|
|
69
|
+
return "System UI"; // i18n-ignore shared generic font label
|
|
70
|
+
if (normalized === "blinkmacsystemfont") {
|
|
71
|
+
return "Apple System"; // i18n-ignore shared generic font label
|
|
72
|
+
}
|
|
73
|
+
return first;
|
|
74
|
+
}
|
|
75
|
+
export function resolveFontFamilySelectValue(value) {
|
|
76
|
+
const raw = value?.trim();
|
|
77
|
+
if (!raw)
|
|
78
|
+
return "sans-serif";
|
|
79
|
+
const normalizedStack = normalizeFontFamilyStack(raw);
|
|
80
|
+
const exact = FONT_FAMILY_OPTIONS.find((option) => normalizeFontFamilyStack(option.value) === normalizedStack);
|
|
81
|
+
if (exact)
|
|
82
|
+
return exact.value;
|
|
83
|
+
const first = normalizeFontFamilyName(splitFontFamilyList(raw)[0] ?? "");
|
|
84
|
+
return (FONT_FAMILY_OPTIONS.find((option) => normalizeFontFamilyName(splitFontFamilyList(option.value)[0] ?? "") ===
|
|
85
|
+
first)?.value ?? raw);
|
|
86
|
+
}
|
|
87
|
+
export function VisualFontFamilyPicker({ label, value, options, onChange, className, contentProps, mixed = false, mixedLabel, }) {
|
|
88
|
+
const selectValue = mixed ? "__mixed_font_family__" : value;
|
|
89
|
+
const unknown = !mixed && !options.some((option) => option.value === value)
|
|
90
|
+
? { value, label: displayFontFamilyName(value) }
|
|
91
|
+
: null;
|
|
92
|
+
return (_jsxs(Select, { value: selectValue, onValueChange: onChange, children: [_jsx(SelectTrigger, { "aria-label": label, className: cn("h-6 w-full px-1.5 text-[11px]", className), children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { ...contentProps, children: [mixed ? (_jsx(SelectItem, { value: "__mixed_font_family__", disabled: true, className: "!text-[11px] text-muted-foreground", children: mixedLabel })) : null, unknown ? (_jsx(SelectItem, { value: unknown.value, className: "!text-[11px]", children: unknown.label })) : null, options.map((option) => (_jsx(SelectItem, { value: option.value, className: "!text-[11px]", children: option.label }, option.value)))] })] }));
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=font-family.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-family.js","sourceRoot":"","sources":["../../src/design-tweaks/font-family.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-family.spec.d.ts","sourceRoot":"","sources":["../../src/design-tweaks/font-family.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { displayFontFamilyName, resolveFontFamilySelectValue, splitFontFamilyList, } from "./font-family.js";
|
|
3
|
+
describe("font family design tweaks", () => {
|
|
4
|
+
it("parses quoted stacks and resolves known families", () => {
|
|
5
|
+
expect(splitFontFamilyList("'Playfair Display', serif")).toEqual([
|
|
6
|
+
"Playfair Display",
|
|
7
|
+
"serif",
|
|
8
|
+
]);
|
|
9
|
+
expect(resolveFontFamilySelectValue('"Inter", sans-serif')).toBe("'Inter', sans-serif");
|
|
10
|
+
});
|
|
11
|
+
it("preserves unknown values while displaying their first family", () => {
|
|
12
|
+
expect(resolveFontFamilySelectValue("Brand Sans, sans-serif")).toBe("Brand Sans, sans-serif");
|
|
13
|
+
expect(displayFontFamilyName("Brand Sans, sans-serif")).toBe("Brand Sans");
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=font-family.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-family.spec.js","sourceRoot":"","sources":["../../src/design-tweaks/font-family.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EACL,qBAAqB,EACrB,4BAA4B,EAC5B,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAE1B,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,mBAAmB,CAAC,2BAA2B,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/D,kBAAkB;YAClB,OAAO;SACR,CAAC,CAAC;QACH,MAAM,CAAC,4BAA4B,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAC9D,qBAAqB,CACtB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,CAAC,4BAA4B,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CACjE,wBAAwB,CACzB,CAAC;QACF,MAAM,CAAC,qBAAqB,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/design-tweaks/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/design-tweaks/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kBAAkB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/design-tweaks/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/design-tweaks/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kBAAkB,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
displayFontFamilyName,
|
|
5
|
+
resolveFontFamilySelectValue,
|
|
6
|
+
splitFontFamilyList,
|
|
7
|
+
} from "./font-family.js";
|
|
8
|
+
|
|
9
|
+
describe("font family design tweaks", () => {
|
|
10
|
+
it("parses quoted stacks and resolves known families", () => {
|
|
11
|
+
expect(splitFontFamilyList("'Playfair Display', serif")).toEqual([
|
|
12
|
+
"Playfair Display",
|
|
13
|
+
"serif",
|
|
14
|
+
]);
|
|
15
|
+
expect(resolveFontFamilySelectValue('"Inter", sans-serif')).toBe(
|
|
16
|
+
"'Inter', sans-serif",
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("preserves unknown values while displaying their first family", () => {
|
|
21
|
+
expect(resolveFontFamilySelectValue("Brand Sans, sans-serif")).toBe(
|
|
22
|
+
"Brand Sans, sans-serif",
|
|
23
|
+
);
|
|
24
|
+
expect(displayFontFamilyName("Brand Sans, sans-serif")).toBe("Brand Sans");
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Select,
|
|
5
|
+
SelectContent,
|
|
6
|
+
SelectItem,
|
|
7
|
+
SelectTrigger,
|
|
8
|
+
SelectValue,
|
|
9
|
+
} from "../ui/select.js";
|
|
10
|
+
import { cn } from "../utils.js";
|
|
11
|
+
|
|
12
|
+
export const FONT_FAMILY_OPTIONS = [
|
|
13
|
+
{ value: "inherit", key: "inherit" },
|
|
14
|
+
{ value: "sans-serif", key: "sansSerif" },
|
|
15
|
+
{ value: "serif", key: "serif" },
|
|
16
|
+
{ value: "monospace", key: "monospace" },
|
|
17
|
+
{ value: "'Inter', sans-serif", key: "inter" },
|
|
18
|
+
{ value: "'Poppins', sans-serif", key: "poppins" },
|
|
19
|
+
{ value: "'Playfair Display', serif", key: "playfairDisplay" },
|
|
20
|
+
{ value: "'JetBrains Mono', monospace", key: "jetBrainsMono" },
|
|
21
|
+
] as const;
|
|
22
|
+
|
|
23
|
+
function cleanFontFamilyName(value: string): string {
|
|
24
|
+
const trimmed = value.trim();
|
|
25
|
+
return (trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
26
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'"))
|
|
27
|
+
? trimmed.slice(1, -1).trim()
|
|
28
|
+
: trimmed;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function splitFontFamilyList(value: string | undefined): string[] {
|
|
32
|
+
if (!value?.trim()) return [];
|
|
33
|
+
const families: string[] = [];
|
|
34
|
+
let token = "";
|
|
35
|
+
let quote: '"' | "'" | null = null;
|
|
36
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
37
|
+
const char = value[index];
|
|
38
|
+
if ((char === '"' || char === "'") && value[index - 1] !== "\\") {
|
|
39
|
+
if (quote === char) quote = null;
|
|
40
|
+
else if (!quote) quote = char;
|
|
41
|
+
}
|
|
42
|
+
if (char === "," && !quote) {
|
|
43
|
+
const family = cleanFontFamilyName(token);
|
|
44
|
+
if (family) families.push(family);
|
|
45
|
+
token = "";
|
|
46
|
+
} else token += char;
|
|
47
|
+
}
|
|
48
|
+
const family = cleanFontFamilyName(token);
|
|
49
|
+
if (family) families.push(family);
|
|
50
|
+
return families;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function normalizeFontFamilyName(value: string): string {
|
|
54
|
+
return cleanFontFamilyName(value).replace(/\s+/g, " ").toLowerCase();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function normalizeFontFamilyStack(value: string): string {
|
|
58
|
+
return splitFontFamilyList(value).map(normalizeFontFamilyName).join(",");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function displayFontFamilyName(value: string | undefined): string {
|
|
62
|
+
const first = splitFontFamilyList(value)[0];
|
|
63
|
+
if (!first) return "Sans Serif"; // i18n-ignore shared generic font label
|
|
64
|
+
const normalized = normalizeFontFamilyName(first);
|
|
65
|
+
if (normalized === "sans-serif") {
|
|
66
|
+
return "Sans Serif"; // i18n-ignore shared generic font label
|
|
67
|
+
}
|
|
68
|
+
if (normalized === "serif") return "Serif"; // i18n-ignore shared generic font label
|
|
69
|
+
if (normalized === "monospace") {
|
|
70
|
+
return "Monospace"; // i18n-ignore shared generic font label
|
|
71
|
+
}
|
|
72
|
+
if (normalized === "system-ui" || normalized === "-apple-system")
|
|
73
|
+
return "System UI"; // i18n-ignore shared generic font label
|
|
74
|
+
if (normalized === "blinkmacsystemfont") {
|
|
75
|
+
return "Apple System"; // i18n-ignore shared generic font label
|
|
76
|
+
}
|
|
77
|
+
return first;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function resolveFontFamilySelectValue(
|
|
81
|
+
value: string | undefined,
|
|
82
|
+
): string {
|
|
83
|
+
const raw = value?.trim();
|
|
84
|
+
if (!raw) return "sans-serif";
|
|
85
|
+
const normalizedStack = normalizeFontFamilyStack(raw);
|
|
86
|
+
const exact = FONT_FAMILY_OPTIONS.find(
|
|
87
|
+
(option) => normalizeFontFamilyStack(option.value) === normalizedStack,
|
|
88
|
+
);
|
|
89
|
+
if (exact) return exact.value;
|
|
90
|
+
const first = normalizeFontFamilyName(splitFontFamilyList(raw)[0] ?? "");
|
|
91
|
+
return (
|
|
92
|
+
FONT_FAMILY_OPTIONS.find(
|
|
93
|
+
(option) =>
|
|
94
|
+
normalizeFontFamilyName(splitFontFamilyList(option.value)[0] ?? "") ===
|
|
95
|
+
first,
|
|
96
|
+
)?.value ?? raw
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface FontFamilySelectOption {
|
|
101
|
+
value: string;
|
|
102
|
+
label: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface VisualFontFamilyPickerProps {
|
|
106
|
+
label: string;
|
|
107
|
+
value: string;
|
|
108
|
+
options: readonly FontFamilySelectOption[];
|
|
109
|
+
onChange: (value: string) => void;
|
|
110
|
+
className?: string;
|
|
111
|
+
contentProps?: Omit<
|
|
112
|
+
ComponentPropsWithoutRef<typeof SelectContent>,
|
|
113
|
+
"children"
|
|
114
|
+
> &
|
|
115
|
+
Partial<Record<`data-${string}`, string | undefined>>;
|
|
116
|
+
mixed?: boolean;
|
|
117
|
+
mixedLabel: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function VisualFontFamilyPicker({
|
|
121
|
+
label,
|
|
122
|
+
value,
|
|
123
|
+
options,
|
|
124
|
+
onChange,
|
|
125
|
+
className,
|
|
126
|
+
contentProps,
|
|
127
|
+
mixed = false,
|
|
128
|
+
mixedLabel,
|
|
129
|
+
}: VisualFontFamilyPickerProps) {
|
|
130
|
+
const selectValue = mixed ? "__mixed_font_family__" : value;
|
|
131
|
+
const unknown =
|
|
132
|
+
!mixed && !options.some((option) => option.value === value)
|
|
133
|
+
? { value, label: displayFontFamilyName(value) }
|
|
134
|
+
: null;
|
|
135
|
+
return (
|
|
136
|
+
<Select value={selectValue} onValueChange={onChange}>
|
|
137
|
+
<SelectTrigger
|
|
138
|
+
aria-label={label}
|
|
139
|
+
className={cn("h-6 w-full px-1.5 text-[11px]", className)}
|
|
140
|
+
>
|
|
141
|
+
<SelectValue />
|
|
142
|
+
</SelectTrigger>
|
|
143
|
+
<SelectContent {...contentProps}>
|
|
144
|
+
{mixed ? (
|
|
145
|
+
<SelectItem
|
|
146
|
+
value="__mixed_font_family__"
|
|
147
|
+
disabled
|
|
148
|
+
className="!text-[11px] text-muted-foreground"
|
|
149
|
+
>
|
|
150
|
+
{mixedLabel}
|
|
151
|
+
</SelectItem>
|
|
152
|
+
) : null}
|
|
153
|
+
{unknown ? (
|
|
154
|
+
<SelectItem value={unknown.value} className="!text-[11px]">
|
|
155
|
+
{unknown.label}
|
|
156
|
+
</SelectItem>
|
|
157
|
+
) : null}
|
|
158
|
+
{options.map((option) => (
|
|
159
|
+
<SelectItem
|
|
160
|
+
key={option.value}
|
|
161
|
+
value={option.value}
|
|
162
|
+
className="!text-[11px]"
|
|
163
|
+
>
|
|
164
|
+
{option.label}
|
|
165
|
+
</SelectItem>
|
|
166
|
+
))}
|
|
167
|
+
</SelectContent>
|
|
168
|
+
</Select>
|
|
169
|
+
);
|
|
170
|
+
}
|