Description
While using DropZone, it was possible to override the component interface to make both allow and disallow type safe. In practice, we created a thin wrapper around DropZone, this is how it looks like in our case:
import { DropZone as PuckDropZone } from '@measured/puck';
import { styled } from '@mui/material';
import type { WidgetKeyValue } from '../registry';
interface DropZoneProps extends React.ComponentPropsWithRef<typeof PuckDropZone> {
/**
* Only allows the specified widgets to be added.
*
* By default, any widgets are allowed.
*/
allow?: WidgetKeyValue[];
/**
* Prevents the specified widgets to be added.
*
* By default, no widgets are disallowed
*/
disallow?: WidgetKeyValue[];
}
// Wrapper to make `allow` and `disallow` type safe and add sxProps support as well
export const DropZone = styled(PuckDropZone)<DropZoneProps>();
It prevented engineers from providing wrong keys and saved time during development and debugging.
Ideally, we should be able to define the same behavior with the new slot API.
Considerations
A possible workaround alternative is to rely on a constant like Widget.KeyOfMyComponent but it doesn't guarantee type safety during development and can fails at runtime, which we want to avoid.
Proposals
Proposal
Add a new generic parameter is added to the PuckComponent interface. The second generic parameter would allow to specify the supported keys for both allow and disallow. It would also require to update the interface for SlotComponent and DropZoneProps in order to use the new generic parameter.
type DropZoneProps<T extends string = string> = {
zone: string;
allow?: T[];
disallow?: T[];
style?: CSSProperties;
minEmptyHeight?: number;
className?: string;
collisionAxis?: DragAxis;
};
type SlotComponent<ComponentKeys = string> = (props?: Omit<DropZoneProps<ComponentKeys>, "zone">) => ReactNode;
type PuckComponent<Props, ComponentKeys = string> = (props: WithId<WithPuckProps<{
[K in keyof Props]: WithDeepSlots<Props[K], SlotComponent<ComponentKeys> >;
}>>) => JSX.Element;
// usage
interface Props {
Slot: Slot;
}
const MyComponent: PuckComponent<Props, "foo" | "bar"> = ({ Slot }) => {
return <Slot
allow={["foo"]} // OK + autocomplete
disallow={["xxx"]} // won't compile
/>
}
Description
While using
DropZone, it was possible to override the component interface to make bothallowanddisallowtype safe. In practice, we created a thin wrapper aroundDropZone, this is how it looks like in our case:It prevented engineers from providing wrong keys and saved time during development and debugging.
Ideally, we should be able to define the same behavior with the new slot API.
Considerations
A possible workaround alternative is to rely on a constant like
Widget.KeyOfMyComponentbut it doesn't guarantee type safety during development and can fails at runtime, which we want to avoid.Proposals
Proposal
Add a new generic parameter is added to the
PuckComponentinterface. The second generic parameter would allow to specify the supported keys for bothallowanddisallow. It would also require to update the interface forSlotComponentandDropZonePropsin order to use the new generic parameter.