import React from "react";
import { HighlightableField } from "../components/HighlightableField";
import { RangeSlider } from "../components/RangeSlider";
import { Toggle } from "../components/Toggle";
import {
LayoutPreviewIcon,
SelectorStylePreviewIcon,
ShapePreviewIcon,
} from "../components/swatchPreviewIcons";
import { ChoiceGroup, ChoiceOption } from "../components/ChoiceGroup";
import { coerceInt } from "../constants";
import {
EXTENSION_LAYOUT_ALLOWED_STYLES,
EXTENSION_LAYOUT_SHOWS_SHAPE,
} from "./presentationConstants";
import type { BaseTabProps } from "../tabs/types";
import type {
ExtensionLayout as Layout,
ExtensionSelectorStyle as SelectorStyle,
ExtensionShape as Shape,
} from "./presentationTypes";
type GeneralExtrasSection = "layout" | "size" | "options";
// Mobile layout cards (no Flow — Flow is desktop-only).
const MOBILE_LAYOUT_OPTIONS = [
{ value: "wrap", label: "Wrap", desc: "Wraps to new lines" },
{ value: "grid", label: "Grid", desc: "Fixed columns" },
{ value: "pill", label: "Pill", desc: "Connected pills" },
{ value: "slider", label: "Slider", desc: "Slide selector" },
] as const;
// Selector styles available for mobile overrides.
export const SELECTOR_STYLE_OPTIONS = [
{ value: "underline", label: "Underline", desc: "Line below selected" },
{ value: "outline", label: "Outline", desc: "Border ring on selected" },
{ value: "background", label: "Background", desc: "Highlight selected" },
] as const;
// Mobile shape cards (icon + label only — no description, tighter padding).
const MOBILE_SHAPE_OPTIONS = [
{ value: "square", label: "Square" },
{ value: "soft", label: "Soft" },
{ value: "rounded", label: "Rounded" },
{ value: "squircle", label: "Squircle" },
{ value: "circle", label: "Circle" },
{ value: "diamond", label: "Diamond" },
{ value: "hexagon", label: "Hexagon" },
] as const;
interface GeneralExtrasSlotProps extends BaseTabProps {
slot: GeneralExtrasSection;
showToast: (payload: {
type: "success" | "error" | "info";
message: string;
durationMs?: number;
}) => void;
}
export function GeneralTabExtras({
slot,
settings,
setSettings,
showToast,
}: GeneralExtrasSlotProps): React.ReactElement | null {
const extensionSettings = settings as typeof settings & {
layout?: Layout;
swatch_style?: SelectorStyle;
shape?: Shape;
mobile_layout?: Layout | "wrap" | "grid" | "pill" | "slider";
mobile_swatch_style?: SelectorStyle | "";
mobile_shape?: Shape;
};
const swatchWidth = coerceInt(extensionSettings.swatch_width, 32);
const swatchHeight = coerceInt(extensionSettings.swatch_height, 32);
const layout = (extensionSettings.layout || "wrap") as Layout;
const storedStyle = (extensionSettings.swatch_style ||
"underline") as SelectorStyle;
const mobileLayout = (extensionSettings.mobile_layout || "wrap") as
Layout | "wrap";
const mobileAllowedStyles = (EXTENSION_LAYOUT_ALLOWED_STYLES[
mobileLayout
] || ["underline"]) as SelectorStyle[];
const showMobileSelectorStyle =
mobileAllowedStyles.length > 0 && mobileLayout !== "slider";
const mobileSelectorCandidate = (extensionSettings.mobile_swatch_style ||
storedStyle ||
"underline") as SelectorStyle;
const mobileSelectorStyle: SelectorStyle = mobileAllowedStyles.includes(
mobileSelectorCandidate,
)
? mobileSelectorCandidate
: mobileAllowedStyles[0] || "underline";
const currentMobileShape = (extensionSettings.mobile_shape ||
"square") as Shape;
const buttonCustomSizing = !!extensionSettings.button_custom_sizing;
const buttonSwatchWidth = coerceInt(
extensionSettings.button_swatch_width ?? swatchWidth,
swatchWidth,
);
const buttonSwatchHeight = coerceInt(
extensionSettings.button_swatch_height ?? swatchHeight,
swatchHeight,
);
if (slot === "layout") {
// Derive each dynamic radiogroup's rendered option set ONCE, so the
// `optionValues` passed to ChoiceGroup and the `ChoiceOption` children
// mapped below always match exactly (roving/Arrow order stays correct).
const mobileSelectorOptions = SELECTOR_STYLE_OPTIONS.filter((o) =>
mobileAllowedStyles.includes(o.value),
);
const mobileShapeOptions = MOBILE_SHAPE_OPTIONS.filter((shapeOption) => {
if (
mobileLayout === "slider" &&
(shapeOption.value === "diamond" || shapeOption.value === "hexagon")
) {
return false;
}
return true;
});
return (
<>
{layout === "slider" ? (