Cannot override custom field type
Description
The code here doesn't allow us to "override" the custom field type.
The reason this is useful, is let's say you want all fields wrapped in a certain component to handle custom logic that all field types inherit, we can't do this currently with custom fields as it's bypassed in the link above.
For example:
import { Config, Plugin, FieldRenderFunctions } from '@measured/puck';
import { FieldDefinition } from '...';
type AllFieldRenderers = FieldRenderFunctions<
Config<{
fields: FieldDefinition;
}>
>;
// Props accepted by any field renderer in fieldTypes (union of all variants)
type FieldWrapperProps = Parameters<AllFieldRenderers[keyof AllFieldRenderers]>[0];
const FieldWrapperInner = ({ field, name, onChange, value, id }: FieldWrapperProps) => {
return (
<StandardFieldWrapper
field={field as StandardFieldComponentProps['field']}
name={name}
onChange={onChange}
value={value}
id={id ?? name}
/>
);
};
export const createPuckOverridesPlugin = (): Plugin<
Config<{
fields: FieldDefinition;
}>
> => {
return {
overrides: {
...
fieldTypes: {
unit: FieldWrapper,
switch: FieldWrapper,
custom: FieldWrapper,
},
};
};
Environment
- Puck version: [latest]
Steps to reproduce
- Simply provide "custom" as a key in the overrides, and a generic function, it'll never execute the function.
export const createPuckOverridesPlugin = () => {
return {
overrides: {
fieldTypes: {
custom:() => {
alert('yeah nah');
},
},
};
};
What happens
Nothing :D
What I expect to happen
Internally, puck should allow overrides of the custom field type.
Hey @shannonhochkins! Sorry for the long delay in getting back to you on this, I'll keep my eye on this from now on.
I think I understand what you mean, you basically want to wrap custom fields.
Would using more specific user-defined field types (which are not greatly documented) meet that need? Something like this:
const myConfig = {
components: {
MyComponent: {
fields: {
example: {
type: "myFieldType",
someCustomFieldConfig: "custom-value"
}
}
}
}
};
<Puck
config={myConfig}
overrides={{
fieldTypes: {
myFieldType: (props) => {
return (
<MyWrapper>
Field for: {props.name}
{/* props.field includes the `someCustomFieldConfig` property */}
<MyCustomField
field={props.field}
value={props.value}
onChange={props.onChange}
/>
</MyWrapper>
);
},
},
}}
/>
The reason I suggest this approach is that custom fields are mostly meant for one-offs.
Adding a global custom field override could potentially break existing usage in your app unless you explicitly call field.render, and even then, there might be side effects (like fields unmounting and losing focus or internal state) if it's not memoized properly. Using the override as a function is finicky.
Not completely against the idea, just wondering if the existing API might be a better fit for your use case.
Hey!
I already have multiple custom fields declared the way you've written them above, however I have custom functionality that's automatically attached to every field types via the overrides, for example i have "device values" as a toggle that can be enabled for every field, allowing different values per breakpoint, which is a pain to wire up, and I'm also using module federation for community plugins, users wouldn't know how to wire it up
I could get around this with a different name other than "custom" as the field type, and just call the custom field internally, but just feels a bit messy and will over complicate the types that's all
Hey @FedericoBonel Just wondering if this will be implemented, if not i'll have to introduce a new field type to achieve this, but would rather re-use the standard "custom" field type if possible, but would like to know if you guys think this will make it into puck before i do anything :)
@shannonhochkins sorry for the delay - we plan on having another look at your PR shortly.
All good my man! I have a few other bits and pieces to work on anyways :)