/**
* WordPress dependencies
*/
import {
__experimentalHeading as Heading,
__experimentalSpacer as Spacer,
Dropdown,
Button,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useMemo, useRef, useState } from '@wordpress/element';
import { closeSmall } from '@wordpress/icons';
import { __experimentalUseDialog as useDialog } from '@wordpress/compose';
import { Stack } from '@wordpress/ui';
/**
* Internal dependencies
*/
import type {
FieldLayoutProps,
NormalizedForm,
FormValidity,
} from '../../../types';
import { DataFormLayout } from '../data-form-layout';
import { DEFAULT_LAYOUT } from '../normalize-form';
import SummaryButton from './summary-button';
import useReportValidity from '../../../hooks/use-report-validity';
import useFieldFromFormField from './utils/use-field-from-form-field';
function DropdownHeader( {
title,
onClose,
}: {
title?: string;
onClose: () => void;
} ) {
return (
{ title && (
{ title }
) }
{ onClose && (
) }
);
}
function DropdownContentWithValidation( {
touched,
children,
}: {
touched: boolean;
children: React.ReactNode;
} ) {
const ref = useRef< HTMLDivElement >( null );
useReportValidity( ref, touched );
return
{ children }
;
}
function PanelDropdown< Item >( {
data,
field,
onChange,
validity,
}: FieldLayoutProps< Item > ) {
const [ touched, setTouched ] = useState( false );
// Use internal state instead of a ref to make sure that the component
// re-renders when the popover's anchor updates.
const [ popoverAnchor, setPopoverAnchor ] = useState< HTMLElement | null >(
null
);
// Memoize popoverProps to avoid returning a new object every time.
const popoverProps = useMemo(
() => ( {
// Anchor the popover to the middle of the entire row so that it doesn't
// move around when the label changes.
anchor: popoverAnchor,
placement: 'left-start',
offset: 36,
shift: true,
} ),
[ popoverAnchor ]
);
const [ dialogRef, dialogProps ] = useDialog( {
focusOnMount: 'firstInputElement',
} );
const form: NormalizedForm = useMemo(
() => ( {
layout: DEFAULT_LAYOUT,
fields: !! field.children
? field.children
: // If not explicit children return the field id itself.
[ { id: field.id, layout: DEFAULT_LAYOUT } ],
} ),
[ field ]
);
const formValidity = useMemo( (): FormValidity => {
if ( validity === undefined ) {
return undefined;
}
if ( !! field.children ) {
return validity?.children;
}
return { [ field.id ]: validity };
}, [ validity, field ] );
const { fieldDefinition, fieldLabel, summaryFields } =
useFieldFromFormField( field );
if ( ! fieldDefinition ) {
return null;
}
return (
{
if ( ! willOpen ) {
setTouched( true );
}
} }
renderToggle={ ( { isOpen, onToggle } ) => (
) }
renderContent={ ( { onClose } ) => (
{ (
FieldLayout,
childField,
childFieldValidity,
markWhenOptional
) => (
) }
) }
/>
);
}
export default PanelDropdown;