Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions examples/06-custom-schema/04-pdf-file-block/src/PDF.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,7 @@ import { RiFilePdfFill } from "react-icons/ri";
import "./styles.css";

export const PDFPreview = (
props: Omit<
ReactCustomBlockRenderProps<
FileBlockConfig["type"],
FileBlockConfig["propSchema"],
FileBlockConfig["content"]
>,
"contentRef"
>,
props: Omit<ReactCustomBlockRenderProps<FileBlockConfig>, "contentRef">,
) => {
return (
<embed
Expand Down
71 changes: 27 additions & 44 deletions packages/core/src/schema/blocks/createSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import {
} from "./internal.js";
import {
BlockConfig,
BlockConfigOrCreator,
BlockImplementation,
BlockImplementationOrCreator,
BlockSpec,
LooseBlockSpec,
} from "./types.js";
Expand Down Expand Up @@ -297,18 +299,17 @@ export function createBlockSpec<
const TOptions extends Partial<Record<string, any>> | undefined = undefined,
>(
blockConfigOrCreator: BlockConfig<TName, TProps, TContent>,
blockImplementationOrCreator:
| BlockImplementation<TName, TProps, TContent>
blockImplementationOrCreator: BlockImplementationOrCreator<
BlockConfig<TName, TProps, TContent>,
TOptions
>,
extensionsOrCreator?:
| (ExtensionFactoryInstance | Extension)[]
| (TOptions extends undefined
? () => BlockImplementation<TName, TProps, TContent>
? () => (ExtensionFactoryInstance | Extension)[]
: (
options: Partial<TOptions>,
) => BlockImplementation<TName, TProps, TContent>),
extensionsOrCreator?:
| ExtensionFactoryInstance[]
| (TOptions extends undefined
? () => ExtensionFactoryInstance[]
: (options: Partial<TOptions>) => ExtensionFactoryInstance[]),
) => (ExtensionFactoryInstance | Extension)[]),
): (options?: Partial<TOptions>) => BlockSpec<TName, TProps, TContent>;
export function createBlockSpec<
const TName extends string,
Expand All @@ -318,30 +319,17 @@ export function createBlockSpec<
const TOptions extends Partial<Record<string, any>>,
>(
blockCreator: (options: Partial<TOptions>) => BlockConf,
blockImplementationOrCreator:
| BlockImplementation<
BlockConf["type"],
BlockConf["propSchema"],
BlockConf["content"]
>
blockImplementationOrCreator: BlockImplementationOrCreator<
BlockConf,
TOptions
>,
extensionsOrCreator?:
| (ExtensionFactoryInstance | Extension)[]
| (TOptions extends undefined
? () => BlockImplementation<
BlockConf["type"],
BlockConf["propSchema"],
BlockConf["content"]
>
? () => (ExtensionFactoryInstance | Extension)[]
: (
options: Partial<TOptions>,
) => BlockImplementation<
BlockConf["type"],
BlockConf["propSchema"],
BlockConf["content"]
>),
extensionsOrCreator?:
| ExtensionFactoryInstance[]
| (TOptions extends undefined
? () => ExtensionFactoryInstance[]
: (options: Partial<TOptions>) => ExtensionFactoryInstance[]),
) => (ExtensionFactoryInstance | Extension)[]),
): (
options?: Partial<TOptions>,
) => BlockSpec<
Expand All @@ -355,23 +343,18 @@ export function createBlockSpec<
const TContent extends "inline" | "none",
const TOptions extends Partial<Record<string, any>> | undefined = undefined,
>(
blockConfigOrCreator:
| BlockConfig<TName, TProps, TContent>
| (TOptions extends undefined
? () => BlockConfig<TName, TProps, TContent>
: (options: Partial<TOptions>) => BlockConfig<TName, TProps, TContent>),
blockImplementationOrCreator:
| BlockImplementation<TName, TProps, TContent>
blockConfigOrCreator: BlockConfigOrCreator<TName, TProps, TContent, TOptions>,
blockImplementationOrCreator: BlockImplementationOrCreator<
BlockConfig<TName, TProps, TContent>,
TOptions
>,
extensionsOrCreator?:
| (ExtensionFactoryInstance | Extension)[]
| (TOptions extends undefined
? () => BlockImplementation<TName, TProps, TContent>
? () => (ExtensionFactoryInstance | Extension)[]
: (
options: Partial<TOptions>,
) => BlockImplementation<TName, TProps, TContent>),
extensionsOrCreator?:
| ExtensionFactoryInstance[]
| (TOptions extends undefined
? () => ExtensionFactoryInstance[]
: (options: Partial<TOptions>) => ExtensionFactoryInstance[]),
) => (ExtensionFactoryInstance | Extension)[]),
): (options?: Partial<TOptions>) => BlockSpec<TName, TProps, TContent> {
return (options = {} as TOptions) => {
const blockConfig =
Expand Down
94 changes: 94 additions & 0 deletions packages/core/src/schema/blocks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,34 @@ export interface BlockConfig<
// e.g. tables, alerts (with title & content)
}

/**
* BlockConfigOrCreator is a union type of BlockConfig and a function that returns a BlockConfig.
* This is used to create block configs that can be passed to the createBlockSpec function.
*/
export type BlockConfigOrCreator<
TName extends string = string,
TProps extends PropSchema = PropSchema,
TContent extends "inline" | "none" = "inline" | "none",
TOptions extends Record<string, any> | undefined =
| Record<string, any>
| undefined,
> =
| BlockConfig<TName, TProps, TContent>
| (TOptions extends undefined
? () => BlockConfig<TName, TProps, TContent>
: (options: Partial<TOptions>) => BlockConfig<TName, TProps, TContent>);

/**
* ExtractBlockConfigFromConfigOrCreator is a helper type that extracts the BlockConfig type from a BlockConfigOrCreator.
*/
export type ExtractBlockConfigFromConfigOrCreator<
ConfigOrCreator extends
| BlockConfig<string, PropSchema, "inline" | "none">
| ((...args: any[]) => BlockConfig<string, PropSchema, "inline" | "none">),
> = ConfigOrCreator extends (...args: any[]) => infer Config
? Config
: ConfigOrCreator;

// restrict content to "inline" and "none" only
export type CustomBlockConfig<
T extends string = string,
Expand All @@ -104,6 +132,32 @@ export type BlockSpec<
extensions?: (Extension | ExtensionFactoryInstance)[];
};

/**
* BlockSpecOrCreator is a union type of BlockSpec and a function that returns a BlockSpec.
* This is used to create block specs that can be passed to the createBlockSpec function.
*/
export type BlockSpecOrCreator<
T extends string = string,
PS extends PropSchema = PropSchema,
C extends "inline" | "none" | "table" = "inline" | "none" | "table",
TOptions extends Record<string, any> | undefined =
| Record<string, any>
| undefined,
> =
| BlockSpec<T, PS, C>
| (TOptions extends undefined
? () => BlockSpec<T, PS, C>
: (options: Partial<TOptions>) => BlockSpec<T, PS, C>);

/**
* ExtractBlockSpecFromSpecOrCreator is a helper type that extracts the BlockSpec type from a BlockSpecOrCreator.
*/
export type ExtractBlockSpecFromSpecOrCreator<
SpecOrCreator extends
| BlockSpec<string, PropSchema, "inline" | "none">
| ((...args: any[]) => BlockSpec<string, PropSchema, "inline" | "none">),
> = SpecOrCreator extends (...args: any[]) => infer Spec ? Spec : SpecOrCreator;

/**
* This allows de-coupling the types that we display to users versus the types we expose internally.
*
Expand Down Expand Up @@ -497,6 +551,46 @@ export type BlockImplementation<
parseContent?: (options: { el: HTMLElement; schema: Schema }) => Fragment;
};

/**
* BlockImplementationOrCreator is a union type of BlockImplementation and a function that returns a BlockImplementation.
* This is used to create block implementations that can be passed to the createBlockSpec function.
*/
export type BlockImplementationOrCreator<
ConfigOrCreator extends BlockConfigOrCreator = BlockConfigOrCreator,
TOptions extends Record<string, any> | undefined =
| Record<string, any>
| undefined,
Config extends
ExtractBlockConfigFromConfigOrCreator<ConfigOrCreator> = ExtractBlockConfigFromConfigOrCreator<ConfigOrCreator>,
> =
| BlockImplementation<Config["type"], Config["propSchema"], Config["content"]>
| (TOptions extends undefined
? () => BlockImplementation<
Config["type"],
Config["propSchema"],
Config["content"]
>
: (
options: Partial<TOptions>,
) => BlockImplementation<
Config["type"],
Config["propSchema"],
Config["content"]
>);

/**
* ExtractBlockImplementationFromImplementationOrCreator is a helper type that extracts the BlockImplementation type from a BlockImplementationOrCreator.
*/
export type ExtractBlockImplementationFromImplementationOrCreator<
ImplementationOrCreator extends
| BlockImplementation<string, PropSchema, "inline" | "none">
| ((
...args: any[]
) => BlockImplementation<string, PropSchema, "inline" | "none">),
> = ImplementationOrCreator extends (...args: any[]) => infer Implementation
? Implementation
: ImplementationOrCreator;

// restrict content to "inline" and "none" only
export type CustomBlockImplementation<
T extends string = string,
Expand Down
18 changes: 3 additions & 15 deletions packages/react/src/blocks/Audio/block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@ import { LinkWithCaption } from "../File/helpers/toExternalHTML/LinkWithCaption.

export const AudioPreview = (
props: Omit<
ReactCustomBlockRenderProps<
ReturnType<typeof createAudioBlockConfig>["type"],
ReturnType<typeof createAudioBlockConfig>["propSchema"],
ReturnType<typeof createAudioBlockConfig>["content"]
>,
ReactCustomBlockRenderProps<typeof createAudioBlockConfig>,
"contentRef"
>,
) => {
Expand All @@ -40,11 +36,7 @@ export const AudioPreview = (

export const AudioToExternalHTML = (
props: Omit<
ReactCustomBlockRenderProps<
ReturnType<typeof createAudioBlockConfig>["type"],
ReturnType<typeof createAudioBlockConfig>["propSchema"],
ReturnType<typeof createAudioBlockConfig>["content"]
>,
ReactCustomBlockRenderProps<typeof createAudioBlockConfig>,
"contentRef"
>,
) => {
Expand Down Expand Up @@ -76,11 +68,7 @@ export const AudioToExternalHTML = (
};

export const AudioBlock = (
props: ReactCustomBlockRenderProps<
ReturnType<typeof createAudioBlockConfig>["type"],
ReturnType<typeof createAudioBlockConfig>["propSchema"],
ReturnType<typeof createAudioBlockConfig>["content"]
>,
props: ReactCustomBlockRenderProps<typeof createAudioBlockConfig>,
) => {
return (
<FileBlockWrapper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,7 @@ import { useDictionary } from "../../../../i18n/dictionary.js";
import { ReactCustomBlockRenderProps } from "../../../../schema/ReactBlockSpec.js";

export const AddFileButton = (
props: Omit<
ReactCustomBlockRenderProps<
FileBlockConfig["type"],
FileBlockConfig["propSchema"],
FileBlockConfig["content"]
>,
"contentRef"
> & {
props: Omit<ReactCustomBlockRenderProps<FileBlockConfig>, "contentRef"> & {
buttonIcon?: ReactNode;
},
) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FileBlockConfig } from "@blocknote/core";
import { BlockConfig, FileBlockConfig } from "@blocknote/core";
import { CSSProperties, ReactNode } from "react";

import { useUploadLoading } from "../../../../hooks/useUploadLoading.js";
Expand All @@ -9,9 +9,11 @@ import { FileNameWithIcon } from "./FileNameWithIcon.js";
export const FileBlockWrapper = (
props: Omit<
ReactCustomBlockRenderProps<
FileBlockConfig["type"],
FileBlockConfig["propSchema"] & { showPreview?: { default: true } },
FileBlockConfig["content"]
BlockConfig<
FileBlockConfig["type"],
FileBlockConfig["propSchema"] & { showPreview?: { default: true } },
FileBlockConfig["content"]
>
>,
"contentRef"
> & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ import { ReactCustomBlockRenderProps } from "../../../../schema/ReactBlockSpec.j

export const FileNameWithIcon = (
props: Omit<
ReactCustomBlockRenderProps<
FileBlockConfig["type"],
FileBlockConfig["propSchema"],
FileBlockConfig["content"]
>,
ReactCustomBlockRenderProps<FileBlockConfig>,
"editor" | "contentRef"
>,
) => (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FileBlockConfig } from "@blocknote/core";
import { BlockConfig, FileBlockConfig } from "@blocknote/core";
import { ReactNode, useCallback, useEffect, useRef, useState } from "react";

import { useUploadLoading } from "../../../../hooks/useUploadLoading.js";
Expand All @@ -8,13 +8,15 @@ import { FileBlockWrapper } from "./FileBlockWrapper.js";
export const ResizableFileBlockWrapper = (
props: Omit<
ReactCustomBlockRenderProps<
FileBlockConfig["type"],
FileBlockConfig["propSchema"] & {
showPreview?: { default: true };
previewWidth?: { default: number };
textAlignment?: { default: "left" };
},
FileBlockConfig["content"]
BlockConfig<
FileBlockConfig["type"],
FileBlockConfig["propSchema"] & {
showPreview?: { default: true };
previewWidth?: { default: number };
textAlignment?: { default: "left" };
},
FileBlockConfig["content"]
>
>,
"contentRef"
> & {
Expand Down
18 changes: 3 additions & 15 deletions packages/react/src/blocks/Image/block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ import { LinkWithCaption } from "../File/helpers/toExternalHTML/LinkWithCaption.

export const ImagePreview = (
props: Omit<
ReactCustomBlockRenderProps<
ReturnType<typeof createImageBlockConfig>["type"],
ReturnType<typeof createImageBlockConfig>["propSchema"],
ReturnType<typeof createImageBlockConfig>["content"]
>,
ReactCustomBlockRenderProps<typeof createImageBlockConfig>,
"contentRef"
>,
) => {
Expand All @@ -39,11 +35,7 @@ export const ImagePreview = (

export const ImageToExternalHTML = (
props: Omit<
ReactCustomBlockRenderProps<
ReturnType<typeof createImageBlockConfig>["type"],
ReturnType<typeof createImageBlockConfig>["propSchema"],
ReturnType<typeof createImageBlockConfig>["content"]
>,
ReactCustomBlockRenderProps<typeof createImageBlockConfig>,
"contentRef"
>,
) => {
Expand Down Expand Up @@ -81,11 +73,7 @@ export const ImageToExternalHTML = (
};

export const ImageBlock = (
props: ReactCustomBlockRenderProps<
ReturnType<typeof createImageBlockConfig>["type"],
ReturnType<typeof createImageBlockConfig>["propSchema"],
ReturnType<typeof createImageBlockConfig>["content"]
>,
props: ReactCustomBlockRenderProps<typeof createImageBlockConfig>,
) => {
return (
<ResizableFileBlockWrapper
Expand Down
Loading
Loading