feat: converts rowHeader to collapsibleLabel, extends data passed to functions/components

This commit is contained in:
Jarrod Flesch
2022-11-15 01:53:09 -05:00
parent e4f2be3dec
commit 13ec1e0398
12 changed files with 79 additions and 95 deletions

View File

@@ -0,0 +1,23 @@
import React from 'react';
import { Props } from './types';
import { useWatchForm } from '../Form/context';
export const CollapsibleLabel: React.FC<Props> = (props) => {
const {
path,
fallback,
label,
rowNumber,
} = props;
const { getDataByPath, getSiblingData, getData } = useWatchForm();
const formData = getData();
const collapsibleData = getDataByPath(path) || getSiblingData(path);
return (
<React.Fragment>
{(typeof label === 'function')
? label({ collapsibleData, index: rowNumber, formData, fallback })
: (label || fallback)}
</React.Fragment>
);
};

View File

@@ -0,0 +1,16 @@
import React from 'react';
import { Data } from '../Form/types';
export type CollapsibleHeader = (props: {
formData: Data,
collapsibleData: Data,
index?: number,
fallback: string,
}) => React.ReactNode;
export type Props = {
fallback: string;
path: string;
header?: CollapsibleHeader;
rowNumber?: number;
}

View File

@@ -1,40 +0,0 @@
import React, { Fragment } from 'react';
import { Props } from './types';
import { useWatchForm } from '../Form/context';
const RowHeader: React.FC<Props> = (props) => {
const {
path,
fallback,
header,
rowNumber,
} = props;
const { getSiblingData } = useWatchForm();
const siblingData = getSiblingData(`${path}`);
/* if (isComponent(header)) {
const Header = header;
return (
<Header
value={siblingData}
index={rowNumber}
/>
);
} */
if (header) {
return (
<Fragment>
{
typeof header === 'function'
? header({ value: siblingData, index: rowNumber })
: header
}
</Fragment>
);
}
return <Fragment>{fallback}</Fragment>;
};
export default RowHeader;

View File

@@ -1,13 +0,0 @@
import React from 'react';
import { Data } from '../Form/types';
export type RowHeaderComponent = (props: {value: Data, index?: number}) => React.ReactNode;
export type RowHeader = string | RowHeaderComponent;
export type Props = {
fallback: string | React.ReactElement;
path: string;
header?: RowHeader;
rowNumber?: number;
}

View File

@@ -22,9 +22,9 @@ import { usePreferences } from '../../../utilities/Preferences';
import { ArrayAction } from '../../../elements/ArrayAction'; import { ArrayAction } from '../../../elements/ArrayAction';
import { scrollToID } from '../../../../utilities/scrollToID'; import { scrollToID } from '../../../../utilities/scrollToID';
import HiddenInput from '../HiddenInput'; import HiddenInput from '../HiddenInput';
import { CollapsibleLabel } from '../../CollapsibleLabel';
import './index.scss'; import './index.scss';
import RowHeader from '../../RowHeader';
const baseClass = 'array-field'; const baseClass = 'array-field';
@@ -49,7 +49,7 @@ const ArrayFieldType: React.FC<Props> = (props) => {
}, },
} = props; } = props;
const RowHeaderFromProps = components?.RowHeader || undefined; const CollapsibleLabelFromProps = components?.CollapsibleLabel || undefined;
const path = pathFromProps || name; const path = pathFromProps || name;
@@ -287,10 +287,10 @@ const ArrayFieldType: React.FC<Props> = (props) => {
key={row.id} key={row.id}
dragHandleProps={providedDrag.dragHandleProps} dragHandleProps={providedDrag.dragHandleProps}
header={( header={(
<RowHeader <CollapsibleLabel
path={`${path}.${i}.0`} path={`${path}.${i}`}
header={RowHeaderFromProps} label={CollapsibleLabelFromProps}
fallback={`${labels.singular} ${rowNumber >= 10 ? rowNumber : `0${rowNumber}`}`} fallback={`${labels.singular} ${String(rowNumber).padStart(2, '0')}`}
rowNumber={rowNumber} rowNumber={rowNumber}
/> />
)} )}

View File

@@ -9,7 +9,7 @@ import { DocumentPreferences } from '../../../../../preferences/types';
import { useDocumentInfo } from '../../../utilities/DocumentInfo'; import { useDocumentInfo } from '../../../utilities/DocumentInfo';
import FieldDescription from '../../FieldDescription'; import FieldDescription from '../../FieldDescription';
import { getFieldPath } from '../getFieldPath'; import { getFieldPath } from '../getFieldPath';
import RowHeader from '../../RowHeader'; import { CollapsibleLabel } from '../../CollapsibleLabel';
import './index.scss'; import './index.scss';
@@ -31,7 +31,7 @@ const CollapsibleField: React.FC<Props> = (props) => {
}, },
} = props; } = props;
const RowHeaderFromProps = components?.RowHeader || undefined; const CollapsibleLabelFromProps = components?.CollapsibleLabel || undefined;
const { getPreference, setPreference } = usePreferences(); const { getPreference, setPreference } = usePreferences();
const { preferencesKey } = useDocumentInfo(); const { preferencesKey } = useDocumentInfo();
@@ -74,10 +74,10 @@ const CollapsibleField: React.FC<Props> = (props) => {
className, className,
].filter(Boolean).join(' ')} ].filter(Boolean).join(' ')}
header={( header={(
<RowHeader <CollapsibleLabel
path={path} path={path}
fallback={<div className={`${baseClass}__label`}>{label}</div>} fallback={label}
header={RowHeaderFromProps} label={CollapsibleLabelFromProps}
/> />
)} )}
onToggle={onToggle} onToggle={onToggle}

View File

@@ -186,7 +186,7 @@ export const collapsible = baseField.keys({
fields: joi.array().items(joi.link('#field')), fields: joi.array().items(joi.link('#field')),
admin: baseAdminFields.keys({ admin: baseAdminFields.keys({
components: joi.object().keys({ components: joi.object().keys({
RowHeader: componentSchema, CollapsibleLabel: componentSchema,
}).default({}), }).default({}),
}).default({}), }).default({}),
}); });
@@ -242,7 +242,7 @@ export const array = baseField.keys({
), ),
admin: baseAdminFields.keys({ admin: baseAdminFields.keys({
components: joi.object().keys({ components: joi.object().keys({
RowHeader: componentSchema, CollapsibleLabel: componentSchema,
}).default({}), }).default({}),
}).default({}), }).default({}),
}); });

View File

@@ -8,7 +8,7 @@ import { ConditionalDateProps } from '../../admin/components/elements/DatePicker
import { Description } from '../../admin/components/forms/FieldDescription/types'; import { Description } from '../../admin/components/forms/FieldDescription/types';
import { User } from '../../auth'; import { User } from '../../auth';
import { Payload } from '../..'; import { Payload } from '../..';
import { RowHeader } from '../../admin/components/forms/RowHeader/types'; import { CollapsibleLabel } from '../../admin/components/forms/CollapsibleLabel/types';
export type FieldHookArgs<T extends TypeWithID = any, P = any, S = any> = { export type FieldHookArgs<T extends TypeWithID = any, P = any, S = any> = {
/** The data passed to update the document within create and update operations, and the full document itself in the afterRead hook. */ /** The data passed to update the document within create and update operations, and the full document itself in the afterRead hook. */
@@ -193,7 +193,7 @@ export type CollapsibleField = Omit<FieldBase, 'name'> & {
admin?: Admin & { admin?: Admin & {
initCollapsed?: boolean | false; initCollapsed?: boolean | false;
components?: { components?: {
RowHeader?: RowHeader CollapsibleLabel?: CollapsibleLabel
} }
} }
} }
@@ -342,7 +342,7 @@ export type ArrayField = FieldBase & {
admin?: Admin & { admin?: Admin & {
initCollapsed?: boolean | false; initCollapsed?: boolean | false;
components?: { components?: {
RowHeader?: RowHeader CollapsibleLabel?: CollapsibleLabel
} }
}; };
}; };

View File

@@ -1,9 +1,7 @@
import React from 'react'; import React from 'react';
import { RowHeaderComponent } from '../../../../src/admin/components/forms/RowHeader/types'; import { CollapsibleLabel } from '../../../../src/admin/components/forms/CollapsibleLabel/types';
const ArrayRowHeader: RowHeaderComponent = (props) => { export const ArrayCollapsibleLabel: CollapsibleLabel = (props) => {
const { value, index } = props; const { collapsibleData, fallback } = props;
return <React.Fragment>{value.title || `array_${index}`}</React.Fragment>; return <span style={{ color: 'hotpink' }}>{collapsibleData.title || fallback}</span>;
}; };
export default ArrayRowHeader;

View File

@@ -1,6 +1,5 @@
import { RowHeaderFunction } from '../../../../src/admin/components/forms/RowHeader/types';
import type { CollectionConfig } from '../../../../src/collections/config/types'; import type { CollectionConfig } from '../../../../src/collections/config/types';
import HeaderComponent from './HeaderComponent'; import { ArrayCollapsibleLabel } from './HeaderComponent';
export const arrayDefaultValue = [ export const arrayDefaultValue = [
{ text: 'row one' }, { text: 'row one' },
@@ -86,7 +85,7 @@ const ArrayFields: CollectionConfig = {
}, },
{ {
type: 'array', type: 'array',
name: 'arrayWithRowHeaderFunction', name: 'collapsibleLabelAsFunction',
fields: [ fields: [
{ {
name: 'title', name: 'title',
@@ -94,14 +93,15 @@ const ArrayFields: CollectionConfig = {
}, },
], ],
admin: { admin: {
description: 'Collapsible labels rendered from a function.',
components: { components: {
RowHeader: ({ value, index }) => value.title || `item ${index}`, CollapsibleLabel: ({ collapsibleData, fallback }) => collapsibleData.title || fallback,
}, },
}, },
}, },
{ {
type: 'array', type: 'array',
name: 'arrayWithRowHeaderComponent', name: 'rowHeaderAsComponent',
fields: [ fields: [
{ {
name: 'title', name: 'title',
@@ -109,8 +109,9 @@ const ArrayFields: CollectionConfig = {
}, },
], ],
admin: { admin: {
description: 'Collapsible labels rendered as components.',
components: { components: {
RowHeader: HeaderComponent, CollapsibleLabel: ArrayCollapsibleLabel,
}, },
}, },
}, },

View File

@@ -1,9 +1,7 @@
import React from 'react'; import React from 'react';
import { RowHeaderComponent } from '../../../../src/admin/components/forms/RowHeader/types'; import { CollapsibleLabel } from '../../../../src/admin/components/forms/CollapsibleLabel/types';
const ArrayRowHeader: RowHeaderComponent = (props) => { export const CollapsibleLabelComponent: CollapsibleLabel = (props) => {
const { value } = props; const { collapsibleData, fallback } = props;
return <React.Fragment>{value.title || 'enter title'}</React.Fragment>; return <span style={{ color: 'coral' }}>{collapsibleData.componentTitleField || fallback}</span>;
}; };
export default ArrayRowHeader;

View File

@@ -1,4 +1,5 @@
import type { CollectionConfig } from '../../../../src/collections/config/types'; import type { CollectionConfig } from '../../../../src/collections/config/types';
import { CollapsibleLabelComponent } from './HeaderComponent';
const CollapsibleFields: CollectionConfig = { const CollapsibleFields: CollectionConfig = {
slug: 'collapsible-fields', slug: 'collapsible-fields',
@@ -74,35 +75,35 @@ const CollapsibleFields: CollectionConfig = {
], ],
}, },
{ {
label: 'Collapsible Field - RowHeaderFunction', label: 'Collapsible Header Function',
type: 'collapsible', type: 'collapsible',
admin: { admin: {
description: 'This is a collapsible field.', description: 'Collapsible label rendered from a function.',
initCollapsed: true, initCollapsed: true,
components: { components: {
RowHeader: ({ value }) => value.title1 || 'untitled', CollapsibleLabel: ({ collapsibleData }) => collapsibleData.functionTitleField || 'Untitled',
}, },
}, },
fields: [ fields: [
{ {
name: 'title1', name: 'functionTitleField',
type: 'text', type: 'text',
}, },
], ],
}, },
{ {
label: 'Collapsible Field - RowHeaderComponent', label: 'Collapsible Header Component',
type: 'collapsible', type: 'collapsible',
admin: { admin: {
description: 'This is a collapsible field.', description: 'Collapsible label rendered as a react component.',
initCollapsed: true, initCollapsed: true,
components: { components: {
RowHeader: ({ value }) => value.title2 || 'untitled', CollapsibleLabel: CollapsibleLabelComponent,
}, },
}, },
fields: [ fields: [
{ {
name: 'title2', name: 'componentTitleField',
type: 'text', type: 'text',
}, },
], ],