From aedd401dd415e9d7dc1cbd6e33e59f5264180374 Mon Sep 17 00:00:00 2001 From: Chris Villa Date: Mon, 1 Apr 2024 16:35:50 +0200 Subject: [PATCH] feat: allow data prop to accept an empty object This is a long-standing API tidy-up to enable partial Data objects to be provided to Puck for easier instantiation. --- README.md | 5 +---- .../pages/docs/api-reference/components/puck.mdx | 2 +- .../docs/api-reference/components/render.mdx | 8 ++++---- .../api-reference/functions/resolve-all-data.mdx | 8 ++++---- .../api-reference/functions/transform-props.mdx | 2 +- apps/docs/pages/docs/getting-started.mdx | 5 +---- packages/core/components/Puck/index.tsx | 5 +++-- packages/core/components/Render/index.tsx | 14 ++++++++++---- packages/core/lib/default-data.ts | 7 +++++++ packages/core/lib/resolve-all-data.ts | 11 +++++++---- packages/core/lib/transform-props.ts | 15 +++++++++------ 11 files changed, 48 insertions(+), 34 deletions(-) create mode 100644 packages/core/lib/default-data.ts diff --git a/README.md b/README.md index 4151e9b319..5eef21f337 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,7 @@ const config = { }; // Describe the initial data -const initialData = { - content: [], - root: {}, -}; +const initialData = {}; // Save the data to your database const save = (data) => {}; diff --git a/apps/docs/pages/docs/api-reference/components/puck.mdx b/apps/docs/pages/docs/api-reference/components/puck.mdx index bcd9c3708a..357b0776e5 100644 --- a/apps/docs/pages/docs/api-reference/components/puck.mdx +++ b/apps/docs/pages/docs/api-reference/components/puck.mdx @@ -28,7 +28,7 @@ export function Editor() { | Param | Example | Type | Status | | ------------------------------- | -------------------------------------- | -------------------------------------------------- | ------------ | | [`config`](#config) | `config: { components: {} }` | [Config](/docs/api-reference/configuration/config) | Required | -| [`data`](#data) | `data: { content: [], root: {} }` | [Data](/docs/api-reference/data) | Required | +| [`data`](#data) | `data: {}` | [Data](/docs/api-reference/data) | Required | | [`dnd`](#dnd) | `dnd: {}` | [DndConfig](#dnd-params) | - | | [`children`](#children) | `children: ` | ReactNode | - | | [`headerPath`](#headerpath) | `headerPath: "/my-page"` | String | - | diff --git a/apps/docs/pages/docs/api-reference/components/render.mdx b/apps/docs/pages/docs/api-reference/components/render.mdx index 1085db960a..cc0d2dc6da 100644 --- a/apps/docs/pages/docs/api-reference/components/render.mdx +++ b/apps/docs/pages/docs/api-reference/components/render.mdx @@ -16,10 +16,10 @@ export function Example() { ## Props -| Param | Example | Type | Status | -| ------------------- | --------------------------------- | ------------------------------------ | -------- | -| [`config`](#config) | `config: { components: {} }` | [Config](/docs/api-reference/config) | Required | -| [`data`](#data) | `data: { content: [], root: {} }` | [Data](/docs/api-reference/data) | Required | +| Param | Example | Type | Status | +| ------------------- | ---------------------------- | ------------------------------------ | -------- | +| [`config`](#config) | `config: { components: {} }` | [Config](/docs/api-reference/config) | Required | +| [`data`](#data) | `data: {}` | [Data](/docs/api-reference/data) | Required | ## Required props diff --git a/apps/docs/pages/docs/api-reference/functions/resolve-all-data.mdx b/apps/docs/pages/docs/api-reference/functions/resolve-all-data.mdx index 4a79a36ce6..07448a4650 100644 --- a/apps/docs/pages/docs/api-reference/functions/resolve-all-data.mdx +++ b/apps/docs/pages/docs/api-reference/functions/resolve-all-data.mdx @@ -16,10 +16,10 @@ This is useful if you need to run your resolvers before passing your data to [`< ## Args -| Param | Example | Type | -| -------- | --------------------------- | -------------------------------------------------- | -| `data` | `{ content: {}, root: {} }` | [Data](/docs/api-reference/data) | -| `config` | `{ components: {} }` | [Config](/docs/api-reference/configuration/config) | +| Param | Example | Type | +| -------- | -------------------- | -------------------------------------------------- | +| `data` | `{}` | [Data](/docs/api-reference/data) | +| `config` | `{ components: {} }` | [Config](/docs/api-reference/configuration/config) | ## Returns diff --git a/apps/docs/pages/docs/api-reference/functions/transform-props.mdx b/apps/docs/pages/docs/api-reference/functions/transform-props.mdx index c04a92a630..19bf990921 100644 --- a/apps/docs/pages/docs/api-reference/functions/transform-props.mdx +++ b/apps/docs/pages/docs/api-reference/functions/transform-props.mdx @@ -28,7 +28,7 @@ console.log(updatedData); | Param | Example | Type | | ------------ | -------------------------------------- | -------------------------------- | -| `data` | `{ content: {}, root: {} }` | [Data](/docs/api-reference/data) | +| `data` | `{}` | [Data](/docs/api-reference/data) | | `transforms` | `{ HeadingBlock: (props) => (props) }` | Object | ### `data` diff --git a/apps/docs/pages/docs/getting-started.mdx b/apps/docs/pages/docs/getting-started.mdx index 1e018a25b5..1d1a620372 100644 --- a/apps/docs/pages/docs/getting-started.mdx +++ b/apps/docs/pages/docs/getting-started.mdx @@ -37,10 +37,7 @@ const config = { }; // Describe the initial data -const initialData = { - content: [], - root: {}, -}; +const initialData = {}; // Save the data to your database const save = (data) => {}; diff --git a/packages/core/components/Puck/index.tsx b/packages/core/components/Puck/index.tsx index 7eeadf337c..7fd42e4e36 100644 --- a/packages/core/components/Puck/index.tsx +++ b/packages/core/components/Puck/index.tsx @@ -71,7 +71,7 @@ export function Puck({ }: { children?: ReactNode; config: UserConfig; - data: Data; + data: Partial; ui?: Partial; onChange?: (data: Data) => void; onPublish?: (data: Data) => void; @@ -147,7 +147,7 @@ export function Puck({ } // DEPRECATED - const rootProps = initialData.root.props || initialData.root; + const rootProps = initialData?.root?.props || initialData.root || {}; const defaultedRootProps = { ...config.root?.defaultProps, @@ -159,6 +159,7 @@ export function Puck({ data: { ...initialData, root: defaultedRootProps, + content: initialData.content || [], }, ui: { ...initial, diff --git a/packages/core/components/Render/index.tsx b/packages/core/components/Render/index.tsx index 9d43af76c8..f987a85b39 100644 --- a/packages/core/components/Render/index.tsx +++ b/packages/core/components/Render/index.tsx @@ -9,15 +9,21 @@ export function Render({ data, }: { config: UserConfig; - data: Data; + data: Partial; }) { + const defaultedData = { + ...data, + root: data.root || {}, + content: data.content || [], + }; + // DEPRECATED - const rootProps = data.root.props || data.root; + const rootProps = defaultedData.root.props || defaultedData.root; const title = rootProps?.title || ""; if (config.root?.render) { return ( - + ({ } return ( - + ); diff --git a/packages/core/lib/default-data.ts b/packages/core/lib/default-data.ts new file mode 100644 index 0000000000..97c8005888 --- /dev/null +++ b/packages/core/lib/default-data.ts @@ -0,0 +1,7 @@ +import { Data } from "../types/Config"; + +export const defaultData = (data: Partial) => ({ + ...data, + root: data.root || {}, + content: data.content || [], +}); diff --git a/packages/core/lib/resolve-all-data.ts b/packages/core/lib/resolve-all-data.ts index 6952241a62..5fa6c4bff3 100644 --- a/packages/core/lib/resolve-all-data.ts +++ b/packages/core/lib/resolve-all-data.ts @@ -1,14 +1,17 @@ import { Config, Data, MappedItem } from "../types/Config"; import { resolveAllComponentData } from "./resolve-component-data"; import { resolveRootData } from "./resolve-root-data"; +import { defaultData } from "./default-data"; export async function resolveAllData( - data: Data, + data: Partial, config: Config, onResolveStart?: (item: MappedItem) => void, onResolveEnd?: (item: MappedItem) => void ) { - const dynamicRoot = await resolveRootData(data, config); + const defaultedData = defaultData(data); + + const dynamicRoot = await resolveRootData(defaultedData, config); const { zones = {} } = data; @@ -26,10 +29,10 @@ export async function resolveAllData( } return { - ...data, + ...defaultedData, root: dynamicRoot, content: await resolveAllComponentData( - data.content, + defaultedData.content, config, onResolveStart, onResolveEnd diff --git a/packages/core/lib/transform-props.ts b/packages/core/lib/transform-props.ts index 7afbb0d19c..23c6a24b0b 100644 --- a/packages/core/lib/transform-props.ts +++ b/packages/core/lib/transform-props.ts @@ -1,4 +1,5 @@ import { Data, DefaultComponentProps, DefaultRootProps } from "../types/Config"; +import { defaultData } from "./default-data"; type PropTransform< Props extends DefaultComponentProps = DefaultComponentProps, @@ -14,7 +15,7 @@ type PropTransform< export function transformProps< Props extends DefaultComponentProps = DefaultComponentProps, RootProps extends DefaultComponentProps = DefaultComponentProps ->(data: Data, propTransforms: PropTransform): Data { +>(data: Partial, propTransforms: PropTransform): Data { const mapItem = (item) => { if (propTransforms[item.type]) { return { @@ -26,11 +27,13 @@ export function transformProps< return item; }; + const defaultedData = defaultData(data); + // DEPRECATED - const rootProps = data.root.props || data.root; - let newRoot = { ...data.root }; + const rootProps = defaultedData.root.props || defaultedData.root; + let newRoot = { ...defaultedData.root }; if (propTransforms["root"]) { - if (data.root.props) { + if (defaultedData.root.props) { newRoot.props = propTransforms["root"](rootProps as any); } else { newRoot = propTransforms["root"](rootProps as any); @@ -38,9 +41,9 @@ export function transformProps< } const afterPropTransforms: Data = { - ...data, + ...defaultedData, root: newRoot, - content: data.content.map(mapItem), + content: defaultedData.content.map(mapItem), zones: Object.keys(data.zones || {}).reduce( (acc, zoneKey) => ({ ...acc,