import { useState, type FormEvent } from "react"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import * as stylex from "@stylexjs/stylex"; import InlineError from "@/lib/InlineError"; import { settingsPutMutation } from "@/lib/queries"; import { buildSettingsPatch } from "@/lib/settingsDiff"; import type { Settings, SettingsEnvelope } from "@/lib/types"; import Select from "@/ui/Select"; import { styles as shared } from "@/ui/styles"; import { colors } from "@/ui/tokens.stylex"; import { SECTIONS, sectionValues, type AnyFieldDef } from "./settingsSections"; import { styles as config } from "./styles"; const DARK = "@media (prefers-color-scheme: dark)"; const styles = stylex.create({ form: { marginTop: "1rem", maxWidth: "48rem", }, /** A `fieldset` has a browser default border and padding; the layout wants neither. */ sections: { display: "flex", flexDirection: "column", gap: "1.5rem", borderStyle: "none", margin: 0, padding: 0, }, section: { borderRadius: "0.25rem", borderWidth: 1, borderStyle: "solid", borderColor: colors.border, padding: "1rem", }, legend: { paddingInline: "0.25rem", fontSize: "0.875rem", lineHeight: "1.25rem", fontWeight: 600, }, /** One column on a phone, two from `sm`. */ fieldGrid: { display: "grid", gap: "0.75rem", gridTemplateColumns: { default: "repeat(1, minmax(0, 1fr))", "@media (min-width: 640px)": "repeat(2, minmax(0, 1fr))", }, }, label: { fontSize: "0.875rem", lineHeight: "1.25rem", color: { default: "oklch(37% 0.013 285.805)", [DARK]: "oklch(87.1% 0.006 286.286)", }, }, checkboxRow: { display: "flex", alignItems: "center", gap: "0.5rem", }, field: { display: "flex", flexDirection: "column", gap: "0.25rem", }, fieldInput: { borderRadius: "0.25rem", borderWidth: 1, borderStyle: "solid", borderColor: colors.borderStrong, backgroundColor: colors.surfaceRaised, color: colors.text, paddingInline: "0.5rem", paddingBlock: "0.25rem", fontSize: "0.875rem", lineHeight: "1.25rem", }, derived: { color: colors.textMuted, }, /** Both notices span the whole grid so the wrapped sentence stays readable. */ spanRow: { gridColumn: { default: null, "@media (min-width: 640px)": "span 2 / span 2" }, fontSize: "0.875rem", lineHeight: "1.25rem", }, passwordNotice: { color: { default: "oklch(55.5% 0.163 48.998)", [DARK]: "oklch(82.8% 0.189 84.429)" }, }, mismatchNotice: { color: colors.danger, }, submitRow: { display: "flex", alignItems: "center", gap: "0.75rem", }, save: { borderStyle: "none", borderRadius: "0.25rem", paddingInline: "1rem", paddingBlock: "0.375rem", fontSize: "0.875rem", lineHeight: "1.25rem", fontWeight: 500, backgroundColor: { default: colors.primary, ":disabled": "oklch(87.1% 0.006 286.286)", [DARK]: { default: colors.primary, ":disabled": "oklch(27.4% 0.006 286.033)" }, }, color: { default: colors.primaryText, ":disabled": "oklch(55.2% 0.016 285.938)" }, }, }); function FieldLabel({ id, text, restart }: { id: string; text: string; restart: boolean }) { return ( ); } function FieldRow({ section, def, value, restart, onChange, }: { section: string; def: AnyFieldDef; value: unknown; restart: boolean; onChange: (value: unknown) => void; }) { const id = `${section}.${def.key}`; if (def.kind === "boolean") { return (