Skip to content

Commit

Permalink
feat: add generic Config type to Puck and Render components
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisvxd committed Dec 18, 2023
1 parent d1baf8f commit 1c4b97f
Show file tree
Hide file tree
Showing 10 changed files with 43 additions and 38 deletions.
6 changes: 3 additions & 3 deletions apps/demo/app/[...puckPath]/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Puck } from "@/core/components/Puck";
import { Render } from "@/core/components/Render";
import { Button } from "@/core/components/Button";
import headingAnalyzer from "@/plugin-heading-analyzer/src/HeadingAnalyzer";
import config from "../../config";
import config, { UserConfig } from "../../config";
import { useDemoData } from "../../lib/use-demo-data";

export function Client({ path, isEdit }: { path: string; isEdit: boolean }) {
Expand All @@ -17,7 +17,7 @@ export function Client({ path, isEdit }: { path: string; isEdit: boolean }) {
if (isEdit) {
return (
<div>
<Puck
<Puck<UserConfig>
config={config}
data={data}
onPublish={async (data: Data) => {
Expand All @@ -42,7 +42,7 @@ export function Client({ path, isEdit }: { path: string; isEdit: boolean }) {
}

if (data) {
return <Render config={config} data={resolvedData} />;
return <Render<UserConfig> config={config} data={resolvedData} />;
}

return (
Expand Down
6 changes: 3 additions & 3 deletions apps/demo/app/custom-ui/[...puckPath]/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Puck } from "@/core/components/Puck";
import { Render } from "@/core/components/Render";
import { Button } from "@/core/components/Button";
import { HeadingAnalyzer } from "@/plugin-heading-analyzer/src/HeadingAnalyzer";
import config from "../../../config";
import config, { UserConfig } from "../../../config";
import { useDemoData } from "../../../lib/use-demo-data";
import { IconButton, usePuck } from "@/core";
import { ReactNode, useEffect, useRef, useState } from "react";
Expand Down Expand Up @@ -287,7 +287,7 @@ export function Client({ path, isEdit }: { path: string; isEdit: boolean }) {

if (isEdit) {
return (
<Puck
<Puck<UserConfig>
config={config}
data={data}
headerPath={path}
Expand Down Expand Up @@ -336,7 +336,7 @@ export function Client({ path, isEdit }: { path: string; isEdit: boolean }) {
}

if (data) {
return <Render config={config} data={resolvedData} />;
return <Render<UserConfig> config={config} data={resolvedData} />;
}

return (
Expand Down
8 changes: 5 additions & 3 deletions apps/demo/config/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ export type Props = {
VerticalSpace: VerticalSpaceProps;
};

// We avoid the name config as next gets confused
export const conf: Config<
export type UserConfig = Config<
Props,
RootProps,
"layout" | "typography" | "interactive"
> = {
>;

// We avoid the name config as next gets confused
export const conf: UserConfig = {
root: {
render: Root,
},
Expand Down
6 changes: 4 additions & 2 deletions packages/core/components/DropZone/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ import { getZoneId } from "../../lib/get-zone-id";

export type PathData = Record<string, { path: string[]; label: string }>;

export type DropZoneContext = {
export type DropZoneContext<
UserConfig extends Config<any, any, any> = Config<any, any, any>
> = {
data: Data;
config: Config;
config: UserConfig;
componentState?: Record<string, any>;
itemSelector?: ItemSelector | null;
setItemSelector?: (newIndex: ItemSelector | null) => void;
Expand Down
14 changes: 9 additions & 5 deletions packages/core/components/Puck/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ export const defaultAppState: AppState = {
},
};

type AppContext = {
type AppContext<
UserConfig extends Config<any, any, any> = Config<any, any, any>
> = {
state: AppState;
dispatch: (action: PuckAction) => void;
config: Config;
config: UserConfig;
componentState: Record<string, { loading: boolean }>;
resolveData: (newAppState: AppState) => void;
plugins: Plugin[];
Expand All @@ -42,8 +44,10 @@ export const appContext = createContext<AppContext>({

export const AppProvider = appContext.Provider;

export const useAppContext = () => {
const mainContext = useContext(appContext);
export function useAppContext<
UserConfig extends Config<any, any, any> = Config<any, any, any>
>() {
const mainContext = useContext(appContext) as AppContext<UserConfig>;

const selectedItem = mainContext.state.ui.itemSelector
? getItem(mainContext.state.ui.itemSelector, mainContext.state.data)
Expand All @@ -61,4 +65,4 @@ export const useAppContext = () => {
});
},
};
};
}
8 changes: 5 additions & 3 deletions packages/core/components/Puck/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ import { useHistoryStore } from "../../lib/use-history-store";

const getClassName = getClassNameFactory("Puck", styles);

export function Puck({
export function Puck<
UserConfig extends Config<any, any, any> = Config<any, any, any>
>({
children,
config,
data: initialData = { content: [], root: { props: { title: "" } } },
Expand All @@ -60,7 +62,7 @@ export function Puck({
headerPath,
}: {
children?: ReactNode;
config: Config<any, any, any>;
config: UserConfig;
data: Data;
ui?: Partial<UiState>;
onChange?: (data: Data) => void;
Expand All @@ -82,7 +84,7 @@ export function Puck({
const historyStore = useHistoryStore();

const [reducer] = useState(() =>
createReducer({ config, record: historyStore.record })
createReducer<UserConfig>({ config, record: historyStore.record })
);

const [initialAppState] = useState<AppState>(() => ({
Expand Down
10 changes: 3 additions & 7 deletions packages/core/components/Render/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@ import { rootDroppableId } from "../../lib/root-droppable-id";
import { Config, Data } from "../../types/Config";
import { DropZone, DropZoneProvider } from "../DropZone";

export function Render({
config,
data,
}: {
config: Config<any, any, any>;
data: Data;
}) {
export function Render<
UserConfig extends Config<any, any, any> = Config<any, any, any>
>({ config, data }: { config: UserConfig; data: Data }) {
// DEPRECATED
const rootProps = data.root.props || data.root;
const title = rootProps?.title || "";
Expand Down
10 changes: 3 additions & 7 deletions packages/core/components/ServerRender/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,9 @@ function DropZoneRender({
);
}

export function Render({
config,
data,
}: {
config: Config<any, any, any>;
data: Data;
}) {
export function Render<
UserConfig extends Config<any, any, any> = Config<any, any, any>
>({ config, data }: { config: UserConfig; data: Data }) {
if (config.root?.render) {
// DEPRECATED
const rootProps = data.root.props || data.root;
Expand Down
11 changes: 7 additions & 4 deletions packages/core/reducer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,16 @@ export const setAction = (state: AppState, action: SetAction) => {
return { ...state, ...action.state(state) };
};

export const createReducer = ({
export function createReducer<
UserConfig extends Config<any, any, any> = Config<any, any, any>
>({
config,
record,
}: {
config: Config<any>;
config: UserConfig;
record?: (appState: AppState) => void;
}): StateReducer =>
storeInterceptor((state, action) => {
}): StateReducer {
return storeInterceptor((state, action) => {
const data = reduceData(state.data, action, config);
const ui = reduceUi(state.ui, action);

Expand All @@ -66,3 +68,4 @@ export const createReducer = ({

return { data, ui };
}, record);
}
2 changes: 1 addition & 1 deletion packages/core/types/Config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ type Category<ComponentName> = {
export type Config<
Props extends { [key: string]: any } = { [key: string]: any },
RootProps extends DefaultRootProps = DefaultRootProps,
CategoryName extends string = string
CategoryName extends string = any
> = {
categories?: Record<CategoryName, Category<keyof Props>> & {
other?: Category<Props>;
Expand Down

0 comments on commit 1c4b97f

Please sign in to comment.