From 0110ff737dbf6072c2ce93279e83564eec5b3a71 Mon Sep 17 00:00:00 2001 From: Martin Barri Date: Sat, 19 Oct 2024 00:21:03 +0200 Subject: [PATCH] feat(react-utils): pass `blockType` to block, `context` always as object & export new types - `blockType` is now passed to block component. - Adapter argument `additionalData` has been renamed to `context` - Adapter argument `context` is now always an object containing `index` & additinal keys one provides to the renderer. - Export new `BlockTypeMap` & `BlockAdapter` types. --- .changeset/nice-beers-kneel.md | 5 ++ .changeset/strange-boxes-fail.md | 5 ++ .changeset/young-suns-beam.md | 5 ++ .../react-utils/src/createRenderBlock.tsx | 57 +++++++++++-------- 4 files changed, 49 insertions(+), 23 deletions(-) create mode 100644 .changeset/nice-beers-kneel.md create mode 100644 .changeset/strange-boxes-fail.md create mode 100644 .changeset/young-suns-beam.md diff --git a/.changeset/nice-beers-kneel.md b/.changeset/nice-beers-kneel.md new file mode 100644 index 00000000..f70a2fe4 --- /dev/null +++ b/.changeset/nice-beers-kneel.md @@ -0,0 +1,5 @@ +--- +'@noaignite/react-utils': minor +--- + +createRenderBlock - `blockType` is now passed to block component diff --git a/.changeset/strange-boxes-fail.md b/.changeset/strange-boxes-fail.md new file mode 100644 index 00000000..c28b1259 --- /dev/null +++ b/.changeset/strange-boxes-fail.md @@ -0,0 +1,5 @@ +--- +'@noaignite/react-utils': minor +--- + +createRenderBlock - adapter `context` argument (prev `additionalData`) is now always an object diff --git a/.changeset/young-suns-beam.md b/.changeset/young-suns-beam.md new file mode 100644 index 00000000..17b1e47d --- /dev/null +++ b/.changeset/young-suns-beam.md @@ -0,0 +1,5 @@ +--- +'@noaignite/react-utils': minor +--- + +createRenderBlock - export new `BlockTypeMap` & `BlockAdapter` types diff --git a/packages/react-utils/src/createRenderBlock.tsx b/packages/react-utils/src/createRenderBlock.tsx index 029a180d..8fac129b 100644 --- a/packages/react-utils/src/createRenderBlock.tsx +++ b/packages/react-utils/src/createRenderBlock.tsx @@ -35,8 +35,8 @@ import { ErrorBoundary, type ErrorBoundaryProps } from './ErrorBoundary' * } * * const adapters = { - * Hero: async (props: HeroData['props'], additionalData, globals): Promise => { - * const { locale } = additionalData + * Hero: async (props: HeroData['props'], context, globals): Promise => { + * const { locale } = context * const { LinkComponent } = globals * * const data = (await fetch( `https://domain.com/${locale}/posts/1`).then((res) => { @@ -76,28 +76,40 @@ import { ErrorBoundary, type ErrorBoundaryProps } from './ErrorBoundary' */ export const createRenderBlock = _createRenderBlock() +/** + * The interface that block data needs to conform to. + */ +export interface BlockTypeMap { + blockType: string + props: Record +} + +/** + * Type helper to set up a block adapter. + */ +export type BlockAdapter< + TInProps extends Record, + TOutProps extends Record, + TContext extends Record, + TGlobals extends Record, +> = (props: TInProps, context: TContext, globals: TGlobals) => Promise | TOutProps + /** * A wrapper around `createRenderBlock` to give the posibility to define the - * `TAdditionalData` type. This is currently a workaround as there is - * currently no way in typescript to partially provide generics while having - * the rest infer. + * `TContext` interface. This is currently a workaround as there is currently + * no way in typescript to partially provide generics while having the rest + * self-infer. * * @see https://github.com/microsoft/TypeScript/issues/10571 * @see https://github.com/microsoft/TypeScript/pull/26349 */ -export function _createRenderBlock< - TAdditionalData extends number | { index: number; [key: string]: unknown }, ->() { +export function _createRenderBlock() { return function __createRenderBlock< TBlocks extends Record>, TGlobals extends Record, TAdapters extends | { - [K in keyof TBlocks]?: ( - props: any, - additionalData: TAdditionalData, - globals: TGlobals, - ) => Promise> | PropsFrom + [K in keyof TBlocks]?: BlockAdapter, TContext, TGlobals> } | undefined, TDefaultProps extends @@ -126,19 +138,18 @@ export function _createRenderBlock< blockType: TBlockType props: keyof TAdapters extends never ? PropsFrom : any }, - indexOrAdditionalData: TAdditionalData, + indexOrContext: number | TContext, ) { const { blockType, props } = data - const { index } = - typeof indexOrAdditionalData === 'number' - ? { index: indexOrAdditionalData } - : indexOrAdditionalData + const context = ( + typeof indexOrContext === 'number' ? { index: indexOrContext } : indexOrContext + ) as TContext if (typeof blockType !== 'string') { if (process.env.NODE_ENV !== 'production') { console.error( 'renderBlock: Block with index `%s` is missing the property `blockType`.', - index, + context.index, ) } return null @@ -148,7 +159,7 @@ export function _createRenderBlock< if (process.env.NODE_ENV !== 'production') { console.error( 'renderBlock: Block with index `%s` and blockType `%s` could not find a matching component.', - index, + context.index, blockType, ) } @@ -163,14 +174,14 @@ export function _createRenderBlock< if (adapters) { const adapter = adapters[blockType] if (typeof adapter === 'function') { - componentProps = await adapter(componentProps, indexOrAdditionalData, globals) + componentProps = await adapter(componentProps, context, globals) } } return ( - + - + )