/**
* WordPress dependencies
*/
import { useMemo, useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import DataForm from '../index';
import type {
CardLayout,
Field,
Form,
Layout,
PanelLayout,
RegularLayout,
} 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' },
],
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 getLayoutFromStoryArgs = ( {
type,
labelPosition,
openAs,
withHeader,
}: {
type: 'default' | 'regular' | 'panel' | 'card' | 'row';
labelPosition?: 'default' | 'top' | 'side' | 'none';
openAs?: 'default' | 'dropdown' | 'modal';
withHeader?: boolean;
} ): Layout | undefined => {
let layout: Layout | undefined;
if ( type === 'default' || type === 'regular' ) {
const regularLayout: RegularLayout = {
type: 'regular',
};
if ( labelPosition !== 'default' ) {
regularLayout.labelPosition = labelPosition;
}
layout = regularLayout;
} else if ( type === 'panel' ) {
const panelLayout: PanelLayout = {
type: 'panel',
};
if ( labelPosition !== 'default' ) {
panelLayout.labelPosition = labelPosition;
}
if ( openAs !== 'default' ) {
panelLayout.openAs = openAs;
}
layout = panelLayout;
} else if ( type === 'card' ) {
const cardLayout: CardLayout = {
type: 'card',
};
if ( withHeader !== undefined ) {
// @ts-ignore We want to demo the effects of configuring withHeader.
cardLayout.withHeader = withHeader;
}
layout = cardLayout;
}
return layout;
};
const LayoutRegularComponent = ( {
labelPosition,
}: {
labelPosition: 'default' | 'top' | 'side' | 'none';
} ) => {
const [ post, setPost ] = useState( {
title: 'Hello, World!',
order: 2,
author: 1,
status: 'draft',
reviewer: 'fulano',
email: 'hello@wordpress.org',
date: '2021-01-01T12:00:00',
birthdate: '1950-02-23T12:00:00',
sticky: false,
can_comment: false,
filesize: 1024,
dimensions: '1920x1080',
tags: [ 'photography' ],
description: 'This is a sample description.',
} );
const form: Form = useMemo(
() => ( {
layout: getLayoutFromStoryArgs( {
type: 'regular',
labelPosition,
} ),
fields: [
'title',
'order',
'sticky',
'author',
'status',
'reviewer',
'email',
'password',
'date',
'birthdate',
'can_comment',
'filesize',
'dimensions',
'tags',
'description',
'longDescription',
],
} ),
[ labelPosition ]
);
return (
data={ post }
fields={ fields }
form={ form }
onChange={ ( edits ) =>
setPost( ( prev ) => ( {
...prev,
...edits,
} ) )
}
/>
);
};
export default LayoutRegularComponent;