diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md
index 8bccc2d10e3137..03cda1e18ec278 100644
--- a/packages/dataviews/CHANGELOG.md
+++ b/packages/dataviews/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Enhancements
+
+- DataForm: support `isDisabled` field property. [#77090](https://github.com/WordPress/gutenberg/pull/77090)
+
## 14.0.0 (2026-04-01)
### Breaking Changes
diff --git a/packages/dataviews/src/components/dataform-controls/array.tsx b/packages/dataviews/src/components/dataform-controls/array.tsx
index e122f3cfa577d1..56381786b5d1fb 100644
--- a/packages/dataviews/src/components/dataform-controls/array.tsx
+++ b/packages/dataviews/src/components/dataform-controls/array.tsx
@@ -24,6 +24,7 @@ export default function ArrayControl< Item >( {
}: DataFormControlProps< Item > ) {
const { label, placeholder, getValue, setValue, isValid } = field;
const value = getValue( { item: data } );
+ const disabled = field.isDisabled( { item: data, field } );
const { elements, isLoading } = useElements( {
elements: field.elements,
@@ -73,6 +74,7 @@ export default function ArrayControl< Item >( {
onChange={ onChangeControl }
placeholder={ placeholder }
suggestions={ elements?.map( ( element ) => element.value ) }
+ disabled={ disabled }
__experimentalValidateInput={ ( token: string ) => {
// If elements validation is required, check if token is valid
if ( field.isValid?.elements && elements ) {
diff --git a/packages/dataviews/src/components/dataform-controls/checkbox.tsx b/packages/dataviews/src/components/dataform-controls/checkbox.tsx
index 9e2637675969dc..34c460d90d9140 100644
--- a/packages/dataviews/src/components/dataform-controls/checkbox.tsx
+++ b/packages/dataviews/src/components/dataform-controls/checkbox.tsx
@@ -22,6 +22,7 @@ export default function Checkbox< Item >( {
validity,
}: DataFormControlProps< Item > ) {
const { getValue, setValue, label, description, isValid } = field;
+ const disabled = field.isDisabled( { item: data, field } );
const onChangeControl = useCallback( () => {
onChange(
@@ -39,6 +40,7 @@ export default function Checkbox< Item >( {
help={ description }
checked={ getValue( { item: data } ) }
onChange={ onChangeControl }
+ disabled={ disabled }
/>
);
}
diff --git a/packages/dataviews/src/components/dataform-controls/color.tsx b/packages/dataviews/src/components/dataform-controls/color.tsx
index e236bc78750427..8d4409bea74e84 100644
--- a/packages/dataviews/src/components/dataform-controls/color.tsx
+++ b/packages/dataviews/src/components/dataform-controls/color.tsx
@@ -30,9 +30,11 @@ const { ValidatedInputControl } = unlock( privateApis );
const ColorPickerDropdown = ( {
color,
onColorChange,
+ disabled,
}: {
color: string;
onColorChange: ( newColor: string ) => void;
+ disabled?: boolean;
} ) => {
const validColor = color && colord( color ).isValid() ? color : '#ffffff';
@@ -45,6 +47,8 @@ const ColorPickerDropdown = ( {
onClick={ onToggle }
aria-label={ __( 'Open color picker' ) }
size="small"
+ disabled={ disabled }
+ accessibleWhenDisabled
icon={ () => }
/>
) }
@@ -70,6 +74,7 @@ export default function Color< Item >( {
validity,
}: DataFormControlProps< Item > ) {
const { label, placeholder, description, setValue, isValid } = field;
+ const disabled = field.isDisabled( { item: data, field } );
const value = field.getValue( { item: data } ) || '';
const handleColorChange = useCallback(
@@ -98,11 +103,13 @@ export default function Color< Item >( {
onChange={ handleInputChange }
hideLabelFromVision={ hideLabelFromVision }
type="text"
+ disabled={ disabled }
prefix={
}
diff --git a/packages/dataviews/src/components/dataform-controls/date.tsx b/packages/dataviews/src/components/dataform-controls/date.tsx
index 758d53e47d7474..5fc114e115cd99 100644
--- a/packages/dataviews/src/components/dataform-controls/date.tsx
+++ b/packages/dataviews/src/components/dataform-controls/date.tsx
@@ -299,6 +299,7 @@ function CalendarDateControl< Item >( {
isValid,
format: fieldFormat,
} = field;
+ const disabled = field.isDisabled( { item: data, field } );
const [ selectedPresetId, setSelectedPresetId ] = useState< string | null >(
null
);
@@ -406,6 +407,8 @@ function CalendarDateControl< Item >( {
variant="tertiary"
isPressed={ isSelected }
size="small"
+ disabled={ disabled }
+ accessibleWhenDisabled
onClick={ () =>
handlePresetClick( preset )
}
@@ -419,8 +422,8 @@ function CalendarDateControl< Item >( {
variant="tertiary"
isPressed={ ! selectedPresetId }
size="small"
- disabled={ !! selectedPresetId }
- accessibleWhenDisabled={ false }
+ disabled={ !! selectedPresetId || disabled }
+ accessibleWhenDisabled
>
{ __( 'Custom' ) }
@@ -436,6 +439,7 @@ function CalendarDateControl< Item >( {
value={ value }
onChange={ handleManualDateChange }
required={ !! field.isValid?.required }
+ disabled={ disabled }
/>
{ /* Calendar widget */ }
@@ -449,6 +453,7 @@ function CalendarDateControl< Item >( {
onMonthChange={ setCalendarMonth }
timeZone={ timezoneString || undefined }
weekStartsOn={ weekStartsOn }
+ disabled={ disabled }
/>
@@ -472,6 +477,7 @@ function CalendarDateRangeControl< Item >( {
setValue,
format: fieldFormat,
} = field;
+ const disabled = field.isDisabled( { item: data, field } );
let value: DateRange;
const fieldValue = getValue( { item: data } );
if (
@@ -626,6 +632,8 @@ function CalendarDateRangeControl< Item >( {
variant="tertiary"
isPressed={ isSelected }
size="small"
+ disabled={ disabled }
+ accessibleWhenDisabled
onClick={ () =>
handlePresetClick( preset )
}
@@ -639,8 +647,8 @@ function CalendarDateRangeControl< Item >( {
variant="tertiary"
isPressed={ ! selectedPresetId }
size="small"
- accessibleWhenDisabled={ false }
- disabled={ !! selectedPresetId }
+ accessibleWhenDisabled
+ disabled={ !! selectedPresetId || disabled }
>
{ __( 'Custom' ) }
@@ -664,6 +672,7 @@ function CalendarDateRangeControl< Item >( {
handleManualDateChange( 'from', newValue )
}
required={ !! field.isValid?.required }
+ disabled={ disabled }
/>
( {
handleManualDateChange( 'to', newValue )
}
required={ !! field.isValid?.required }
+ disabled={ disabled }
/>
@@ -687,6 +697,7 @@ function CalendarDateRangeControl< Item >( {
onMonthChange={ setCalendarMonth }
timeZone={ timezone.string || undefined }
weekStartsOn={ weekStartsOn }
+ disabled={ disabled }
/>
diff --git a/packages/dataviews/src/components/dataform-controls/datetime.tsx b/packages/dataviews/src/components/dataform-controls/datetime.tsx
index 21037428945b38..746c5b5eb878fb 100644
--- a/packages/dataviews/src/components/dataform-controls/datetime.tsx
+++ b/packages/dataviews/src/components/dataform-controls/datetime.tsx
@@ -41,6 +41,7 @@ function CalendarDateTimeControl< Item >( {
}: DataFormControlProps< Item > ) {
const { compact } = config || {};
const { id, label, description, setValue, getValue, isValid } = field;
+ const disabled = field.isDisabled( { item: data, field } );
const fieldValue = getValue( { item: data } );
const value = typeof fieldValue === 'string' ? fieldValue : undefined;
@@ -179,6 +180,7 @@ function CalendarDateTimeControl< Item >( {
hideLabelFromVision
value={ formatDateTime( value ) }
onChange={ handleManualDateTimeChange }
+ disabled={ disabled }
/>
{ /* Calendar widget */ }
{ ! compact && (
@@ -194,6 +196,7 @@ function CalendarDateTimeControl< Item >( {
onMonthChange={ setCalendarMonth }
timeZone={ timezoneString || undefined }
weekStartsOn={ weekStartsOn }
+ disabled={ disabled }
/>
) }
diff --git a/packages/dataviews/src/components/dataform-controls/password.tsx b/packages/dataviews/src/components/dataform-controls/password.tsx
index 5b8c75639e7ba2..d9acdbd657afe3 100644
--- a/packages/dataviews/src/components/dataform-controls/password.tsx
+++ b/packages/dataviews/src/components/dataform-controls/password.tsx
@@ -23,6 +23,7 @@ export default function Password< Item >( {
validity,
}: DataFormControlProps< Item > ) {
const [ isVisible, setIsVisible ] = useState( false );
+ const disabled = field.isDisabled( { item: data, field } );
const toggleVisibility = useCallback( () => {
setIsVisible( ( prev ) => ! prev );
@@ -49,6 +50,8 @@ export default function Password< Item >( {
? __( 'Hide password' )
: __( 'Show password' )
}
+ disabled={ disabled }
+ accessibleWhenDisabled
/>
),
diff --git a/packages/dataviews/src/components/dataform-controls/radio.tsx b/packages/dataviews/src/components/dataform-controls/radio.tsx
index 599f009146f88e..6abf9a41b39885 100644
--- a/packages/dataviews/src/components/dataform-controls/radio.tsx
+++ b/packages/dataviews/src/components/dataform-controls/radio.tsx
@@ -23,6 +23,7 @@ export default function Radio< Item >( {
validity,
}: DataFormControlProps< Item > ) {
const { label, description, getValue, setValue, isValid } = field;
+ const disabled = field.isDisabled( { item: data, field } );
const { elements, isLoading } = useElements( {
elements: field.elements,
getElements: field.getElements,
@@ -50,6 +51,7 @@ export default function Radio< Item >( {
options={ elements }
selected={ value }
hideLabelFromVision={ hideLabelFromVision }
+ disabled={ disabled }
/>
);
}
diff --git a/packages/dataviews/src/components/dataform-controls/select.tsx b/packages/dataviews/src/components/dataform-controls/select.tsx
index 19211840ce2926..197166f7c3fa0b 100644
--- a/packages/dataviews/src/components/dataform-controls/select.tsx
+++ b/packages/dataviews/src/components/dataform-controls/select.tsx
@@ -23,6 +23,7 @@ export default function Select< Item >( {
validity,
}: DataFormControlProps< Item > ) {
const { type, label, description, getValue, setValue, isValid } = field;
+ const disabled = field.isDisabled( { item: data, field } );
const isMultiple = type === 'array';
const value = getValue( { item: data } ) ?? ( isMultiple ? [] : '' );
@@ -55,6 +56,7 @@ export default function Select< Item >( {
__next40pxDefaultSize
hideLabelFromVision={ hideLabelFromVision }
multiple={ isMultiple }
+ disabled={ disabled }
/>
);
}
diff --git a/packages/dataviews/src/components/dataform-controls/textarea.tsx b/packages/dataviews/src/components/dataform-controls/textarea.tsx
index 6a1785a0376e73..65ca6b496d0fbb 100644
--- a/packages/dataviews/src/components/dataform-controls/textarea.tsx
+++ b/packages/dataviews/src/components/dataform-controls/textarea.tsx
@@ -23,6 +23,7 @@ export default function Textarea< Item >( {
validity,
}: DataFormControlProps< Item > ) {
const { rows = 4 } = config || {};
+ const disabled = field.isDisabled( { item: data, field } );
const { label, placeholder, description, setValue, isValid } = field;
const value = field.getValue( { item: data } );
@@ -43,6 +44,7 @@ export default function Textarea< Item >( {
help={ description }
onChange={ onChangeControl }
rows={ rows }
+ disabled={ disabled }
minLength={
isValid.minLength ? isValid.minLength.constraint : undefined
}
diff --git a/packages/dataviews/src/components/dataform-controls/toggle-group.tsx b/packages/dataviews/src/components/dataform-controls/toggle-group.tsx
index 58ec8883337ff9..8d1d03df3aca0a 100644
--- a/packages/dataviews/src/components/dataform-controls/toggle-group.tsx
+++ b/packages/dataviews/src/components/dataform-controls/toggle-group.tsx
@@ -27,6 +27,7 @@ export default function ToggleGroup< Item >( {
validity,
}: DataFormControlProps< Item > ) {
const { getValue, setValue, isValid } = field;
+ const disabled = field.isDisabled( { item: data, field } );
const value = getValue( { item: data } );
const onChangeControl = useCallback(
@@ -67,6 +68,7 @@ export default function ToggleGroup< Item >( {
key={ el.value }
label={ el.label }
value={ el.value }
+ disabled={ disabled }
/>
) ) }
diff --git a/packages/dataviews/src/components/dataform-controls/toggle.tsx b/packages/dataviews/src/components/dataform-controls/toggle.tsx
index 045e46384625fe..62e514610fc855 100644
--- a/packages/dataviews/src/components/dataform-controls/toggle.tsx
+++ b/packages/dataviews/src/components/dataform-controls/toggle.tsx
@@ -22,6 +22,7 @@ export default function Toggle< Item >( {
validity,
}: DataFormControlProps< Item > ) {
const { label, description, getValue, setValue, isValid } = field;
+ const disabled = field.isDisabled( { item: data, field } );
const onChangeControl = useCallback( () => {
onChange(
@@ -39,6 +40,7 @@ export default function Toggle< Item >( {
help={ description }
checked={ getValue( { item: data } ) }
onChange={ onChangeControl }
+ disabled={ disabled }
/>
);
}
diff --git a/packages/dataviews/src/components/dataform-controls/utils/relative-date-control.tsx b/packages/dataviews/src/components/dataform-controls/utils/relative-date-control.tsx
index a44f4e634ef275..50de96d4347c78 100644
--- a/packages/dataviews/src/components/dataform-controls/utils/relative-date-control.tsx
+++ b/packages/dataviews/src/components/dataform-controls/utils/relative-date-control.tsx
@@ -59,6 +59,7 @@ export default function RelativeDateControl< Item >( {
];
const { id, label, description, getValue, setValue } = field;
+ const disabled = field.isDisabled( { item: data, field } );
const fieldValue = getValue( { item: data } );
const { value: relValue = '', unit = options[ 0 ].value } =
fieldValue && typeof fieldValue === 'object' ? fieldValue : {};
@@ -102,6 +103,7 @@ export default function RelativeDateControl< Item >( {
step={ 1 }
value={ relValue }
onChange={ onChangeValue }
+ disabled={ disabled }
/>
( {
options={ options }
onChange={ onChangeUnit }
hideLabelFromVision
+ disabled={ disabled }
/>
diff --git a/packages/dataviews/src/components/dataform-controls/utils/validated-input.tsx b/packages/dataviews/src/components/dataform-controls/utils/validated-input.tsx
index cc2f1f3055a564..37c2b8f9448b53 100644
--- a/packages/dataviews/src/components/dataform-controls/utils/validated-input.tsx
+++ b/packages/dataviews/src/components/dataform-controls/utils/validated-input.tsx
@@ -43,6 +43,7 @@ export default function ValidatedText< Item >( {
const { label, placeholder, description, getValue, setValue, isValid } =
field;
const value = getValue( { item: data } );
+ const disabled = field.isDisabled( { item: data, field } );
const onChangeControl = useCallback(
( newValue: string ) =>
@@ -69,6 +70,7 @@ export default function ValidatedText< Item >( {
type={ type }
prefix={ prefix }
suffix={ suffix }
+ disabled={ disabled }
pattern={ isValid.pattern ? isValid.pattern.constraint : undefined }
minLength={
isValid.minLength ? isValid.minLength.constraint : undefined
diff --git a/packages/dataviews/src/components/dataform-controls/utils/validated-number.tsx b/packages/dataviews/src/components/dataform-controls/utils/validated-number.tsx
index f5fbb24c9a137a..9d93de775ec907 100644
--- a/packages/dataviews/src/components/dataform-controls/utils/validated-number.tsx
+++ b/packages/dataviews/src/components/dataform-controls/utils/validated-number.tsx
@@ -96,6 +96,7 @@ export default function ValidatedNumber< Item >( {
const step = Math.pow( 10, Math.abs( decimals ) * -1 );
const { label, description, getValue, setValue, isValid } = field;
const value = getValue( { item: data } ) ?? '';
+ const disabled = field.isDisabled( { item: data, field } );
const onChangeControl = useCallback(
( newValue: string | undefined ) => {
@@ -161,6 +162,7 @@ export default function ValidatedNumber< Item >( {
step={ step }
min={ isValid.min ? isValid.min.constraint : undefined }
max={ isValid.max ? isValid.max.constraint : undefined }
+ disabled={ disabled }
/>
);
}
diff --git a/packages/dataviews/src/components/dataviews-filters/input-widget.tsx b/packages/dataviews/src/components/dataviews-filters/input-widget.tsx
index fa60759f3e981d..8229bc938508a9 100644
--- a/packages/dataviews/src/components/dataviews-filters/input-widget.tsx
+++ b/packages/dataviews/src/components/dataviews-filters/input-widget.tsx
@@ -64,6 +64,10 @@ export default function InputWidget( {
...currentField,
// Deactivate validation for filters.
isValid: {} satisfies NormalizedRules< any >,
+ // Filter controls are always enabled.
+ isDisabled: () => false,
+ // Filter controls are always visible.
+ isVisible: () => true,
// Configure getValue/setValue as if Item was a plain object.
getValue: ( { item }: { item: any } ) =>
item[ currentField.id ],
diff --git a/packages/dataviews/src/dataform/stories/index.story.tsx b/packages/dataviews/src/dataform/stories/index.story.tsx
index 8a75a7be59a35b..dd094de7469c1b 100644
--- a/packages/dataviews/src/dataform/stories/index.story.tsx
+++ b/packages/dataviews/src/dataform/stories/index.story.tsx
@@ -93,6 +93,13 @@ export const LayoutRegular = {
description: 'Chooses the label position.',
options: [ 'default', 'top', 'side', 'none' ],
},
+ disabled: {
+ control: { type: 'boolean' },
+ description: 'Disable all fields in the form.',
+ },
+ },
+ args: {
+ disabled: false,
},
};
diff --git a/packages/dataviews/src/dataform/stories/layout-regular.tsx b/packages/dataviews/src/dataform/stories/layout-regular.tsx
index 4c6a1b8a646f40..10517bd55a29e7 100644
--- a/packages/dataviews/src/dataform/stories/layout-regular.tsx
+++ b/packages/dataviews/src/dataform/stories/layout-regular.tsx
@@ -312,8 +312,10 @@ const getLayoutFromStoryArgs = ( {
const LayoutRegularComponent = ( {
labelPosition,
+ disabled = false,
}: {
labelPosition: 'default' | 'top' | 'side' | 'none';
+ disabled?: boolean;
} ) => {
const [ post, setPost ] = useState( {
title: 'Hello, World!',
@@ -332,6 +334,18 @@ const LayoutRegularComponent = ( {
description: 'This is a sample description.',
} );
+ // Make fields disabled when control is set to disabled.
+ const _fields: Field< SamplePost >[] = useMemo( () => {
+ if ( ! disabled ) {
+ return fields;
+ }
+
+ return fields.map( ( field ) => ( {
+ ...field,
+ isDisabled: true,
+ } ) );
+ }, [ disabled ] );
+
const form: Form = useMemo(
() => ( {
layout: getLayoutFromStoryArgs( {
@@ -363,7 +377,7 @@ const LayoutRegularComponent = ( {
return (
data={ post }
- fields={ fields }
+ fields={ _fields }
form={ form }
onChange={ ( edits ) =>
setPost( ( prev ) => ( {
diff --git a/packages/dataviews/src/field-types/index.tsx b/packages/dataviews/src/field-types/index.tsx
index 2b570b38bb5eb8..acbb4b8fc54ab0 100644
--- a/packages/dataviews/src/field-types/index.tsx
+++ b/packages/dataviews/src/field-types/index.tsx
@@ -96,6 +96,10 @@ export default function normalizeFields< Item >(
getElements: field.getElements,
hasElements: hasElements( field ),
isVisible: field.isVisible,
+ isDisabled:
+ typeof field.isDisabled === 'function'
+ ? field.isDisabled
+ : () => !! field.isDisabled,
enableHiding: field.enableHiding ?? true,
readOnly: field.readOnly ?? false,
// The type provides defaults for the following props
diff --git a/packages/dataviews/src/field-types/stories/index.story.tsx b/packages/dataviews/src/field-types/stories/index.story.tsx
index 7bf3e152ea399a..fbe84685297850 100644
--- a/packages/dataviews/src/field-types/stories/index.story.tsx
+++ b/packages/dataviews/src/field-types/stories/index.story.tsx
@@ -66,12 +66,17 @@ const meta = {
'Add 10 more elements to push over the threshold and trigger Combobox rendering',
if: { arg: 'Edit', eq: 'adaptiveSelect' },
},
+ disabled: {
+ control: { type: 'boolean' },
+ description: 'Whether the field controls are disabled.',
+ },
},
args: {
type: 'regular',
Edit: 'default',
asyncElements: false,
manyElements: false,
+ disabled: false,
},
};
export default meta;
@@ -590,6 +595,7 @@ interface FieldTypeStoryProps {
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
}
const FieldTypeStory = ( {
@@ -598,17 +604,27 @@ const FieldTypeStory = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: FieldTypeStoryProps ) => {
const storyFields = useMemo( () => {
let fieldsToProcess = _fields;
- if ( Edit !== 'default' ) {
- fieldsToProcess = _fields.map( ( field: Field< DataType > ) => ( {
+ if ( disabled ) {
+ fieldsToProcess = fieldsToProcess.map( ( field ) => ( {
...field,
- Edit,
+ isDisabled: true,
} ) );
}
+ if ( Edit !== 'default' ) {
+ fieldsToProcess = fieldsToProcess.map(
+ ( field: Field< DataType > ) => ( {
+ ...field,
+ Edit,
+ } )
+ );
+ }
+
// Expand elements when adaptiveSelect is selected and manyElements is toggled
if ( Edit === 'adaptiveSelect' && manyElements ) {
fieldsToProcess = fieldsToProcess.map( ( field ) => {
@@ -648,7 +664,7 @@ const FieldTypeStory = ( {
}
return fieldsToProcess;
- }, [ _fields, Edit, asyncElements, manyElements ] );
+ }, [ _fields, Edit, asyncElements, manyElements, disabled ] );
const form = useMemo(
() => ( {
layout: { type },
@@ -756,11 +772,13 @@ export const AllComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
return (
);
};
@@ -779,11 +798,13 @@ export const TextComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
const textFields = useMemo(
() => fields.filter( ( field ) => field.type === 'text' ),
@@ -797,6 +818,7 @@ export const TextComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -808,12 +830,14 @@ export const IntegerComponent = ( {
asyncElements,
manyElements,
formatSeparatorThousand,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
formatSeparatorThousand?: string;
+ disabled: boolean;
} ) => {
const integerFields = useMemo(
() =>
@@ -840,6 +864,7 @@ export const IntegerComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -863,6 +888,7 @@ export const NumberComponent = ( {
formatSeparatorThousand,
formatSeparatorDecimal,
formatDecimals,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
@@ -871,6 +897,7 @@ export const NumberComponent = ( {
formatSeparatorThousand?: string;
formatSeparatorDecimal?: string;
formatDecimals?: number;
+ disabled: boolean;
} ) => {
const numberFields = useMemo(
() =>
@@ -913,6 +940,7 @@ export const NumberComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -945,11 +973,13 @@ export const BooleanComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
const booleanFields = useMemo(
() => fields.filter( ( field ) => field.type === 'boolean' ),
@@ -963,6 +993,7 @@ export const BooleanComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -975,6 +1006,7 @@ export const DateTimeComponent = ( {
manyElements,
formatDatetime,
formatWeekStartsOn,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
@@ -982,6 +1014,7 @@ export const DateTimeComponent = ( {
manyElements: boolean;
formatDatetime?: string;
formatWeekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
+ disabled: boolean;
} ) => {
const datetimeFields = useMemo(
() =>
@@ -1006,7 +1039,7 @@ export const DateTimeComponent = ( {
}
return field;
} ),
- [ fields, formatDatetime, formatWeekStartsOn ]
+ [ formatDatetime, formatWeekStartsOn ]
);
return (
@@ -1016,6 +1049,7 @@ export const DateTimeComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -1054,6 +1088,7 @@ export const DateComponent = ( {
manyElements,
formatDate,
formatWeekStartsOn,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
@@ -1061,6 +1096,7 @@ export const DateComponent = ( {
manyElements: boolean;
formatDate?: string;
formatWeekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
+ disabled: boolean;
} ) => {
const dateFields = useMemo(
() =>
@@ -1095,6 +1131,7 @@ export const DateComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -1131,11 +1168,13 @@ export const EmailComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
const emailFields = useMemo(
() => fields.filter( ( field ) => field.type === 'email' ),
@@ -1149,6 +1188,7 @@ export const EmailComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -1159,11 +1199,13 @@ export const TelephoneComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
const telephoneFields = fields.filter( ( field ) =>
field.id.startsWith( 'telephone' )
@@ -1176,6 +1218,7 @@ export const TelephoneComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -1186,11 +1229,13 @@ export const UrlComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
const urlFields = useMemo(
() => fields.filter( ( field ) => field.type === 'url' ),
@@ -1204,6 +1249,7 @@ export const UrlComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -1214,11 +1260,13 @@ export const ColorComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
const colorFields = useMemo(
() => fields.filter( ( field ) => field.type === 'color' ),
@@ -1232,6 +1280,7 @@ export const ColorComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -1242,11 +1291,13 @@ export const MediaComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
const mediaFields = useMemo(
() => fields.filter( ( field ) => field.type === 'media' ),
@@ -1260,6 +1311,7 @@ export const MediaComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -1270,11 +1322,13 @@ export const ArrayComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
const arrayTextFields = useMemo(
() => fields.filter( ( field ) => field.type === 'array' ),
@@ -1288,6 +1342,7 @@ export const ArrayComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -1298,11 +1353,13 @@ export const PasswordComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
const passwordFields = fields.filter( ( field ) =>
field.id.startsWith( 'password' )
@@ -1315,6 +1372,7 @@ export const PasswordComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
@@ -1325,11 +1383,13 @@ export const NoTypeComponent = ( {
Edit,
asyncElements,
manyElements,
+ disabled,
}: {
type: PanelTypes;
Edit: ControlTypes;
asyncElements: boolean;
manyElements: boolean;
+ disabled: boolean;
} ) => {
const noTypeFields = useMemo(
() => fields.filter( ( field ) => field.type === undefined ),
@@ -1343,6 +1403,7 @@ export const NoTypeComponent = ( {
Edit={ Edit }
asyncElements={ asyncElements }
manyElements={ manyElements }
+ disabled={ disabled }
/>
);
};
diff --git a/packages/dataviews/src/types/field-api.ts b/packages/dataviews/src/types/field-api.ts
index fae835d0e126b8..c1028eb0dfd52a 100644
--- a/packages/dataviews/src/types/field-api.ts
+++ b/packages/dataviews/src/types/field-api.ts
@@ -244,6 +244,18 @@ export type Field< Item > = {
*/
isVisible?: ( item: Item ) => boolean;
+ /**
+ * Whether a field should be disabled.
+ * Can be a boolean or a callback receiving the current item and field.
+ * Defaults to false.
+ */
+ isDisabled?:
+ | boolean
+ | ( ( args: {
+ item: Item;
+ field: NormalizedField< Item >;
+ } ) => boolean );
+
/**
* Whether the field is sortable.
*/
@@ -380,6 +392,10 @@ export type NormalizedField< Item > = Omit<
filterBy: Required< FilterByConfig > | false;
filter: FilterOperatorMap< Item >;
readOnly: boolean;
+ isDisabled: ( args: {
+ item: Item;
+ field: NormalizedField< Item >;
+ } ) => boolean;
format:
| {}
| Required< FormatDate >