import { Plus } from "../../icons/SystemIcons"; import { isTextEditableSelection, type DomEditSelection } from "./domEditing"; import type { ImportedFontAsset } from "./fontAssets"; import { normalizeTextMetricValue } from "./propertyPanelHelpers"; import { ColorField } from "./propertyPanelColor"; import { FontFamilyField } from "./propertyPanelFont"; import { FlatRow, FlatSegmentedRow } from "./propertyPanelFlatPrimitives"; import { resolveValueTier, VALUE_TIER_LABEL_CLASS, VALUE_TIER_VALUE_CLASS, } from "./propertyPanelValueTier"; import { detectAvailableWeights, getTextFieldColor, getTextStyleValue, TextAreaField, TextSection, WEIGHT_LABELS, } from "./propertyPanelSections"; /* ------------------------------------------------------------------ */ /* Flat text section (design_handoff_studio_inspector, #10a) */ /* ------------------------------------------------------------------ */ const ALIGN_OPTIONS = [ { key: "left", label: "left", node: "L" }, { key: "center", label: "center", node: "C" }, { key: "right", label: "right", node: "R" }, { key: "justify", label: "justify", node: "J" }, ]; const CASE_OPTIONS = [ { key: "none", node: "–" }, { key: "uppercase", node: "AG" }, { key: "lowercase", node: "ag" }, ]; function FlatTextFieldEditor({ field, styles, fontAssets, onImportFonts, onSetText, onSetTextFieldStyle, }: { field: DomEditSelection["textFields"][number]; styles: Record; fontAssets: ImportedFontAsset[]; onImportFonts?: (files: FileList | File[]) => Promise; onSetText: (value: string, fieldKey?: string) => void; onSetTextFieldStyle: (fieldKey: string, property: string, value: string) => void; }) { const weight = getTextStyleValue(field, styles, "font-weight", "400"); const weightOptions = detectAvailableWeights( field.computedStyles["font-family"] || styles["font-family"] || "", ); const align = getTextStyleValue(field, styles, "text-align", "start"); const textTransform = getTextStyleValue(field, styles, "text-transform", "none"); const fontStyle = getTextStyleValue(field, styles, "font-style", "normal"); return ( <> onSetText(next, field.key)} /> onSetTextFieldStyle(field.key, "font-family", next)} /> onSetTextFieldStyle(field.key, "font-size", next)} />
Weight
onSetTextFieldStyle( field.key, "letter-spacing", normalizeTextMetricValue("letter-spacing", next), ) } onReset={() => onSetTextFieldStyle(field.key, "letter-spacing", "")} /> onSetTextFieldStyle( field.key, "line-height", normalizeTextMetricValue("line-height", next), ) } onReset={() => onSetTextFieldStyle(field.key, "line-height", "")} /> ({ key: option.key, node: option.node, active: align === option.key || (option.key === "left" && align === "start"), }))} onChange={(next) => onSetTextFieldStyle(field.key, "text-align", next)} /> ({ key: option.key, node: option.node, active: textTransform === option.key, })), { key: "normal", node: "A", active: fontStyle === "normal" }, { key: "italic", node: "A", active: fontStyle === "italic" }, ]} spacerAfterIndex={2} onChange={(next) => { if (next === "normal" || next === "italic") { onSetTextFieldStyle(field.key, "font-style", next); } else { onSetTextFieldStyle(field.key, "text-transform", next); } }} /> onSetTextFieldStyle(field.key, "color", next)} /> ); } export function FlatTextSection({ element, styles, fontAssets, onImportFonts, onSetText, onSetTextFieldStyle, onAddTextField, onRemoveTextField, }: { element: DomEditSelection; styles: Record; fontAssets: ImportedFontAsset[]; onImportFonts?: (files: FileList | File[]) => Promise; onSetText: (value: string, fieldKey?: string) => void; onSetTextFieldStyle: (fieldKey: string, property: string, value: string) => void; onAddTextField: (afterFieldKey?: string) => string | Promise | null; onRemoveTextField: (fieldKey: string) => void; }) { if (!isTextEditableSelection(element)) return null; const textFields = element.textFields; const activeField = textFields[0]; if (!activeField) return null; if (textFields.length > 1) { // The parent FlatGroup (PropertyPanelFlat) already renders a "Text" // heading around this section — suppress TextSection's own internal // heading so the flat panel doesn't show "Text" twice in a row. return ( ); } return (
); }