/** * WordPress dependencies */ import { useMemo, useState } from '@wordpress/element'; /** * Internal dependencies */ import DataForm from '../index'; import type { Field, Form, Layout, PanelLayout, EditVisibility, } from '../../types'; type SamplePost = { title: string; order: number; author: number; status: string; reviewer: string; date: string; birthdate: string; password?: string; filesize?: number; dimensions?: string; tags?: string[]; address1?: string; address2?: string; city?: string; comment_status?: string; ping_status?: boolean; longDescription?: string; origin?: string; destination?: string; flight_status?: string; gate?: string; seat?: string; }; const fields: Field< SamplePost >[] = [ { id: 'title', label: 'Title', type: 'text', }, { id: 'order', label: 'Order', type: 'integer', }, { id: 'date', label: 'Date', type: 'datetime', }, { id: 'birthdate', label: 'Date as options', type: 'datetime', elements: [ { value: '', label: 'Select a date' }, { value: '1970-02-23T12:00:00', label: "Jane's birth date" }, { value: '1950-02-23T12:00:00', label: "John's birth date" }, ], }, { id: 'author', label: 'Author', type: 'integer', elements: [ { value: 1, label: 'Jane' }, { value: 2, label: 'John' }, { value: 3, label: 'Alice' }, { value: 4, label: 'Bob' }, { value: 5, label: 'Superadministratoraccountwithalongunhyphenatedusername', }, ], setValue: ( { value } ) => ( { author: Number( value ), } ), }, { id: 'reviewer', label: 'Reviewer', type: 'text', Edit: 'radio', elements: [ { value: 'jane', label: 'Jane' }, { value: 'john', label: 'John' }, { value: 'alice', label: 'Alice' }, { value: 'bob', label: 'Bob' }, ], }, { id: 'status', label: 'Status', type: 'text', Edit: 'toggleGroup', elements: [ { value: 'draft', label: 'Draft' }, { value: 'published', label: 'Published' }, { value: 'private', label: 'Private' }, ], }, { id: 'email', label: 'Email', type: 'email', }, { id: 'password', label: 'Password', type: 'text', isVisible: ( item: SamplePost ) => { return item.status !== 'private'; }, }, { id: 'sticky', label: 'Sticky', type: 'boolean', }, { id: 'can_comment', label: 'Allow people to leave a comment', type: 'boolean', Edit: 'checkbox', }, { id: 'filesize', label: 'File Size', type: 'integer', readOnly: true, }, { id: 'dimensions', label: 'Dimensions', type: 'text', readOnly: true, }, { id: 'tags', label: 'Tags', type: 'array', placeholder: 'Enter comma-separated tags', description: 'Add tags separated by commas (e.g., "tag1, tag2, tag3")', elements: [ { value: 'astronomy', label: 'Astronomy' }, { value: 'book-review', label: 'Book review' }, { value: 'event', label: 'Event' }, { value: 'photography', label: 'Photography' }, { value: 'travel', label: 'Travel' }, ], }, { id: 'address1', label: 'Address 1', type: 'text', }, { id: 'address2', label: 'Address 2', type: 'text', }, { id: 'city', label: 'City', type: 'text', }, { id: 'description', label: 'Description', type: 'text', Edit: 'textarea', }, { id: 'longDescription', label: 'Long Description', type: 'text', Edit: { control: 'textarea', rows: 5, }, }, { id: 'comment_status', label: 'Comment Status', type: 'text', Edit: 'radio', elements: [ { value: 'open', label: 'Allow comments' }, { value: 'closed', label: 'Comments closed' }, ], }, { id: 'ping_status', label: 'Allow Pings/Trackbacks', type: 'boolean', }, { id: 'discussion', label: 'Discussion', type: 'text', render: ( { item } ) => { const commentLabel = item.comment_status === 'open' ? 'Allow comments' : 'Comments closed'; const pingLabel = item.ping_status ? 'Pings enabled' : 'Pings disabled'; return ( { commentLabel }, { pingLabel } ); }, }, { id: 'origin', label: 'Origin', type: 'text', }, { id: 'destination', label: 'Destination', type: 'text', }, { id: 'flight_status', label: 'Flight Status', type: 'text', Edit: 'radio', elements: [ { value: 'on-time', label: 'On Time' }, { value: 'delayed', label: 'Delayed' }, { value: 'cancelled', label: 'Cancelled' }, ], }, { id: 'gate', label: 'Gate', type: 'text', }, { id: 'seat', label: 'Seat', type: 'text', }, { id: 'metadata_summary', label: 'Metadata', type: 'text', render: ( { item } ) => { return ( <>Metadata { item.filesize ? `, ${ item.filesize } KB` : '' } ); }, }, ]; const getPanelLayoutFromStoryArgs = ( { summary, labelPosition, openAs, editVisibility, }: { summary?: string[]; labelPosition?: 'default' | 'top' | 'side' | 'none'; openAs?: PanelLayout[ 'openAs' ]; editVisibility?: 'default' | EditVisibility; } ): Layout | undefined => { const panelLayout: PanelLayout = { type: 'panel', }; if ( labelPosition !== 'default' ) { panelLayout.labelPosition = labelPosition; } if ( openAs ) { panelLayout.openAs = openAs; } if ( summary !== undefined ) { panelLayout.summary = summary; } if ( editVisibility !== 'default' ) { panelLayout.editVisibility = editVisibility; } return panelLayout; }; const LayoutPanelComponent = ( { labelPosition, openAs: openAsArg, editVisibility, applyLabel, cancelLabel, }: { type: 'default' | 'regular' | 'panel' | 'card'; labelPosition: 'default' | 'top' | 'side' | 'none'; openAs: 'default' | 'dropdown' | 'modal'; editVisibility: 'default' | EditVisibility; applyLabel?: string; cancelLabel?: string; } ) => { const [ post, setPost ] = useState< SamplePost >( { title: 'Hello, World!', order: 2, author: 5, status: 'draft', reviewer: 'fulano', date: '2021-01-01T12:00:00', birthdate: '1950-02-23T12:00:00', filesize: 1024, dimensions: '1920x1080', tags: [ 'photography' ], address1: '123 Main St', address2: 'Apt 4B', city: 'New York', comment_status: 'open', ping_status: true, origin: 'New York (JFK)', destination: 'Los Angeles (LAX)', flight_status: 'on-time', gate: 'A12', seat: '14F', } ); const form: Form = useMemo( () => { let openAs: PanelLayout[ 'openAs' ]; if ( openAsArg === 'modal' && ( applyLabel || cancelLabel ) ) { openAs = { type: 'modal', applyLabel: applyLabel || undefined, cancelLabel: cancelLabel || undefined, }; } else if ( openAsArg !== 'default' ) { openAs = openAsArg; } return { layout: getPanelLayoutFromStoryArgs( { labelPosition, openAs, editVisibility, } ), fields: [ 'title', { id: 'status', label: 'Status & Visibility', children: [ 'status', 'password' ], }, 'order', 'author', 'filesize', 'dimensions', 'tags', { id: 'discussion', label: 'Discussion', children: [ 'comment_status', 'ping_status' ], }, { id: 'address1', label: 'Combined Address', children: [ 'address1', 'address2', 'city' ], }, { id: 'flight_info', label: 'Flight Information', children: [ 'origin', 'destination', 'flight_status', 'gate', ], layout: getPanelLayoutFromStoryArgs( { summary: [ 'origin', 'destination', 'flight_status' ], labelPosition, openAs, editVisibility, } ), }, { id: 'passenger_details', label: 'Passenger Details', children: [ 'author', 'seat' ], layout: getPanelLayoutFromStoryArgs( { summary: [ 'author', 'seat' ], labelPosition, openAs, editVisibility, } ), }, ], }; }, [ labelPosition, openAsArg, applyLabel, cancelLabel, editVisibility ] ); return ( data={ post } fields={ fields } form={ form } onChange={ ( edits ) => setPost( ( prev ) => ( { ...prev, ...edits, } ) ) } /> ); }; export default LayoutPanelComponent;