import {useCallback, useState} from 'react'; import styled from '@emotion/styled'; import FieldFromConfig from 'sentry/components/forms/fieldFromConfig'; import {Panel, PanelBody, PanelHeader} from 'sentry/components/panels'; import {IconChevron} from 'sentry/icons'; import {Scope} from 'sentry/types'; import {sanitizeQuerySelector} from 'sentry/utils/sanitizeQuerySelector'; import {FieldObject, JsonFormObject} from './types'; type Props = { /** * List of fields to render */ fields: FieldObject[]; access?: Set; additionalFieldProps?: {[key: string]: any}; /** * Can the PanelBody be hidden with a click? */ collapsible?: boolean; /** * Disables the entire form */ disabled?: boolean; features?: Record; /** * The name of the field that should be highlighted */ highlighted?: string; /** * Renders inside of PanelBody before PanelBody close */ renderFooter?: (arg: JsonFormObject) => React.ReactNode; /** * Renders inside of PanelBody at the start */ renderHeader?: (arg: JsonFormObject) => React.ReactNode; /** * Panel title */ title?: React.ReactNode; }; function FormPanel({ additionalFieldProps = {}, title, fields, access, disabled, renderFooter, renderHeader, collapsible, ...otherProps }: Props) { const [collapsed, setCollapse] = useState(false); const handleCollapseToggle = useCallback(() => setCollapse(current => !current), []); return ( {title && ( {title} {collapsible && ( )} )} {!collapsed && ( {typeof renderHeader === 'function' && renderHeader({title, fields})} {fields.map(field => { if (typeof field === 'function') { return field(); } const {defaultValue: _, ...fieldWithoutDefaultValue} = field; // Allow the form panel disabled prop to override the fields // disabled prop, with fallback to the fields disabled state. if (disabled === true) { fieldWithoutDefaultValue.disabled = true; fieldWithoutDefaultValue.disabledReason = undefined; } return ( ); })} {typeof renderFooter === 'function' && renderFooter({title, fields})} )} ); } export default FormPanel; const Collapse = styled('span')` cursor: pointer; `;