Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/dataviews/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Enhancements

- DataForm: add new details layout. [#72355](https://github.com/WordPress/gutenberg/pull/72355)
- DatViews list layout: remove link variant from primary actions's button. [#72920](https://github.com/WordPress/gutenberg/pull/72920)
- DataForm: simplify form normalization. [#72848](https://github.com/WordPress/gutenberg/pull/72848)
- DataViewsPicker: Add With Modal story. [#72913](https://github.com/WordPress/gutenberg/pull/72913)
Expand Down
71 changes: 71 additions & 0 deletions packages/dataviews/src/dataform-layouts/details/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* WordPress dependencies
*/
import { useContext, useMemo } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import type {
NormalizedForm,
NormalizedDetailsLayout,
FieldLayoutProps,
} from '../../types';
import DataFormContext from '../../components/dataform-context';
import { DataFormLayout } from '../data-form-layout';
import { DEFAULT_LAYOUT } from '../normalize-form';

export default function FormDetailsField< Item >( {
data,
field,
onChange,
}: FieldLayoutProps< Item > ) {
const { fields } = useContext( DataFormContext );

const form: NormalizedForm = useMemo(
() => ( {
layout: DEFAULT_LAYOUT,
fields: field.children ?? [],
} ),
[ field ]
);

if ( ! field.children ) {
return null;
}

// Find the summary field definition if specified
const summaryFieldId =
( field.layout as NormalizedDetailsLayout ).summary ?? '';
const summaryField = summaryFieldId
? fields.find( ( fieldDef ) => fieldDef.id === summaryFieldId )
: undefined;

// Render the summary content
let summaryContent;
if ( summaryField && summaryField.render ) {
// Use the field's render function to display the current value
summaryContent = (
<summaryField.render item={ data } field={ summaryField } />
);
} else {
// Fall back to the label
summaryContent = field.label || __( 'More details' );
}

return (
<details className="dataforms-layouts-details__details">
<summary className="dataforms-layouts-details__summary">
{ summaryContent }
</summary>
<div className="dataforms-layouts-details__content">
<DataFormLayout
data={ data }
form={ form }
onChange={ onChange }
/>
</div>
</details>
);
}
5 changes: 5 additions & 0 deletions packages/dataviews/src/dataform-layouts/details/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@use "@wordpress/base-styles/variables" as *;

.dataforms-layouts-details__content {
padding-top: $grid-unit-15;
}
5 changes: 5 additions & 0 deletions packages/dataviews/src/dataform-layouts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import FormRegularField from './regular';
import FormPanelField from './panel';
import FormCardField from './card';
import FormRowField from './row';
import FormDetailsField from './details';

const FORM_FIELD_LAYOUTS = [
{
Expand Down Expand Up @@ -67,6 +68,10 @@ const FORM_FIELD_LAYOUTS = [
</VStack>
),
},
{
type: 'details',
component: FormDetailsField,
},
];

export function getFormFieldLayout( type: string ) {
Expand Down
6 changes: 6 additions & 0 deletions packages/dataviews/src/dataform-layouts/normalize-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
NormalizedPanelLayout,
NormalizedCardLayout,
NormalizedRowLayout,
NormalizedDetailsLayout,
NormalizedCardSummaryField,
CardSummaryField,
} from '../types';
Expand Down Expand Up @@ -94,6 +95,11 @@ function normalizeLayout( layout?: Layout ): NormalizedLayout {
alignment: layout?.alignment ?? 'center',
styles: layout?.styles ?? {},
} satisfies NormalizedRowLayout;
} else if ( layout?.type === 'details' ) {
normalizedLayout = {
type: 'details',
summary: layout?.summary ?? '',
} satisfies NormalizedDetailsLayout;
}

return normalizedLayout;
Expand Down
84 changes: 84 additions & 0 deletions packages/dataviews/src/stories/dataform.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,19 @@ const fields: Field< SamplePost >[] = [
label: 'Seat',
type: 'text',
},
{
id: 'metadata_summary',
label: 'Metadata',
type: 'text',
render: ( { item } ) => {
return (
<span>
<>Metadata</>
{ item.filesize ? `, ${ item.filesize } KB` : '' }
</span>
);
},
},
];

const LayoutRegularComponent = ( {
Expand Down Expand Up @@ -1854,6 +1867,73 @@ const LayoutRowComponent = ( {
);
};

const LayoutDetailsComponent = () => {
const [ post, setPost ] = useState< SamplePost >( {
title: 'Hello, World!',
order: 2,
author: 1,
status: 'draft',
reviewer: 'fulano',
date: '2021-01-01T12:00:00',
birthdate: '1950-02-23T12:00:00',
filesize: 1024,
dimensions: '1920x1080',
comment_status: 'open',
ping_status: true,
tags: [ 'photography' ],
} );

const form: Form = {
fields: [
{
id: 'discussion',
label: 'Discussion',
children: [ 'comment_status', 'ping_status' ],
layout: {
type: 'details',
summary: 'discussion',
},
},
{
id: 'metadata',
label: 'Metadata',
children: [ 'filesize', 'dimensions' ],
layout: {
type: 'details',
summary: 'metadata_summary',
},
},
{
id: 'categorization',
label: 'Categorization',
children: [ 'tags', 'description' ],
layout: { type: 'details' },
},
{
id: 'scheduling',
children: [ 'date', 'birthdate' ],
layout: {
type: 'details',
},
},
],
};

return (
<DataForm< SamplePost >
data={ post }
fields={ fields }
form={ form }
onChange={ ( edits ) =>
setPost( ( prev ) => ( {
...prev,
...edits,
} ) )
}
/>
);
};

const LayoutMixedComponent = () => {
const [ post, setPost ] = useState< SamplePost >( {
title: 'Hello, World!',
Expand Down Expand Up @@ -1981,6 +2061,10 @@ export const LayoutRow = {
},
};

export const LayoutDetails = {
render: LayoutDetailsComponent,
};

export const LayoutMixed = {
render: LayoutMixedComponent,
};
Expand Down
1 change: 1 addition & 0 deletions packages/dataviews/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
@use "./dataform-layouts/panel/style.scss" as *;
@use "./dataform-layouts/regular/style.scss" as *;
@use "./dataform-layouts/card/style.scss" as *;
@use "./dataform-layouts/details/style.scss" as *;
@use "./dataform-layouts/row/style.scss" as *;
@use "./dataform-layouts/style.scss" as *;
21 changes: 18 additions & 3 deletions packages/dataviews/src/types/dataform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { Field, FieldValidity } from './field-api';
/**
* DataForm layouts.
*/
export type LayoutType = 'regular' | 'panel' | 'card' | 'row';
export type LayoutType = 'regular' | 'panel' | 'card' | 'row' | 'details';
export type LabelPosition = 'top' | 'side' | 'none';

export type PanelSummaryField = string | string[];
Expand Down Expand Up @@ -97,12 +97,27 @@ export type NormalizedRowLayout = {
styles: Record< string, { flex?: React.CSSProperties[ 'flex' ] } >;
};

export type Layout = RegularLayout | PanelLayout | CardLayout | RowLayout;
export type DetailsLayout = {
type: 'details';
summary?: string;
};
export type NormalizedDetailsLayout = {
type: 'details';
summary: string;
};

export type Layout =
| RegularLayout
| PanelLayout
| CardLayout
| RowLayout
| DetailsLayout;
export type NormalizedLayout =
| NormalizedRegularLayout
| NormalizedPanelLayout
| NormalizedCardLayout
| NormalizedRowLayout;
| NormalizedRowLayout
| NormalizedDetailsLayout;

export type NormalizedSummaryField =
| NormalizedPanelSummaryField
Expand Down
Loading