type DefaultSizing = "xl" | "lg" | "md" | "sm";
export type DefaultLayoutProps = {
marginLeft?: DefaultSizing;
marginRight?: DefaultSizing;
...
};
type DefaultWrapperProps = DefaultLayoutProps & { children?: ReactNode };
export type DefaultComponentConfig<TProps> = ComponentConfig<
TProps & DefaultLayoutProps
;
const defaultLayoutFields = {
marginLeft: {
type: "select" as const,
options: [
{ label: "Small", value: "sm" },
{ label: "Medium", value: "md" },
{ label: "Large", value: "lg" },
{ label: "Extra Large", value: "xl" },
],
},
marginRight: {
type: "select" as const,
options: [
...
],
},
},
} satisfies ComponentConfig<DefaultLayoutProps>["fields"];
const defaultLayoutProps: DefaultLayoutProps = {
marginLeft: "md",
marginRight: "md",
marginTop: "md",
...
};
const DefaultWrapper = ({
children,
marginBottom,
marginLeft,
marginRight,
...
}: DefaultWrapperProps) => {
const className = [
marginBottom && mb-${marginBottom},
marginTop && mt-${marginTop},
...
]
.filter(Boolean)
.join(" ");
return <div className={className}>{children}</div>;
};
export type HeaderBlockProps = {
title: string;
};
type HeaderBlockRenderProps = HeaderBlockProps & DefaultWrapperProps;
export const HeaderBlock: ComponentConfig<
HeaderBlockRenderProps,
HeaderBlockProps & DefaultLayoutProps
= {
fields: {
title: { type: "text" as const },
...defaultLayoutFields,
},
defaultProps: {
...defaultLayoutProps,
title: "Heading",
},
render: ({ title, children, ...spacing }) => (
<DefaultWrapper {...spacing}>
<HeadingComponent title={title} />
{children}
</DefaultWrapper>
),
};