'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * Top-level admin field for component-aware blocks. Consumes a
 * {@link Manifest} produced by `@actuate-media/component-blocks`,
 * renders a component picker (when more than one component is allowed)
 * and a recursive props form via {@link PropInput}.
 *
 * Storage shape:
 *   { component: 'Hero', props: { title: 'Welcome', alignment: 'center' } }
 *
 * Live validation runs through `validateComponentBlockValue` from
 * `@actuate-media/cms-core`. The whole-value error is shown at the top
 * of the form, and the per-prop error map (parsed out of the message
 * string) is forwarded into `PropInput` so each input can render its
 * own inline error.
 */
import { useEffect, useMemo, useRef, useState } from 'react';
import { buildClientValidator, getAllowedComponents, parsePerPropErrors, seedPropsForComponent, } from './component-block-helpers.js';
import { PropInput } from './PropInput.js';
export function ComponentBlockField({ label, manifest, allow, defaultComponent, value, onChange, validate, helpText, }) {
    const allowedComponents = useMemo(() => getAllowedComponents(manifest, allow), [manifest, allow]);
    // Track the initial seed application so we don't repeatedly stomp
    // the editor's prop values on every render. The defaultComponent
    // seed only fires once, when value is undefined on mount.
    const seededRef = useRef(false);
    useEffect(() => {
        if (seededRef.current)
            return;
        if (value) {
            seededRef.current = true;
            return;
        }
        const picked = allowedComponents.find((c) => c.name === defaultComponent) ?? allowedComponents[0];
        if (!picked)
            return;
        seededRef.current = true;
        onChange({ component: picked.name, props: seedPropsForComponent(picked) });
    }, [allowedComponents, defaultComponent, value, onChange]);
    const currentSpec = (value && manifest.components.find((c) => c.name === value.component)) ?? allowedComponents[0];
    // Pure structural validation when caller didn't provide their own.
    // Keeps the form usable even without a live validator wired in.
    const builtinValidate = useMemo(() => buildClientValidator(manifest, allow), [manifest, allow]);
    const validator = validate ?? builtinValidate;
    const [errorMessage, setErrorMessage] = useState(null);
    const perPropErrors = useMemo(() => parsePerPropErrors(errorMessage), [errorMessage]);
    useEffect(() => {
        if (!value) {
            setErrorMessage(null);
            return;
        }
        const result = validator(value);
        setErrorMessage(result === true ? null : result);
    }, [value, validator]);
    function handleComponentChange(componentName) {
        const spec = manifest.components.find((c) => c.name === componentName);
        if (!spec)
            return;
        onChange({ component: spec.name, props: seedPropsForComponent(spec) });
    }
    function handlePropChange(propName, next) {
        if (!value)
            return;
        onChange({
            ...value,
            props: { ...value.props, [propName]: next },
        });
    }
    if (!currentSpec) {
        return (_jsx("div", { className: "rounded-md border border-[var(--destructive)] bg-red-50 p-3 text-sm text-[var(--destructive)]", children: "Component block has no components to choose from." }));
    }
    return (_jsxs("div", { className: "space-y-3", children: [label ? _jsx("label", { className: "block text-sm font-medium", children: label }) : null, allowedComponents.length > 1 ? (_jsxs("label", { className: "block text-sm", children: [_jsx("div", { className: "mb-1 text-xs tracking-wide text-[var(--muted-foreground)] uppercase", children: "Component" }), _jsx("select", { value: currentSpec.name, onChange: (e) => handleComponentChange(e.target.value), className: "w-full rounded-md border border-[var(--border)] bg-[var(--input-background)] px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-[var(--ring)]", children: allowedComponents.map((spec) => (_jsx("option", { value: spec.name, children: spec.displayName }, spec.name))) })] })) : null, errorMessage ? (_jsx("div", { className: "rounded-md border border-[var(--destructive)] bg-red-50 px-3 py-2 text-xs text-[var(--destructive)]", children: errorMessage })) : null, _jsxs("fieldset", { className: "rounded-md border border-[var(--border)] bg-[var(--card)] p-4", children: [_jsx("legend", { className: "px-1 text-xs tracking-wide text-[var(--muted-foreground)] uppercase", children: currentSpec.displayName }), currentSpec.description ? (_jsx("p", { className: "mb-3 text-xs text-[var(--muted-foreground)]", children: currentSpec.description })) : null, _jsx("div", { className: "space-y-4", children: currentSpec.props.map((prop) => (_jsx(PropInput, { prop: prop, value: value?.props?.[prop.name], onChange: (next) => handlePropChange(prop.name, next), errors: perPropErrors, path: prop.name }, prop.name))) })] }), helpText ? _jsx("p", { className: "text-xs text-[var(--muted-foreground)]", children: helpText }) : null] }));
}
//# sourceMappingURL=ComponentBlockField.js.map