Skip to content

Ability to make allow and disallow type safe #1099

Description

@fkhadra

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
             />
}

Activity

  1. changed the title [-][v0.19] Ability to make allow and disallow type safe[/-] [+]Ability to make allow and disallow type safe[/+] on Jul 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions