@pdfme/common
Version:
TypeScript base PDF generator and React base UI. Open source, developed by the community, and completely free to use under the MIT license!
253 lines (252 loc) • 11.1 kB
TypeScript
import { z } from 'zod';
import type { PDFPage, PDFDocument } from '@pdfme/pdf-lib';
import { Lang, Dict, Mode, Size, DynamicLayoutSplitRange, Schema, Font, SchemaForUI, BasePdf, BlankPdf, CustomPdf, CommonOptions, Template, GeneratorOptions, GenerateProps, UIOptions, UIProps, PreviewProps, DesignerProps, ColorType, LegacySchemaPageArray, SchemaPageArray } from './schema.js';
export interface UIOptionsThemeToken {
colorPrimary?: string;
colorPrimaryBg?: string;
colorWhite?: string;
[key: string]: unknown;
}
export interface UIOptionsTheme {
token?: UIOptionsThemeToken;
components?: Record<string, Record<string, unknown>>;
[key: string]: unknown;
}
export interface PropPanelRule {
validator?: (...args: any[]) => unknown;
message?: string;
pattern?: RegExp | string;
[key: string]: unknown;
}
export interface PropPanelSchema {
title?: string;
type?: string;
widget?: string;
default?: unknown;
placeholder?: string;
format?: string;
required?: boolean;
hidden?: boolean | string;
disabled?: boolean;
bind?: string | false | string[];
span?: number;
column?: number;
min?: number;
max?: number;
props?: Record<string, unknown>;
rules?: PropPanelRule[];
properties?: Record<string, PropPanelSchema>;
items?: PropPanelSchema | PropPanelSchema[];
[key: string]: unknown;
}
export type ChangeSchemaItem = {
key: string;
value: unknown;
schemaId: string;
};
export type ChangeSchemas = (objs: ChangeSchemaItem[]) => void;
export type UITheme = {
colorPrimary: string;
colorPrimaryBg: string;
colorWhite: string;
};
/**
* Properties used for PDF rendering.
* @template T Type of the extended Schema object.
* @property {string} value The string used for PDF rendering.
* @property {T} schema Extended Schema object for rendering.
* @property {BasePdf} basePdf Base PDF object for rendering.
* @property {typeof import('@pdfme/pdf-lib')} pdfLib The pdf-lib library used for rendering.
* @property {PDFDocument} pdfDoc PDFDocument object from pdf-lib.
* @property {PDFPage} page PDFPage object from pdf-lib.
* @property {GeneratorOptions} options Options object passed from the generator.
* @property {Map<string | number, unknown>} _cache Cache shared only during the execution of the generate function (useful for caching images, etc. if needed).
*/
export interface PDFRenderProps<T extends Schema> {
value: string;
schema: T;
basePdf: BasePdf;
pdfLib: typeof import('@pdfme/pdf-lib');
pdfDoc: PDFDocument;
page: PDFPage;
options: GeneratorOptions;
_cache: Map<string | number, unknown>;
}
/**
* Type for properties used in UI rendering.
*
* @template T - Type of the extended Schema object.
* @property {T} schema - Extended Schema object for rendering.
* @property {BasePdf} basePdf Base PDF object for rendering.
* @property {Mode} mode - String indicating the rendering state. 'designer' is only used when the field is in edit mode in the Designer.
* @property {number} [tabIndex] - Tab index for Form.
* @property {string} [placeholder] - Placeholder text for Form.
* @property {() => void} [stopEditing] - Stops editing mode, can be used when the mode is 'designer'.
* @property {string} value - The string used for UI rendering.
* @property {(arg: { key: string; value: unknown } | { key: string; value: unknown }[]) => void} [onChange] - Used to change the value and schema properties. Only applicable when the mode is 'form' or 'designer'.
* @property {HTMLDivElement} rootElement - The root HTMLDivElement for the UI.
* @property {UIOptions} options - Options object passed from the Viewer, Form, or Designer.
* @property {UITheme} theme - A merged token object used for UI rendering.
* @property {(key: keyof Dict | string) => string} i18n - An object merged based on the options 'lang' and 'labels'.
* @property {number} scale - The scale of the UI.
* @property {Map<string | number, unknown>} _cache - Cache shared only during the execution of the render function (useful for caching images, etc. if needed).
*/
export type UIRenderProps<T extends Schema> = {
schema: T;
basePdf: BasePdf;
mode: Mode;
tabIndex?: number;
placeholder?: string;
stopEditing?: () => void;
value: string;
onChange?: (arg: {
key: string;
value: unknown;
} | {
key: string;
value: unknown;
}[]) => void;
rootElement: HTMLDivElement;
options: UIOptions;
theme: UITheme;
i18n: (key: string) => string;
scale: number;
_cache: Map<string | number, unknown>;
};
/**
* Type for properties used in configuring the property panel.
*
* @property {HTMLDivElement} rootElement - The root HTML element of the property panel.
* @property {SchemaForUI} activeSchema - The currently active schema for UI rendering.
* @property {HTMLElement[]} activeElements - Array of currently active HTML elements in the UI.
* @property {ChangeSchemas} changeSchemas - Function to change multiple schemas simultaneously.
* @property {SchemaForUI[]} schemas - Array of schemas for UI rendering.
* @property {BasePdf} basePdf - The base PDF used by the current template.
* @property {Size} pageSize - The size of the page being edited.
* @property {UIOptions} options - UI options for the property panel.
* @property {UITheme} theme - The theme token used in the UI.
* @property {(key: keyof Dict | string) => string} i18n - Internationalization dictionary for UI labels and texts.
*/
type PropPanelProps = {
rootElement: HTMLDivElement;
activeSchema: SchemaForUI;
activeElements: HTMLElement[];
changeSchemas: ChangeSchemas;
schemas: SchemaForUI[];
basePdf?: BasePdf;
options: UIOptions;
theme: UITheme;
i18n: (key: string) => string;
};
type PropPanelWidgetRuntimeProps = {
schema?: PropPanelSchema;
value?: unknown;
onChange?: (...args: any[]) => unknown;
error?: unknown;
[key: string]: unknown;
};
export type PropPanelWidgetProps = PropPanelWidgetRuntimeProps & PropPanelProps;
/**
* Used for customizing the property panel.
* @template T - Type of the extended Schema object.
* @property {Record<string, PropPanelSchema> | ((propPanelProps: Omit<PropPanelProps, 'rootElement'>) => Record<string, PropPanelSchema>)} schema - A function returning a form-render schema object or the schema object itself. When a function, it takes properties passed from the designer as arguments.
* @property {Record<string, (props: PropPanelWidgetProps) => void>} [widgets] - An object of functions returning form-render widgets. The functions take, as arguments, both form-render's WidgetProps and properties passed from the designer.
* @property {T} defaultSchema - The default schema set when adding the schema.
*/
export interface PropPanel<T extends Schema> {
schema: ((propPanelProps: Omit<PropPanelProps, 'rootElement'>) => Record<string, PropPanelSchema>) | Record<string, PropPanelSchema>;
widgets?: Record<string, (props: PropPanelWidgetProps) => void>;
defaultSchema: T;
}
/**
* The Plugin interface is used for PDF and UI rendering, as well as defining the property panel.
* The 'pdf' is used in the generator package, 'ui' is used in the viewer, form, and designer packages, and 'propPanel' is used in the designer package.
* Objects defined as Plugins using this interface can be used with a consistent interface across all packages.
* @template T Type of the extended Schema object.
* @property {function} pdf Function for rendering PDFs.
* @property {function} ui Function for rendering UI.
* @property {PropPanel} propPanel Object for defining the property panel.
* @property {string} [icon] Icon SVG for the plugin.
* @property {boolean} [uninterruptedEditMode] When editing in the UI, should the field avoid re-rendering while in edit mode?
*/
export interface Plugin<T extends Schema = Schema> {
pdf(arg: PDFRenderProps<T & Schema>): Promise<void> | void;
ui(arg: UIRenderProps<T & Schema>): Promise<void> | void;
propPanel: PropPanel<T & Schema>;
icon?: string;
uninterruptedEditMode?: boolean;
}
export type Plugins = {
[key: string]: Plugin;
};
export interface PluginRegistry {
plugins: {
[key: string]: Plugin;
};
exists(): boolean;
values(): Plugin[];
entries(): [string, Plugin][];
findByType(type: string): Plugin | undefined;
findWithLabelByType(type: string): [string, Plugin | undefined];
}
export type Lang = z.infer<typeof Lang>;
export type Dict = z.infer<typeof Dict>;
export type Mode = z.infer<typeof Mode>;
export type Size = z.infer<typeof Size>;
export type DynamicLayoutSplitRange = z.infer<typeof DynamicLayoutSplitRange>;
export type DynamicLayoutRange = Omit<DynamicLayoutSplitRange, 'unit'>;
export type Schema = z.infer<typeof Schema>;
export type SchemaForUI = z.infer<typeof SchemaForUI>;
/**
* Represents the Font type definition.
* @property {Object} [x: string] - Object key is the font name.
* @property {(string | ArrayBuffer | Uint8Array)} data - The font data.
* @property {boolean} [fallback] - Please set to true for the fallback font when no font is specified. Only one value within the given Font object needs to be set to true.
* @property {boolean} [subset] - The default is true (use subset font). So if you don't want to use a subset font, please set it to false.
*/
export type Font = z.infer<typeof Font>;
export type ColorType = z.infer<typeof ColorType>;
export type BasePdf = z.infer<typeof BasePdf>;
export type BlankPdf = z.infer<typeof BlankPdf>;
export type CustomPdf = z.infer<typeof CustomPdf>;
export type Template = z.infer<typeof Template>;
export type CommonOptions = z.infer<typeof CommonOptions>;
export type GeneratorOptions = z.infer<typeof GeneratorOptions>;
export type GenerateProps = Omit<z.infer<typeof GenerateProps>, 'plugins'> & {
plugins?: Plugins;
};
export type UIOptions = z.infer<typeof UIOptions> & {
theme?: UIOptionsTheme;
};
export type UIProps = Omit<z.infer<typeof UIProps>, 'plugins'> & {
plugins?: Plugins;
};
export type PreviewProps = Omit<z.infer<typeof PreviewProps>, 'plugins'> & {
plugins?: Plugins;
};
export type DesignerProps = Omit<z.infer<typeof DesignerProps>, 'plugins'> & {
plugins?: Plugins;
};
export type SchemaPageArray = z.infer<typeof SchemaPageArray>;
export type LegacySchemaPageArray = z.infer<typeof LegacySchemaPageArray>;
export type DynamicLayoutPatchArgs = {
schema: Schema;
start: number;
end: number;
isSplit: boolean;
chunkHeight: number;
};
export type DynamicLayoutResult = {
heights: number[];
avoidFirstUnitOnly?: boolean;
patchSplitSchema?: (args: DynamicLayoutPatchArgs) => Partial<Schema>;
};
export type DynamicLayoutCallbackResult = DynamicLayoutResult | number[];
export type DynamicLayoutArgs = {
schema: Schema;
basePdf: BasePdf;
options: CommonOptions;
_cache: Map<string | number, unknown>;
};
export type GetDynamicLayout = (value: string, args: DynamicLayoutArgs) => Promise<DynamicLayoutCallbackResult>;
export {};