import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { forwardRef, useRef, useEffect } from 'react';
import styled, { css } from 'styled-components';
import { useAfterInitialEffect, useUID, useI18n, usePrevious, useBreakpoint, useTheme, useConsolidatedRef, useConfiguration } from '../../hooks';
import { focusNonInteractiveElement, isInstance } from '../../utils';
import { calculateFontSize } from '../../styles';
import Text from '../Text';
import HTML from '../HTML';
import VisuallyHiddenText from '../VisuallyHiddenText';
import Grid, { StyledGrid } from '../Grid';
import { defaultThemeProp } from '../../theme';
import Progress from '../Progress';
import ResponsiveActions from '../ResponsiveActions';
import VerticalFormProgress from './VerticalFormProgress';
import HorizontalFormProgress from './HorizontalFormProgress';
export const StyledForm = styled.form(({ actions, heading, theme }) => {
    return css `
      & > ${StyledGrid} {
        position: relative;

        ${actions &&
        css `
          padding-block-end: calc(2 * ${theme.base.spacing});
        `}

        ${heading &&
        css `
          padding-block-start: calc(2 * ${theme.base.spacing});
        `}
      }

      &:focus-visible {
        outline: none;
        box-shadow: ${theme.base.shadow.focus};
      }
    `;
});
StyledForm.defaultProps = defaultThemeProp;
export const StyledFormContent = styled.div ``;
export const StyledInstructionText = styled(Grid) `
  /* Prevent instruction text from contributing to modal width calculation */
  width: 0;
  min-width: 100%;
`;
export const StyledRequiredFieldLegend = styled(Text)(({ theme }) => {
    const { base: { 'font-size': fontSize, 'font-scale': fontScale, palette: { urgent } } } = theme;
    const { xxs: infoFontSize } = calculateFontSize(fontSize, fontScale);
    return css `
    font-size: ${infoFontSize};
    font-style: italic;

    &::before {
      display: 'inline';
      content: '\\00a0*';
      vertical-align: top;
      color: ${urgent};
    }
  `;
});
StyledRequiredFieldLegend.defaultProps = defaultThemeProp;
const MultiStepForm = forwardRef(function MultiStepForm({ currentStepId, steps, heading, stepIndicator: stepIndicatorProp, progress, ...restProps }, ref) {
    const multiStepRef = useConsolidatedRef(ref);
    const headingRef = useRef(null);
    const progressIndicatorRef = useRef(null);
    const multiStepFormContentRef = useRef(null);
    const multiStepActionsRef = useRef(null);
    const { loadedRef } = useConfiguration();
    const previousId = usePrevious(currentStepId);
    const currentStep = steps.find(step => step.id === currentStepId);
    const headingId = useUID();
    const descriptionId = useUID();
    const t = useI18n();
    const { base: { 'content-width': contentWidth } } = useTheme();
    const isSmallOrAbove = useBreakpoint('sm');
    const stepIndicator = (() => {
        if (stepIndicatorProp === 'none' || steps.length < 2)
            return 'none';
        if (!isSmallOrAbove)
            return 'horizontal';
        return stepIndicatorProp ?? 'horizontal';
    })();
    const setFocus = () => {
        if (!loadedRef.current) {
            loadedRef.current = true;
            return;
        }
        if (progress)
            return;
        if (stepIndicator !== 'none' && progressIndicatorRef.current) {
            const focusables = [
                ...progressIndicatorRef.current.querySelectorAll(`[id="${currentStepId}"]`)
            ];
            focusables[0]?.focus();
        }
        else if (headingRef.current) {
            focusNonInteractiveElement(headingRef.current);
        }
        else if (multiStepRef.current) {
            const containerEl = multiStepRef.current.closest('[data-focusable-form-container]');
            const headingEl = containerEl?.querySelector('[data-focusable-form-heading]');
            if (isInstance(headingEl, HTMLElement)) {
                focusNonInteractiveElement(headingEl);
            }
            else {
                let label;
                if (heading && currentStep.name) {
                    label = `${heading} - ${currentStep.name}`;
                }
                else if (currentStep.name) {
                    label = currentStep.name;
                }
                else if (heading) {
                    label = heading;
                }
                focusNonInteractiveElement(multiStepRef.current, label);
            }
        }
    };
    // Set focus if the current step id updates
    useEffect(() => {
        if (previousId !== currentStepId) {
            setFocus();
        }
    }, [currentStepId, previousId]);
    // Set focus if the form content updates while focus is within the actions region of the form
    useAfterInitialEffect(() => {
        if (multiStepActionsRef.current &&
            multiStepActionsRef.current.contains(document.activeElement)) {
            setFocus();
        }
    }, [currentStep.content]);
    // Set focus if a progress state resolves
    useAfterInitialEffect(() => {
        if (!progress) {
            setFocus();
        }
    }, [progress]);
    let areaDef = '';
    let colDef = '';
    switch (stepIndicator) {
        case 'horizontal':
            areaDef += '"stepIndicator" ';
            if (currentStep.banners)
                areaDef += '"banners" ';
            if (currentStep.description)
                areaDef += '"description" ';
            areaDef += '"content"';
            colDef = 'minmax(0, 1fr)';
            break;
        case 'vertical':
            if (currentStep.banners)
                areaDef += '"banners stepIndicator" ';
            if (currentStep.description)
                areaDef += '"description stepIndicator" ';
            areaDef += '"content stepIndicator"';
            colDef = `2fr minmax(${contentWidth.xs}, 1fr)`;
            break;
        case 'vertical-start':
            if (currentStep.banners)
                areaDef += '"stepIndicator banners" ';
            if (currentStep.description)
                areaDef += '"stepIndicator description" ';
            areaDef += '"stepIndicator content"';
            colDef = 'fit-content(clamp(10ch, calc(100% / 3), 40ch)) 2fr';
            break;
        default:
            if (currentStep.banners)
                areaDef += '"banners" ';
            if (currentStep.description)
                areaDef += '"description" ';
            areaDef += '"content"';
            colDef = 'minmax(0, 1fr)';
    }
    return (_jsxs(StyledForm, { ref: multiStepRef, ...restProps, "aria-labelledby": heading ? headingId : undefined, "aria-describedby": currentStep.description ? descriptionId : undefined, heading: !!heading, actions: !!currentStep.actions, children: [heading && (_jsx(Text, { ref: headingRef, id: headingId, variant: 'h3', children: heading })), _jsxs(Grid, { container: {
                    cols: colDef,
                    areas: areaDef,
                    rowGap: 2,
                    colGap: stepIndicator.startsWith('vertical') ? 4 : 2
                }, inert: progress ? '' : undefined, children: [steps.length > 1 && (_jsxs(Grid, { ref: progressIndicatorRef, item: { area: 'stepIndicator' }, children: [stepIndicator === 'horizontal' && (_jsx(Grid, { item: { area: 'stepIndicator' }, as: HorizontalFormProgress, steps: steps, currentStepId: currentStepId })), stepIndicator.startsWith('vertical') && (_jsx(Grid, { item: { area: 'stepIndicator' }, as: VerticalFormProgress, steps: steps, currentStepId: currentStepId })), _jsx(VisuallyHiddenText, { "aria-live": 'polite', children: previousId !== undefined && previousId !== currentStepId
                                    ? t('step_changed_to_name', [currentStep.name])
                                    : '' })] })), currentStep.banners && _jsx(Grid, { item: { area: 'banners' }, children: currentStep.banners }), currentStep.description && (_jsx(StyledInstructionText, { item: { area: 'description' }, children: _jsx(HTML, { id: descriptionId, as: 'p', content: currentStep.description }) })), _jsx(Grid, { item: { area: 'content' }, as: StyledFormContent, ref: multiStepFormContentRef, children: currentStep.content }), _jsx(Progress, { visible: !!progress, focusOnVisible: true, placement: 'local', message: typeof progress === 'string' ? progress : undefined })] }), currentStep.actions && (_jsx(ResponsiveActions, { actionsRef: multiStepActionsRef, actionsEl: currentStep.actions }))] }));
});
export default MultiStepForm;
//# sourceMappingURL=MultiStepForm.js.map