// Bespoke primitives that mirror prototype/src/primitives.jsx exactly so
// screens like UserDetail keep pixel-level fidelity to the prototype rather
// than picking up AntD's default chrome.
import React from "react";
const fieldStyles = {
label: {
width: 88,
flex: "none" as const,
textAlign: "right" as const,
paddingRight: 8,
color: "var(--text)",
fontSize: 12,
lineHeight: "26px",
whiteSpace: "nowrap" as const,
overflow: "hidden" as const,
textOverflow: "ellipsis" as const,
},
control: {
flex: 1,
minWidth: 0,
height: "var(--input-h)",
border: "1px solid var(--border-input)",
background: "var(--bg-input)",
padding: "0 6px",
fontSize: 12,
color: "var(--text)",
borderRadius: 0,
outline: "none",
fontFamily: "inherit",
},
controlDisabled: { background: "var(--bg-disabled)", color: "var(--text-muted)" },
controlReq: { background: "#d4e8f7" }, // light cyan tint matching prototype screenshots
};
interface FieldProps {
label: string;
required?: boolean;
children: React.ReactNode;
labelWidth?: number;
}
export function Field({ label, required, children, labelWidth }: FieldProps) {
return (
{required ? * : null}
{label}:
{children}
);
}
interface InputProps {
value: string;
onChange?: (v: string) => void;
disabled?: boolean;
required?: boolean;
placeholder?: string;
mono?: boolean;
}
export function PrimInput({ value, onChange, disabled, required, placeholder, mono }: InputProps) {
return (
onChange(e.target.value) : undefined}
disabled={disabled}
placeholder={placeholder}
style={{
...fieldStyles.control,
...(disabled ? fieldStyles.controlDisabled : {}),
...(required && !disabled ? fieldStyles.controlReq : {}),
...(mono
? { fontFamily: '"JetBrains Mono", Menlo, Consolas, monospace', fontSize: 11 }
: {}),
}}
/>
);
}
interface SelectOption {
value: string;
label: string;
}
interface SelectProps {
value: string;
onChange?: (v: string) => void;
disabled?: boolean;
required?: boolean;
options: (string | SelectOption)[];
allowEmpty?: boolean;
}
export function PrimSelect({
value,
onChange,
disabled,
required,
options,
allowEmpty = true,
}: SelectProps) {
return (
▼
);
}
interface CheckboxProps {
checked: boolean;
onChange?: (v: boolean) => void;
disabled?: boolean;
label?: string;
size?: number;
}
export function PrimCheckbox({ checked, onChange, disabled, label, size = 13 }: CheckboxProps) {
return (
);
}
interface ToolbarBtnDarkProps {
children: React.ReactNode;
icon?: React.ReactNode;
onClick?: () => void;
disabled?: boolean;
danger?: boolean;
}
export function ToolbarBtnDark({
children,
icon,
onClick,
disabled,
danger,
}: ToolbarBtnDarkProps) {
const [hover, setHover] = React.useState(false);
return (
);
}
interface ToolbarBtnLightProps {
children: React.ReactNode;
icon?: React.ReactNode;
onClick?: () => void;
disabled?: boolean;
primary?: boolean;
danger?: boolean;
success?: boolean;
}
export function ToolbarBtnLight({
children,
icon,
onClick,
disabled,
primary,
danger,
success,
}: ToolbarBtnLightProps) {
const [hover, setHover] = React.useState(false);
let bg = "#fff",
border = "var(--border-input)",
color = "var(--text)";
if (primary) {
bg = hover ? "#3a9ae8" : "#5cabe8";
border = "#3a8ad6";
color = "#fff";
} else if (danger) {
bg = hover ? "#e85a5a" : "#f07070";
border = "#d04141";
color = "#fff";
} else if (success) {
bg = hover ? "#38b777" : "#4cc488";
border = "#27a567";
color = "#fff";
} else if (hover && !disabled) {
bg = "var(--accent-soft)";
border = "var(--accent)";
}
return (
);
}