From 2c5b097242f4e403e68b5ba57069f01cd7baf5e3 Mon Sep 17 00:00:00 2001 From: Johannes Obermair <48853629+johnnyomair@users.noreply.github.com> Date: Tue, 12 Dec 2023 12:24:54 +0100 Subject: [PATCH] Infer additional item fields in `BlocksBlock` and `ListBlock` (#1481) Additional fields in the `item` prop of `AdditionalItemContextMenuItems` and `AdditionalItemContent` will be typed correctly if the `additionalItemFields` option is strongly typed. --- .changeset/silly-lemons-compete.md | 7 + .../admin/src/common/blocks/LinkListBlock.tsx | 4 - demo/admin/src/pages/PageContentBlock.tsx | 4 - .../userGroupAdditionalItemFields.ts | 4 +- .../blocks/factories/createBlocksBlock.tsx | 198 +++++++++++------- .../src/blocks/factories/createListBlock.tsx | 151 +++++++------ .../listBlock/createUseAdminComponent.tsx | 4 +- 7 files changed, 221 insertions(+), 151 deletions(-) create mode 100644 .changeset/silly-lemons-compete.md diff --git a/.changeset/silly-lemons-compete.md b/.changeset/silly-lemons-compete.md new file mode 100644 index 0000000000..66c90b5723 --- /dev/null +++ b/.changeset/silly-lemons-compete.md @@ -0,0 +1,7 @@ +--- +"@comet/blocks-admin": patch +--- + +Infer additional item fields in `BlocksBlock` and `ListBlock` + +Additional fields in the `item` prop of `AdditionalItemContextMenuItems` and `AdditionalItemContent` will be typed correctly if the `additionalItemFields` option is strongly typed. diff --git a/demo/admin/src/common/blocks/LinkListBlock.tsx b/demo/admin/src/common/blocks/LinkListBlock.tsx index 9a1ce34f68..0b183c681b 100644 --- a/demo/admin/src/common/blocks/LinkListBlock.tsx +++ b/demo/admin/src/common/blocks/LinkListBlock.tsx @@ -17,13 +17,9 @@ export const LinkListBlock = createListBlock({ ...userGroupAdditionalItemFields, }, AdditionalItemContextMenuItems: ({ item, onChange, onMenuClose }) => { - // TODO fix typing: infer additional fields somehow - // @ts-expect-error missing additional field return ; }, AdditionalItemContent: ({ item }) => { - // TODO fix typing: infer additional fields somehow - // @ts-expect-error missing additional field return ; }, }); diff --git a/demo/admin/src/pages/PageContentBlock.tsx b/demo/admin/src/pages/PageContentBlock.tsx index f8a1714d6b..4a1373ebe8 100644 --- a/demo/admin/src/pages/PageContentBlock.tsx +++ b/demo/admin/src/pages/PageContentBlock.tsx @@ -37,13 +37,9 @@ export const PageContentBlock = createBlocksBlock({ ...userGroupAdditionalItemFields, }, AdditionalItemContextMenuItems: ({ item, onChange, onMenuClose }) => { - // TODO fix typing: infer additional fields somehow - // @ts-expect-error missing additional field return ; }, AdditionalItemContent: ({ item }) => { - // TODO fix typing: infer additional fields somehow - // @ts-expect-error missing additional field return ; }, }); diff --git a/demo/admin/src/userGroups/userGroupAdditionalItemFields.ts b/demo/admin/src/userGroups/userGroupAdditionalItemFields.ts index a185519609..13d31d39a3 100644 --- a/demo/admin/src/userGroups/userGroupAdditionalItemFields.ts +++ b/demo/admin/src/userGroups/userGroupAdditionalItemFields.ts @@ -1,6 +1,8 @@ +import { GQLUserGroup } from "@src/graphql.generated"; + const userGroupAdditionalItemFields = { userGroup: { - defaultValue: "All", + defaultValue: "All" as GQLUserGroup, }, }; diff --git a/packages/admin/blocks-admin/src/blocks/factories/createBlocksBlock.tsx b/packages/admin/blocks-admin/src/blocks/factories/createBlocksBlock.tsx index 855dc6b2b4..5915e941ed 100644 --- a/packages/admin/blocks-admin/src/blocks/factories/createBlocksBlock.tsx +++ b/packages/admin/blocks-admin/src/blocks/factories/createBlocksBlock.tsx @@ -21,7 +21,14 @@ import { deduplicateBlockDependencies } from "../helpers/deduplicateBlockDepende import { BlockDependency, BlockInterface, BlockState, DispatchSetStateAction, PreviewContent } from "../types"; import { resolveNewState } from "../utils"; -interface BlocksBlockItem { +// Using {} instead of Record because never and unknown are incompatible. +// eslint-disable-next-line @typescript-eslint/ban-types +type DefaultAdditionalItemFields = {}; + +type BlocksBlockItem< + T extends BlockInterface = BlockInterface, + AdditionalItemFields extends Record = DefaultAdditionalItemFields, +> = { [key: string]: unknown; key: string; type: string; @@ -29,63 +36,76 @@ interface BlocksBlockItem { selected: boolean; props: BlockState; slideIn: boolean; -} +} & AdditionalItemFields; -type RemovedBlocksBlockItem = BlocksBlockItem & { removedAt: number }; +type RemovedBlocksBlockItem< + T extends BlockInterface = BlockInterface, + AdditionalItemFields extends Record = DefaultAdditionalItemFields, +> = BlocksBlockItem & { removedAt: number }; -export interface BlocksBlockState { - blocks: BlocksBlockItem[]; +export interface BlocksBlockState = DefaultAdditionalItemFields> { + blocks: BlocksBlockItem[]; } -export interface BlocksBlockFragment { - blocks: { - [key: string]: unknown; - key: string; - type: string; - visible: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - props: any; - }[]; +export interface BlocksBlockFragment = DefaultAdditionalItemFields> { + blocks: Array< + { + [key: string]: unknown; + key: string; + type: string; + visible: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + props: any; + } & AdditionalItemFields + >; } -export interface BlocksBlockOutput { - blocks: { - [key: string]: unknown; - key: string; - type: string; - visible: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - props: any; - }[]; +export interface BlocksBlockOutput = DefaultAdditionalItemFields> { + blocks: Array< + { + [key: string]: unknown; + key: string; + type: string; + visible: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + props: any; + } & AdditionalItemFields + >; } type BlockType = string; -interface AdditionalItemField { +interface BlocksBlockAdditionalItemField { defaultValue: Value; } -interface CreateBlocksBlockOptions { +interface CreateBlocksBlockOptions> { name: string; displayName?: React.ReactNode; supportedBlocks: Record; - additionalItemFields?: Record; + additionalItemFields?: { + [Key in keyof AdditionalItemFields]: BlocksBlockAdditionalItemField; + }; AdditionalItemContextMenuItems?: React.FunctionComponent<{ - item: BlocksBlockItem; - onChange: (item: BlocksBlockItem) => void; + item: BlocksBlockItem; + onChange: (item: BlocksBlockItem) => void; onMenuClose: () => void; }>; - AdditionalItemContent?: React.FunctionComponent<{ item: BlocksBlockItem }>; + AdditionalItemContent?: React.FunctionComponent<{ item: BlocksBlockItem }>; } -export function createBlocksBlock({ +export function createBlocksBlock = DefaultAdditionalItemFields>({ supportedBlocks, name, displayName = , - additionalItemFields = {}, + additionalItemFields, AdditionalItemContextMenuItems, AdditionalItemContent, -}: CreateBlocksBlockOptions): BlockInterface { +}: CreateBlocksBlockOptions): BlockInterface< + BlocksBlockFragment, + BlocksBlockState, + BlocksBlockOutput +> { if (Object.keys(supportedBlocks).length === 0) { throw new Error("Blocks block with no supported block is not allowed. Please specify at least two supported blocks."); } @@ -102,7 +122,11 @@ export function createBlocksBlock({ return Object.entries(supportedBlocks).find(([, block]) => block.name === targetBlock.name)?.[0] ?? null; } - const BlocksBlock: BlockInterface = { + const BlocksBlock: BlockInterface< + BlocksBlockFragment, + BlocksBlockState, + BlocksBlockOutput + > = { ...createBlockSkeleton(), name, @@ -112,21 +136,21 @@ export function createBlocksBlock({ defaultValues: () => ({ blocks: [] }), input2State: (input) => { - const blocks: BlocksBlockItem[] = []; + const blocks: BlocksBlockItem[] = []; - for (const item of input.blocks) { - const block = blockForType(item.type); + for (const child of input.blocks) { + const block = blockForType(child.type); if (!block) { // eslint-disable-next-line no-console - console.warn(`Unknown block type "${item.type}"`); + console.warn(`Unknown block type "${child.type}"`); continue; } blocks.push({ - ...item, - props: block.input2State(item.props), - ...Object.keys(additionalItemFields).reduce((fields, field) => ({ ...fields, [field]: item[field] }), {}), + ...child, + props: block.input2State(child.props), + ...Object.keys(additionalItemFields ?? {}).reduce((fields, field) => ({ ...fields, [field]: child[field] }), {}), selected: false, slideIn: false, }); @@ -136,40 +160,45 @@ export function createBlocksBlock({ blocks, }; }, - state2Output: (s) => { + + state2Output: (state) => { return { - blocks: s.blocks.map((c) => { - const block = blockForType(c.type); + blocks: state.blocks.map((child) => { + const block = blockForType(child.type); if (!block) { - throw new Error(`No Block found for type ${c.type}`); // for TS + throw new Error(`No Block found for type ${child.type}`); // for TS } return { - key: c.key, - visible: c.visible, - type: c.type, - props: block.state2Output(c.props), - ...Object.keys(additionalItemFields).reduce((fields, field) => ({ ...fields, [field]: c[field] }), {}), + key: child.key, + visible: child.visible, + type: child.type, + props: block.state2Output(child.props), + // Type cast to suppress "'AdditionalItemFields' could be instantiated with a different subtype of constraint 'Record'" error + ...(Object.keys(additionalItemFields ?? {}).reduce( + (fields, field) => ({ ...fields, [field]: child[field] }), + {}, + ) as AdditionalItemFields), }; }), }; }, output2State: async (output, context) => { - const state: BlocksBlockState = { + const state: BlocksBlockState = { blocks: [], }; - for (const item of output.blocks) { - const block = blockForType(item.type); + for (const child of output.blocks) { + const block = blockForType(child.type); if (!block) { - throw new Error(`No Block found for type ${item.type}`); + throw new Error(`No Block found for type ${child.type}`); } state.blocks.push({ slideIn: false, - ...item, - props: await block.output2State(item.props, context), + ...child, + props: await block.output2State(child.props, context), selected: false, }); } @@ -181,20 +210,24 @@ export function createBlocksBlock({ return { adminRoute: previewCtx.parentUrl, blocks: state.blocks - .filter((c) => (previewCtx.showVisibleOnly ? c.visible : true)) // depending on context show all blocks or only visible blocks - .map((c) => { - const blockAdminRoute = `${previewCtx.parentUrl}/${c.key}/blocks`; - const block = blockForType(c.type); + .filter((child) => (previewCtx.showVisibleOnly ? child.visible : true)) // depending on context show all blocks or only visible blocks + .map((child) => { + const blockAdminRoute = `${previewCtx.parentUrl}/${child.key}/blocks`; + const block = blockForType(child.type); if (!block) { - throw new Error(`No Block found for type ${c.type}`); // for TS + throw new Error(`No Block found for type ${child.type}`); // for TS } return { - key: c.key, - visible: c.visible, - type: c.type, + key: child.key, + visible: child.visible, + type: child.type, adminRoute: blockAdminRoute, - props: block.createPreviewState(c.props, { ...previewCtx, parentUrl: blockAdminRoute }), - ...Object.keys(additionalItemFields).reduce((fields, field) => ({ ...fields, [field]: c[field] }), {}), + props: block.createPreviewState(child.props, { ...previewCtx, parentUrl: blockAdminRoute }), + // Type cast to suppress "'AdditionalItemFields' could be instantiated with a different subtype of constraint 'Record'" error + ...(Object.keys(additionalItemFields ?? {}).reduce( + (fields, field) => ({ ...fields, [field]: child[field] }), + {}, + ) as AdditionalItemFields), }; }), adminMeta: { route: previewCtx.parentUrl }, @@ -233,15 +266,15 @@ export function createBlocksBlock({ }, replaceDependenciesInOutput: (output, replacements) => { - const newOutput: BlocksBlockOutput = { blocks: [] }; + const newOutput: BlocksBlockOutput = { blocks: [] }; - for (const c of output.blocks) { - const block = blockForType(c.type); + for (const child of output.blocks) { + const block = blockForType(child.type); if (!block) { - throw new Error(`No Block found for type ${c.type}`); + throw new Error(`No Block found for type ${child.type}`); } - newOutput.blocks.push({ ...c, props: block.replaceDependenciesInOutput(c.props, replacements) }); + newOutput.blocks.push({ ...child, props: block.replaceDependenciesInOutput(child.props, replacements) }); } return newOutput; @@ -279,7 +312,7 @@ export function createBlocksBlock({ }, [state.blocks, updateState]); const handleUndoClick = React.useCallback( - (removedBlocks: RemovedBlocksBlockItem[] | undefined) => { + (removedBlocks: RemovedBlocksBlockItem[] | undefined) => { if (!removedBlocks) { return; } @@ -287,7 +320,9 @@ export function createBlocksBlock({ updateState((prevState) => { const blocks = [...prevState.blocks]; removedBlocks?.forEach((removedBlock) => { - const { removedAt, ...block } = removedBlock; + const { removedAt } = removedBlock; + const block: BlocksBlockItem = { ...removedBlock }; + delete block.removedAt; blocks.splice(removedAt, 0, block); }); @@ -362,14 +397,17 @@ export function createBlocksBlock({ if (!block) { throw new Error(`No Block found for type ${type}`); } - const newItem: BlocksBlockItem = { + const newItem: BlocksBlockItem = { key, type, visible: true, selected: false, props: block.defaultValues(), slideIn: true, - ...Object.entries(additionalItemFields).reduce((fields, [field, { defaultValue }]) => ({ ...fields, [field]: defaultValue }), {}), + ...(Object.entries(additionalItemFields ?? {}).reduce( + (fields, [field, { defaultValue }]) => ({ ...fields, [field]: defaultValue }), + {}, + ) as AdditionalItemFields), }; const newBlocks = [...state.blocks]; @@ -416,7 +454,7 @@ export function createBlocksBlock({ const { content } = response; updateState((prevState) => { - const newBlocks: BlocksBlockItem[] = content.map((block) => { + const newBlocks: BlocksBlockItem[] = content.map((block) => { const type = typeForBlock(block); if (!type) { @@ -430,7 +468,8 @@ export function createBlocksBlock({ visible: block.visible, props: block.state, slideIn: true, - ...block.additionalFields, + // Type cast to suppress "'AdditionalItemFields' could be instantiated with a different subtype of constraint 'Record'" error + ...(block.additionalFields as AdditionalItemFields), }; }); @@ -491,7 +530,10 @@ export function createBlocksBlock({ name: blockInterface.name, visible: block.visible, state: block.props, - additionalFields: Object.keys(additionalItemFields).reduce((fields, field) => ({ ...fields, [field]: block[field] }), {}), + additionalFields: Object.keys(additionalItemFields ?? {}).reduce( + (fields, field) => ({ ...fields, [field]: block[field] }), + {}, + ), }; }); @@ -613,7 +655,7 @@ export function createBlocksBlock({ name: block.name, visible: data.visible, state: data.props, - additionalFields: Object.keys(additionalItemFields).reduce( + additionalFields: Object.keys(additionalItemFields ?? {}).reduce( (fields, field) => ({ ...fields, [field]: data[field] }), {}, ), diff --git a/packages/admin/blocks-admin/src/blocks/factories/createListBlock.tsx b/packages/admin/blocks-admin/src/blocks/factories/createListBlock.tsx index 57617d5ae9..cd29294587 100644 --- a/packages/admin/blocks-admin/src/blocks/factories/createListBlock.tsx +++ b/packages/admin/blocks-admin/src/blocks/factories/createListBlock.tsx @@ -20,44 +20,52 @@ import { deduplicateBlockDependencies } from "../helpers/deduplicateBlockDepende import { BlockDependency, BlockInterface, BlockState, PreviewContent } from "../types"; import { createUseAdminComponent } from "./listBlock/createUseAdminComponent"; -export interface ListBlockItem { +// Using {} instead of Record because never and unknown are incompatible. +// eslint-disable-next-line @typescript-eslint/ban-types +type DefaultAdditionalItemFields = {}; + +export type ListBlockItem = DefaultAdditionalItemFields> = { [key: string]: unknown; key: string; visible: boolean; props: BlockState; selected: boolean; slideIn: boolean; -} +} & AdditionalItemFields; -export interface ListBlockState { - blocks: ListBlockItem[]; +export interface ListBlockState = DefaultAdditionalItemFields> { + blocks: ListBlockItem[]; } -export interface ListBlockFragment { - blocks: Array<{ - [key: string]: unknown; - key: string; - visible: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - props: any; - }>; +export interface ListBlockFragment = DefaultAdditionalItemFields> { + blocks: Array< + { + [key: string]: unknown; + key: string; + visible: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + props: any; + } & AdditionalItemFields + >; } -export interface ListBlockOutput { - blocks: Array<{ - [key: string]: unknown; - key: string; - visible: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - props: any; - }>; +export interface ListBlockOutput = DefaultAdditionalItemFields> { + blocks: Array< + { + [key: string]: unknown; + key: string; + visible: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + props: any; + } & AdditionalItemFields + >; } -export interface AdditionalItemField { +export interface ListBlockAdditionalItemField { defaultValue: Value; } -interface CreateListBlockOptions { +interface CreateListBlockOptions> { name: string; displayName?: React.ReactNode; itemName?: React.ReactNode; @@ -65,16 +73,18 @@ interface CreateListBlockOptions { block: T; maxVisibleBlocks?: number; createDefaultListEntry?: boolean; - additionalItemFields?: Record; + additionalItemFields?: { + [Key in keyof AdditionalItemFields]: ListBlockAdditionalItemField; + }; AdditionalItemContextMenuItems?: React.FunctionComponent<{ - item: ListBlockItem; - onChange: (item: ListBlockItem) => void; + item: ListBlockItem; + onChange: (item: ListBlockItem) => void; onMenuClose: () => void; }>; - AdditionalItemContent?: React.FunctionComponent<{ item: ListBlockItem }>; + AdditionalItemContent?: React.FunctionComponent<{ item: ListBlockItem }>; } -export function createListBlock({ +export function createListBlock = DefaultAdditionalItemFields>({ name, block, displayName = , @@ -82,12 +92,20 @@ export function createListBlock({ itemsName = , maxVisibleBlocks, createDefaultListEntry, - additionalItemFields = {}, + additionalItemFields, AdditionalItemContextMenuItems, AdditionalItemContent, -}: CreateListBlockOptions): BlockInterface, ListBlockOutput> { +}: CreateListBlockOptions): BlockInterface< + ListBlockFragment, + ListBlockState, + ListBlockOutput +> { const useAdminComponent = createUseAdminComponent({ block, maxVisibleBlocks, additionalItemFields }); - const BlockListBlock: BlockInterface, ListBlockOutput> = { + const BlockListBlock: BlockInterface< + ListBlockFragment, + ListBlockState, + ListBlockOutput + > = { ...createBlockSkeleton(), name, @@ -103,10 +121,11 @@ export function createListBlock({ props: block.defaultValues(), selected: false, slideIn: false, - ...Object.entries(additionalItemFields).reduce( + // Type cast to suppress "'AdditionalItemFields' could be instantiated with a different subtype of constraint 'Record'" error + ...(Object.entries(additionalItemFields ?? {}).reduce( (fields, [field, { defaultValue }]) => ({ ...fields, [field]: defaultValue }), {}, - ), + ) as AdditionalItemFields), }, ] : [], @@ -114,16 +133,16 @@ export function createListBlock({ category: block.category, - input2State: (s) => { + input2State: (input) => { return { - ...s, - blocks: s.blocks.map((c) => { + ...input, + blocks: input.blocks.map((child) => { return { - ...c, - key: c.key, - visible: c.visible, - props: block.input2State(c.props), - ...Object.keys(additionalItemFields).reduce((fields, field) => ({ ...fields, [field]: c[field] }), {}), + ...child, + key: child.key, + visible: child.visible, + props: block.input2State(child.props), + ...Object.keys(additionalItemFields ?? {}).reduce((fields, field) => ({ ...fields, [field]: child[field] }), {}), selected: false, slideIn: false, }; @@ -131,29 +150,33 @@ export function createListBlock({ }; }, - state2Output: (s) => { + state2Output: (state) => { return { - blocks: s.blocks.map((c) => { + blocks: state.blocks.map((child) => { return { - key: c.key, - visible: c.visible, - props: block.state2Output(c.props), - ...Object.keys(additionalItemFields).reduce((fields, field) => ({ ...fields, [field]: c[field] }), {}), + key: child.key, + visible: child.visible, + props: block.state2Output(child.props), + // Type cast to suppress "'AdditionalItemFields' could be instantiated with a different subtype of constraint 'Record'" error + ...(Object.keys(additionalItemFields ?? {}).reduce( + (fields, field) => ({ ...fields, [field]: child[field] }), + {}, + ) as AdditionalItemFields), }; }), }; }, output2State: async (output, context) => { - const state: ListBlockState = { + const state: ListBlockState = { blocks: [], }; - for (const item of output.blocks) { + for (const child of output.blocks) { state.blocks.push({ slideIn: false, - ...item, - props: await block.output2State(item.props, context), + ...child, + props: await block.output2State(child.props, context), selected: false, }); } @@ -165,15 +188,19 @@ export function createListBlock({ return { adminRoute: previewCtx.parentUrl, blocks: state.blocks - .filter((c) => (previewCtx.showVisibleOnly ? c.visible : true)) // depending on context show all blocks or only visible blocks - .map((c) => { - const blockAdminRoute = `${previewCtx.parentUrl}/${c.key}/edit`; + .filter((child) => (previewCtx.showVisibleOnly ? child.visible : true)) // depending on context show all blocks or only visible blocks + .map((child) => { + const blockAdminRoute = `${previewCtx.parentUrl}/${child.key}/edit`; return { - key: c.key, - visible: c.visible, - props: block.createPreviewState(c.props, { ...previewCtx, parentUrl: blockAdminRoute }), - ...Object.keys(additionalItemFields).reduce((fields, field) => ({ ...fields, [field]: c[field] }), {}), + key: child.key, + visible: child.visible, + props: block.createPreviewState(child.props, { ...previewCtx, parentUrl: blockAdminRoute }), + // Type cast to suppress "'AdditionalItemFields' could be instantiated with a different subtype of constraint 'Record'" error + ...(Object.keys(additionalItemFields ?? {}).reduce( + (fields, field) => ({ ...fields, [field]: child[field] }), + {}, + ) as AdditionalItemFields), adminRoute: blockAdminRoute, adminMeta: { route: blockAdminRoute }, }; @@ -200,12 +227,12 @@ export function createListBlock({ }, replaceDependenciesInOutput: (output, replacements) => { - const newOutput: ListBlockOutput = { ...output, blocks: [] }; + const newOutput: ListBlockOutput = { ...output, blocks: [] }; - for (const c of output.blocks) { + for (const child of output.blocks) { newOutput.blocks.push({ - ...c, - props: block.replaceDependenciesInOutput(c.props, replacements), + ...child, + props: block.replaceDependenciesInOutput(child.props, replacements), }); } @@ -346,7 +373,7 @@ export function createListBlock({ name: block.name, visible: data.visible, state: data.props, - additionalFields: Object.keys(additionalItemFields).reduce( + additionalFields: Object.keys(additionalItemFields ?? {}).reduce( (fields, field) => ({ ...fields, [field]: data[field] }), {}, ), diff --git a/packages/admin/blocks-admin/src/blocks/factories/listBlock/createUseAdminComponent.tsx b/packages/admin/blocks-admin/src/blocks/factories/listBlock/createUseAdminComponent.tsx index 2cb42477d6..b8a1ea71e9 100644 --- a/packages/admin/blocks-admin/src/blocks/factories/listBlock/createUseAdminComponent.tsx +++ b/packages/admin/blocks-admin/src/blocks/factories/listBlock/createUseAdminComponent.tsx @@ -7,12 +7,12 @@ import { CannotPasteBlockDialog } from "../../../clipboard/CannotPasteBlockDialo import { ClipboardContent, useBlockClipboard } from "../../../clipboard/useBlockClipboard"; import { BlockAdminComponentProps, BlockInterface, BlockState, DispatchSetStateAction } from "../../types"; import { resolveNewState } from "../../utils"; -import { AdditionalItemField, ListBlockState } from "../createListBlock"; +import { ListBlockAdditionalItemField, ListBlockState } from "../createListBlock"; interface CreateListBlockUseAdminComponentOptions { block: T; maxVisibleBlocks?: number; - additionalItemFields?: Record; + additionalItemFields?: Record; } type ListBlockUseAdminComponentProps = BlockAdminComponentProps>;