🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@templatical/types

Package Overview
Dependencies
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@templatical/types - npm Package Compare versions

Comparing version
0.19.0
to
0.20.0
+197
-173
dist/index.d.ts

@@ -330,153 +330,32 @@ //#region src/blocks.d.ts

//#endregion
//#region src/custom-blocks.d.ts
type CustomBlockFieldType = "text" | "textarea" | "image" | "color" | "number" | "select" | "boolean" | "repeatable";
interface CustomBlockFieldBase {
key: string;
label: string;
required?: boolean;
placeholder?: string;
readOnly?: boolean;
//#region src/merge-tags.d.ts
interface SyntaxPreset {
value: RegExp;
logic: RegExp;
}
interface CustomBlockTextField extends CustomBlockFieldBase {
type: "text";
default?: string;
}
interface CustomBlockTextareaField extends CustomBlockFieldBase {
type: "textarea";
default?: string;
}
interface CustomBlockImageField extends CustomBlockFieldBase {
type: "image";
default?: string;
}
interface CustomBlockColorField extends CustomBlockFieldBase {
type: "color";
default?: string;
}
interface CustomBlockNumberField extends CustomBlockFieldBase {
type: "number";
default?: number;
min?: number;
max?: number;
step?: number;
}
interface SelectOption {
label: string;
value: string;
}
interface CustomBlockSelectField extends CustomBlockFieldBase {
type: "select";
options: SelectOption[];
default?: string;
}
interface CustomBlockBooleanField extends CustomBlockFieldBase {
type: "boolean";
default?: boolean;
}
interface CustomBlockRepeatableField extends CustomBlockFieldBase {
type: "repeatable";
fields: Exclude<CustomBlockField, CustomBlockRepeatableField>[];
default?: Record<string, unknown>[];
minItems?: number;
maxItems?: number;
}
type CustomBlockField = CustomBlockTextField | CustomBlockTextareaField | CustomBlockImageField | CustomBlockColorField | CustomBlockNumberField | CustomBlockSelectField | CustomBlockBooleanField | CustomBlockRepeatableField;
interface CustomBlockDefinition {
type: string;
name: string;
icon?: string;
description?: string;
fields: CustomBlockField[];
template: string;
dataSource?: DataSourceConfig;
/**
* Default block styles applied when a new instance of this custom block is
* created. Deep-merged over the built-in defaults — only specify the fields
* you want to override. Controls both the editor canvas wrapper and the
* rendered MJML/email output.
*
* @example
* defaultStyles: {
* padding: { top: 0, right: 0, bottom: 0, left: 0 },
* }
*/
defaultStyles?: Partial<BlockStyles>;
/**
* Optional CSS rules attached to this custom block definition. Emitted once
* (deduped across instances) into `<mj-head><mj-style>…</mj-style></mj-head>`
* in the rendered MJML, and adopted into the editor canvas (shadow root or
* light-DOM mount) so authored responsive/hover/font behavior previews
* inside the editor.
*
* Use this for media queries, hover states, or any CSS that should apply
* once per definition rather than per block instance. Class names are not
* scoped by the SDK — namespace them yourself (e.g. `.tplc-<type>-<el>`) to
* avoid collisions with other definitions or built-in editor styles.
*
* @example
* stylesheet: `
* @media (max-width: 480px) {
* .tplc-image-text-cell { display: block !important; width: 100% !important; }
* }
* `
*/
stylesheet?: string;
}
interface DataSourceFetchContext {
fieldValues: Record<string, unknown>;
blockId: string;
}
interface DataSourceConfig {
label: string;
onFetch: (context: DataSourceFetchContext) => Promise<Record<string, unknown> | null>;
}
//#endregion
//#region src/factory.d.ts
declare function generateId(): string;
declare function createTitleBlock(partial?: Partial<TitleBlock>): TitleBlock;
declare function createParagraphBlock(partial?: Partial<ParagraphBlock>): ParagraphBlock;
declare function createImageBlock(partial?: Partial<ImageBlock>): ImageBlock;
declare function createButtonBlock(partial?: Partial<ButtonBlock>): ButtonBlock;
declare function createDividerBlock(partial?: Partial<DividerBlock>): DividerBlock;
declare function createSectionBlock(partial?: Partial<SectionBlock>): SectionBlock;
declare function createVideoBlock(partial?: Partial<VideoBlock>): VideoBlock;
declare function createSocialIconsBlock(partial?: Partial<SocialIconsBlock>): SocialIconsBlock;
declare function createSpacerBlock(partial?: Partial<SpacerBlock>): SpacerBlock;
declare function createHtmlBlock(partial?: Partial<HtmlBlock>): HtmlBlock;
declare function createMenuBlock(partial?: Partial<MenuBlock>): MenuBlock;
declare function createTableBlock(partial?: Partial<TableBlock>): TableBlock;
declare function createCountdownBlock(partial?: Partial<CountdownBlock>): CountdownBlock;
declare function createCustomBlock(definition: CustomBlockDefinition): CustomBlock;
declare function createBlock(type: BlockType, blockDefaults?: BlockDefaults): Block;
declare function cloneBlock(block: Block): Block;
//#endregion
//#region src/events.d.ts
declare class EventEmitter<TEvents extends Record<string, unknown> = Record<string, unknown>> {
private handlers;
on<K extends keyof TEvents>(event: K, handler: (data: TEvents[K]) => void): () => void;
off<K extends keyof TEvents>(event: K, handler: (data: TEvents[K]) => void): void;
emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void;
removeAllListeners(event?: keyof TEvents): void;
listenerCount(event: keyof TEvents): number;
}
//#endregion
//#region src/clone.d.ts
type SyntaxPresetName = "liquid" | "handlebars" | "mailchimp" | "ampscript";
declare const SYNTAX_PRESETS: Record<SyntaxPresetName, SyntaxPreset>;
/**
* Cycle-safe deep clone via a JSON round-trip.
*
* A naked `JSON.stringify` throws `Converting circular structure to JSON`
* if the tree is self-referencing — e.g. a DOM element carrying a Sortable
* expando back-ref (`HTMLDivElement.SortableXXX -> instance -> el -> div`)
* leaks into block data through a drag handler inside a section. Both the
* editor's public `getContent()` export path and the history snapshot path
* must tolerate that: we drop the offending back-ref from the clone rather
* than throw. Losing a transient DOM expando is harmless; the block data is
* intact.
*
* The `WeakSet` replacer omits any object already seen on the current path,
* which covers every cyclic shape. Template content is tree-shaped (and is
* serialized to JSON for storage anyway), so dropping repeated references
* never costs real data.
* Resolves the autocomplete trigger string for a syntax preset.
* Returns null when the syntax doesn't match any built-in preset
* (custom regex syntax — autocomplete cannot be enabled safely).
*/
declare function safeClone<T>(value: T): T;
declare function getSyntaxTriggerChar(syntax: SyntaxPreset): string | null;
/**
* Resolves the closing delimiter for a syntax preset (e.g. `}}` for liquid,
* `|*` for mailchimp). The autocomplete trigger detector uses it to tell an
* open tag (`{{first`) from a completed one (`{{first_name}}`) so the popup
* doesn't reappear over a finished tag. Returns null for custom syntaxes —
* the same set for which `getSyntaxTriggerChar` returns null.
*/
declare function getSyntaxClosingChar(syntax: SyntaxPreset): string | null;
declare function resolveSyntax(syntax?: SyntaxPresetName | SyntaxPreset): SyntaxPreset;
declare function isMergeTagValue(value: string, syntax: SyntaxPreset): boolean;
declare function getMergeTagLabel(value: string, mergeTags: MergeTag[]): string;
declare function resolveHtmlMergeTagLabels(html: string, mergeTags: MergeTag[]): string;
declare function containsMergeTag(value: string, syntax: SyntaxPreset): boolean;
declare function restoreMergeTagMarkup(html: string, mergeTags: MergeTag[], syntax: SyntaxPreset): string;
declare function isLogicMergeTagValue(value: string, syntax: SyntaxPreset): boolean;
declare function getLogicMergeTagKeyword(value: string, syntax: SyntaxPreset): string;
declare function resolveHtmlLogicMergeTagLabels(html: string, syntax: SyntaxPreset): string;
//#endregion

@@ -668,32 +547,177 @@ //#region src/config.d.ts

//#endregion
//#region src/merge-tags.d.ts
interface SyntaxPreset {
value: RegExp;
logic: RegExp;
//#region src/custom-blocks.d.ts
type CustomBlockFieldType = "text" | "textarea" | "image" | "color" | "number" | "select" | "boolean" | "repeatable";
interface CustomBlockFieldBase {
key: string;
label: string;
required?: boolean;
placeholder?: string;
readOnly?: boolean;
}
type SyntaxPresetName = "liquid" | "handlebars" | "mailchimp" | "ampscript";
declare const SYNTAX_PRESETS: Record<SyntaxPresetName, SyntaxPreset>;
interface CustomBlockTextField extends CustomBlockFieldBase {
type: "text";
default?: string;
}
interface CustomBlockTextareaField extends CustomBlockFieldBase {
type: "textarea";
default?: string;
}
interface CustomBlockImageField extends CustomBlockFieldBase {
type: "image";
default?: string;
}
/**
* Resolves the autocomplete trigger string for a syntax preset.
* Returns null when the syntax doesn't match any built-in preset
* (custom regex syntax — autocomplete cannot be enabled safely).
* A color-picker field. Beyond the shared field props it accepts the same flat
* `presets` / `allowCustom` pair as the editor-wide `colors` config (their
* shapes are derived from `ColorsConfig`, so the two can't drift), scoping this
* one field to a color *role* — e.g. a button-color field offering only the
* brand's accent/ink pair while other color fields inherit the global palette.
*
* **Narrowing only — of the author's freedom, not the palette.** A field can
* restrict what authors may do (lock this field, or give it its own `presets`),
* but never unlock what the editor locked. Its `presets` *replace* the
* editor-wide grid rather than intersecting it, so a locked field may offer
* colors outside `colors.presets`:
*
* - `presets` — entries are validated exactly like editor-level presets
* (`#rgb` / `#rrggbb` hex; invalid ones are skipped with a console warning
* naming the block and field). A non-empty valid list replaces the editor's
* palette for this field; leaving it unset, passing `[]`, or passing only
* invalid entries all inherit the editor's palette.
* - `allowCustom` — `false` locks this field to its palette even while the rest
* of the editor allows free-form entry. `true` cannot unlock a field when the
* editor-wide `colors.allowCustom` is `false`; it is ignored with a warning.
*
* @see https://docs.templatical.com/guide/custom-blocks
*/
declare function getSyntaxTriggerChar(syntax: SyntaxPreset): string | null;
interface CustomBlockColorField extends CustomBlockFieldBase, Pick<ColorsConfig, "presets" | "allowCustom"> {
type: "color";
default?: string;
}
interface CustomBlockNumberField extends CustomBlockFieldBase {
type: "number";
default?: number;
min?: number;
max?: number;
step?: number;
}
interface SelectOption {
label: string;
value: string;
}
interface CustomBlockSelectField extends CustomBlockFieldBase {
type: "select";
options: SelectOption[];
default?: string;
}
interface CustomBlockBooleanField extends CustomBlockFieldBase {
type: "boolean";
default?: boolean;
}
interface CustomBlockRepeatableField extends CustomBlockFieldBase {
type: "repeatable";
fields: Exclude<CustomBlockField, CustomBlockRepeatableField>[];
default?: Record<string, unknown>[];
minItems?: number;
maxItems?: number;
}
type CustomBlockField = CustomBlockTextField | CustomBlockTextareaField | CustomBlockImageField | CustomBlockColorField | CustomBlockNumberField | CustomBlockSelectField | CustomBlockBooleanField | CustomBlockRepeatableField;
interface CustomBlockDefinition {
type: string;
name: string;
icon?: string;
description?: string;
fields: CustomBlockField[];
template: string;
dataSource?: DataSourceConfig;
/**
* Default block styles applied when a new instance of this custom block is
* created. Deep-merged over the built-in defaults — only specify the fields
* you want to override. Controls both the editor canvas wrapper and the
* rendered MJML/email output.
*
* @example
* defaultStyles: {
* padding: { top: 0, right: 0, bottom: 0, left: 0 },
* }
*/
defaultStyles?: Partial<BlockStyles>;
/**
* Optional CSS rules attached to this custom block definition. Emitted once
* (deduped across instances) into `<mj-head><mj-style>…</mj-style></mj-head>`
* in the rendered MJML, and adopted into the editor canvas (shadow root or
* light-DOM mount) so authored responsive/hover/font behavior previews
* inside the editor.
*
* Use this for media queries, hover states, or any CSS that should apply
* once per definition rather than per block instance. Class names are not
* scoped by the SDK — namespace them yourself (e.g. `.tplc-<type>-<el>`) to
* avoid collisions with other definitions or built-in editor styles.
*
* @example
* stylesheet: `
* @media (max-width: 480px) {
* .tplc-image-text-cell { display: block !important; width: 100% !important; }
* }
* `
*/
stylesheet?: string;
}
interface DataSourceFetchContext {
fieldValues: Record<string, unknown>;
blockId: string;
}
interface DataSourceConfig {
label: string;
onFetch: (context: DataSourceFetchContext) => Promise<Record<string, unknown> | null>;
}
//#endregion
//#region src/factory.d.ts
declare function generateId(): string;
declare function createTitleBlock(partial?: Partial<TitleBlock>): TitleBlock;
declare function createParagraphBlock(partial?: Partial<ParagraphBlock>): ParagraphBlock;
declare function createImageBlock(partial?: Partial<ImageBlock>): ImageBlock;
declare function createButtonBlock(partial?: Partial<ButtonBlock>): ButtonBlock;
declare function createDividerBlock(partial?: Partial<DividerBlock>): DividerBlock;
declare function createSectionBlock(partial?: Partial<SectionBlock>): SectionBlock;
declare function createVideoBlock(partial?: Partial<VideoBlock>): VideoBlock;
declare function createSocialIconsBlock(partial?: Partial<SocialIconsBlock>): SocialIconsBlock;
declare function createSpacerBlock(partial?: Partial<SpacerBlock>): SpacerBlock;
declare function createHtmlBlock(partial?: Partial<HtmlBlock>): HtmlBlock;
declare function createMenuBlock(partial?: Partial<MenuBlock>): MenuBlock;
declare function createTableBlock(partial?: Partial<TableBlock>): TableBlock;
declare function createCountdownBlock(partial?: Partial<CountdownBlock>): CountdownBlock;
declare function createCustomBlock(definition: CustomBlockDefinition): CustomBlock;
declare function createBlock(type: BlockType, blockDefaults?: BlockDefaults): Block;
declare function cloneBlock(block: Block): Block;
//#endregion
//#region src/events.d.ts
declare class EventEmitter<TEvents extends Record<string, unknown> = Record<string, unknown>> {
private handlers;
on<K extends keyof TEvents>(event: K, handler: (data: TEvents[K]) => void): () => void;
off<K extends keyof TEvents>(event: K, handler: (data: TEvents[K]) => void): void;
emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void;
removeAllListeners(event?: keyof TEvents): void;
listenerCount(event: keyof TEvents): number;
}
//#endregion
//#region src/clone.d.ts
/**
* Resolves the closing delimiter for a syntax preset (e.g. `}}` for liquid,
* `|*` for mailchimp). The autocomplete trigger detector uses it to tell an
* open tag (`{{first`) from a completed one (`{{first_name}}`) so the popup
* doesn't reappear over a finished tag. Returns null for custom syntaxes —
* the same set for which `getSyntaxTriggerChar` returns null.
* Cycle-safe deep clone via a JSON round-trip.
*
* A naked `JSON.stringify` throws `Converting circular structure to JSON`
* if the tree is self-referencing — e.g. a DOM element carrying a Sortable
* expando back-ref (`HTMLDivElement.SortableXXX -> instance -> el -> div`)
* leaks into block data through a drag handler inside a section. Both the
* editor's public `getContent()` export path and the history snapshot path
* must tolerate that: we drop the offending back-ref from the clone rather
* than throw. Losing a transient DOM expando is harmless; the block data is
* intact.
*
* The `WeakSet` replacer omits any object already seen on the current path,
* which covers every cyclic shape. Template content is tree-shaped (and is
* serialized to JSON for storage anyway), so dropping repeated references
* never costs real data.
*/
declare function getSyntaxClosingChar(syntax: SyntaxPreset): string | null;
declare function resolveSyntax(syntax?: SyntaxPresetName | SyntaxPreset): SyntaxPreset;
declare function isMergeTagValue(value: string, syntax: SyntaxPreset): boolean;
declare function getMergeTagLabel(value: string, mergeTags: MergeTag[]): string;
declare function resolveHtmlMergeTagLabels(html: string, mergeTags: MergeTag[]): string;
declare function containsMergeTag(value: string, syntax: SyntaxPreset): boolean;
declare function restoreMergeTagMarkup(html: string, mergeTags: MergeTag[], syntax: SyntaxPreset): string;
declare function isLogicMergeTagValue(value: string, syntax: SyntaxPreset): boolean;
declare function getLogicMergeTagKeyword(value: string, syntax: SyntaxPreset): string;
declare function resolveHtmlLogicMergeTagLabels(html: string, syntax: SyntaxPreset): string;
declare function safeClone<T>(value: T): T;
//#endregion

@@ -700,0 +724,0 @@ //#region ../media-library/src/types.d.ts

{
"name": "@templatical/types",
"description": "Shared TypeScript types, block factory functions, and event emitter for Templatical email editor",
"version": "0.19.0",
"version": "0.20.0",
"bugs": "https://github.com/templatical/sdk/issues",

@@ -9,3 +9,3 @@ "devDependencies": {

"vitest": "^4.1.10",
"@templatical/media-library": "0.19.0"
"@templatical/media-library": "0.20.0"
},

@@ -12,0 +12,0 @@ "exports": {