@myissue/vue-website-page-builder
Version:
Vue 3 page builder for ecommerce admin, multi-tenant SaaS, and CMS dashboards. Drag-and-drop editor with custom media library and product catalog integration.
1,185 lines (1,162 loc) • 70.6 kB
TypeScript
import { App } from 'vue';
import { ComponentOptionsMixin } from 'vue';
import { ComponentProvideOptions } from 'vue';
import { createPinia } from 'pinia';
import { DefineComponent } from 'vue';
import { ExtractPropTypes } from 'vue';
import { Pinia } from 'pinia';
import { PiniaCustomStateProperties } from 'pinia';
import { PublicProps } from 'vue';
import { StoreDefinition } from 'pinia';
declare const __VLS_export: DefineComponent<ExtractPropTypes<{
CustomMediaLibraryComponent: {
type: ObjectConstructor;
default: null;
};
DisplayProducts: {
type: ObjectConstructor;
default: null;
};
enableDefaultProducts: {
type: BooleanConstructor;
default: boolean;
};
CustomBuilderComponents: {
type: ObjectConstructor;
default: null;
};
showCloseButton: {
type: BooleanConstructor;
default: boolean;
};
showPublishButton: {
type: BooleanConstructor;
default: boolean;
};
}>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
handleClosePageBuilder: (...args: any[]) => void;
handlePublishPageBuilder: (...args: any[]) => void;
}, string, PublicProps, Readonly< ExtractPropTypes<{
CustomMediaLibraryComponent: {
type: ObjectConstructor;
default: null;
};
DisplayProducts: {
type: ObjectConstructor;
default: null;
};
enableDefaultProducts: {
type: BooleanConstructor;
default: boolean;
};
CustomBuilderComponents: {
type: ObjectConstructor;
default: null;
};
showCloseButton: {
type: BooleanConstructor;
default: boolean;
};
showPublishButton: {
type: BooleanConstructor;
default: boolean;
};
}>> & Readonly<{
onHandleClosePageBuilder?: ((...args: any[]) => any) | undefined;
onHandlePublishPageBuilder?: ((...args: any[]) => any) | undefined;
}>, {
CustomBuilderComponents: Record<string, any>;
CustomMediaLibraryComponent: Record<string, any>;
DisplayProducts: Record<string, any>;
enableDefaultProducts: boolean;
showCloseButton: boolean;
showPublishButton: boolean;
}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
declare const __VLS_export_2: DefineComponent<ExtractPropTypes<{
mobile: {
type: BooleanConstructor;
};
tablet: {
type: BooleanConstructor;
};
}>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly< ExtractPropTypes<{
mobile: {
type: BooleanConstructor;
};
tablet: {
type: BooleanConstructor;
};
}>> & Readonly<{}>, {
mobile: boolean;
tablet: boolean;
}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
declare type AvailableLanguage = 'en' | 'zh-Hans' | 'fr' | 'ja' | 'ru' | 'es' | 'pt' | 'de' | 'ar' | 'hi' | 'da' | 'it';
export declare interface BuilderResourceComponent {
html_code: string;
title?: string;
[key: string]: unknown;
}
export declare type BuilderResourceData = BuilderResourceComponent[];
export declare function buildProductSectionHtml(products: ReadonlyArray<PageBuilderProductInput>, layout?: ProductGridLayout, sectionTitle?: string, styleOptions?: BuildProductSectionStyleOptions): string;
declare interface BuildProductSectionStyleOptions {
cardStyle?: ProductCardStyle;
roundedImages?: boolean;
openInNewTab?: boolean;
buttonStyle?: ProductButtonStyle;
roundedButtons?: boolean;
hidePrice?: boolean;
hideImage?: boolean;
hideButton?: boolean;
hideLinks?: boolean;
mobileColumns?: 1 | 2;
}
/**
* Build a user-scoped storage key so each user keeps their own presets.
* Falls back to the shared key when no `userForPageBuilder.id` is provided.
*
* @example
* // user id 42 → "vueWebsitePageBuilderThemeColorPresets-u42"
* // no id → "vueWebsitePageBuilderThemeColorPresets"
*/
export declare function buildStorageKey(config?: PageBuilderConfig | null): string;
export declare interface ComponentObject {
id: string | number | null;
html_code: string;
title: string;
[key: string]: unknown;
}
export { createPinia }
export declare type FormName = 'post' | 'article' | 'blog' | 'news' | 'page' | 'faq' | 'testimonial' | 'case-study' | 'press-release' | 'product' | 'products' | 'category' | 'collection' | 'brand' | 'coupon' | 'discount' | 'shop' | 'cart' | 'checkout' | 'profile' | 'account' | 'team' | 'team-member' | 'author' | 'customer' | 'user' | 'service' | 'services' | 'package' | 'plan' | 'pricing' | 'subscription' | 'job' | 'job-listing' | 'career' | 'applicant' | 'event' | 'events' | 'webinar' | 'appointment' | 'reservation' | 'schedule' | 'listing' | 'directory' | 'location' | 'vendor' | 'company' | 'gallery' | 'image' | 'video' | 'media' | 'audio' | 'file' | 'contact' | 'support' | 'ticket' | 'feedback' | 'review' | 'inquiry' | 'report' | 'setting' | 'configuration' | 'integration' | 'theme' | 'language' | 'menu' | 'navigation' | 'tag' | 'meta';
/**
* Retrieves the singleton instance of the PageBuilderService.
* This function is used throughout the application to access the service.
* It throws an error if the service has not been initialized, ensuring that
* the plugin has been correctly installed.
*
* @throws {Error} If the PageBuilderService has not been initialized.
* @returns {PageBuilderService} The singleton instance of the PageBuilderService.
*/
export declare function getPageBuilder(): PageBuilderService;
export declare interface ImageObject {
src: string;
[key: string]: unknown;
}
export declare interface InsertProductsOptions {
layout?: ProductGridLayout;
mobileColumns?: ProductMobileColumns;
cardStyle?: ProductCardStyle;
/** Adds rounded corners to product images */
roundedImages?: boolean;
/** Adds target="_blank" rel="noopener noreferrer" to product links */
openInNewTab?: boolean;
/** Product CTA appearance: plain text link or button style */
buttonStyle?: ProductButtonStyle;
/** Applies rounded/full corners when CTA button style is enabled */
roundedButtons?: boolean;
/** Hides price and compare-at price when product data includes them */
hidePrice?: boolean;
/** Hides product photos when product data includes images */
hideImage?: boolean;
/** Hides the CTA button when product data includes url and buttonText */
hideButton?: boolean;
/** Removes clickable links from product cards (title/image/CTA). */
hideLinks?: boolean;
sectionTitle?: string;
/** unshift | push | insert (uses current add index) */
method?: 'unshift' | 'push' | 'insert' | (string & {});
}
export declare const PageBuilder: typeof __VLS_export;
export declare const pageBuilder: {
install: (app: App) => void;
};
export declare interface PageBuilderConfig {
updateOrCreate: {
/**
* Whether the builder is creating new content or updating existing content.
* Accepts `'create'`, `'update'`, or any other string for dynamic / computed values.
* The union with `(string & {})` preserves autocomplete for the two common values
* while allowing any string without requiring `as const` or explicit casting.
*
* @example
* // Dynamic value — works without `as const`
* formType: hasContent ? 'update' : 'create'
*/
formType: 'create' | 'update' | (string & {});
formName: FormName | (string & {});
[key: string]: unknown;
};
pageBuilderLogo?: {
src: string;
[key: string]: unknown;
} | null;
resourceData?: {
/**
* Optional page/resource title shown in the builder toolbar.
* Made optional so consumers can pass a resource object without a title
* or when the title isn't known yet at the time `startBuilder` is called.
*/
title?: string;
/**
* Accepts both numeric IDs and string-based IDs (e.g. UUIDs).
* The service handles both types at runtime when building localStorage keys.
*/
id?: number | string;
[key: string]: unknown;
} | null;
userForPageBuilder?: PageBuilderUser;
[key: string]: unknown;
userSettings?: {
language?: {
default?: string;
enable?: readonly string[];
disableLanguageDropDown?: boolean;
};
autoSave?: boolean;
notifications?: boolean;
/**
* Default canvas font and, optionally, the restricted set of fonts shown in
* the font-family picker.
*
* - Single built-in key: `'jost'` — canvas default; picker shows all built-in fonts.
* - Comma-separated list: first entry is the canvas default; picker is restricted
* to the listed fonts.
*
* Any name not in the built-in list is treated as a custom font (e.g.
* `'Bitcount Grid Double'`). You must load the font in your app CSS
* (`@import`, `@font-face`, or a `<link>`). The builder applies the name only.
*/
fontFamily?: string;
/**
* Per-element font overrides applied to the builder canvas.
* Same format as `fontFamily` — built-in keys, comma-separated fallbacks,
* or custom font names you load yourself.
*/
elementFonts?: PageBuilderElementFonts;
} | null;
settings?: {
brandColor?: string;
themeColorPresets?: ThemeColorPresetSettingsInput | ThemeColorPresetSettings | null;
[key: string]: unknown;
} | null;
pageSettings?: PageSettings;
}
/**
* Per-element font overrides for the builder canvas.
* Each value is a font key name or comma-separated list (e.g. `'jost'` or
* `'jost, raleway, arial'`). The first recognised font name is applied;
* unrecognised names are silently skipped.
*/
declare interface PageBuilderElementFonts {
h1?: string;
h2?: string;
h3?: string;
h4?: string;
h5?: string;
h6?: string;
p?: string;
}
export declare const PageBuilderPreview: typeof __VLS_export_2;
/**
* Flexible product shape for ecommerce integrations.
* All fields are optional — hosts decide what to show in their custom picker or layouts.
* Includes an index signature for custom fields used in templates.
*/
export declare type PageBuilderProduct = PageBuilderProductInput & {
[key: string]: unknown;
};
/**
* Product fields accepted by insertProducts() / buildProductSectionHtml().
* No index signature — assign from your API interfaces without extra casting.
*/
export declare interface PageBuilderProductInput {
id?: string | number;
title?: string;
description?: string;
image?: string;
imageAlt?: string;
price?: string | number;
compareAtPrice?: string | number;
badge?: string;
/** Product or checkout URL on the host storefront */
url?: string;
buttonText?: string;
sku?: string;
}
export declare class PageBuilderService {
private fontSizeRegex;
protected pageBuilderStateStore: ReturnType<typeof usePageBuilderStateStore>;
private getLocalStorageItemName;
private getApplyImageToSelection;
private getHyberlinkEnable;
private getComponents;
private getComponent;
private getElement;
private getComponentArrayAddMethod;
private NoneListernesTags;
private hasStartedEditing;
private originalComponents;
private originalPageSettings;
private savedMountComponents;
private pendingMountComponents;
private globalStylesObserver;
private _pendingPageSettings;
private _lastKnownPageSettings;
private isPageBuilderMissingOnStart;
private hasCompletedBuilderMount;
private builderWasMountedBeforeClose;
private builderMountPromise;
private activeBuilderSessionToken;
private canvasClickCaptureListener;
private canvasDblClickCaptureListener;
private elementsWithListeners;
private translate;
constructor(pageBuilderStateStore: ReturnType<typeof usePageBuilderStateStore>);
private isDebugEnabled;
private debugLog;
/**
* Returns the active builder canvas element.
* Prefer the editor canvas marker to avoid collisions with host-rendered
* published HTML that may also contain #pagebuilder.
*/
private getBuilderCanvasElement;
/**
* Returns an array of available languages.
* @returns {AvailableLanguage[]} An array of available language codes.
*/
availableLanguage(): AvailableLanguage[];
/**
* Sets the current language in the page builder state.
* @param {string} lang - The language code to set.
*/
changeLanguage(lang: string): void;
/**
* Deselects any selected or hovered elements in the builder UI.
* @returns {Promise<void>}
*/
clearHtmlSelection(): Promise<void>;
/**
* Ensures that the `updateOrCreate` configuration is valid and sets default values if necessary.
* @param {PageBuilderConfig} config - The page builder configuration.
* @private
*/
private ensureUpdateOrCreateConfig;
/**
* Validates the user-provided components array.
* @param {unknown} components - The components data to validate.
* @returns {{error: true, warning: string, status: string} | {error: true, reason: string} | undefined} An error object if validation fails, otherwise undefined.
* @private
*/
private validateUserProvidedComponents;
/**
* Ensures that the language configuration is valid and sets default values if necessary.
* @param {PageBuilderConfig} config - The page builder configuration.
* @private
*/
private ensureLanguage;
/**
* Validates the entire page builder configuration.
* @param {PageBuilderConfig} config - The page builder configuration.
* @private
*/
private validateConfig;
/**
* Saves user settings to local storage.
* @param {string} newLang - The new language to save.
*/
saveUserSettingsStorage(newLang: string): void;
/**
* Initializes the Page Builder.
* @param {PageBuilderConfig} config - The configuration object for the Page Builder.
* @param {BuilderResourceData} [passedComponentsArray] - Optional array of components to load.
* @returns {Promise<StartBuilderResult>} A result object indicating success or failure.
*/
startBuilder(config: PageBuilderConfig, passedComponentsArray?: BuilderResourceData): Promise<StartBuilderResult>;
/**
* Whether PageBuilder.vue should run deferred mount on mount (DOM was missing at startBuilder).
*
* @param ownCanvas - The component's own #pagebuilder element (passed from PageBuilder.vue ref).
* Using this instead of document.querySelector ensures the correct canvas is checked when
* multiple PageBuilder instances exist on the same page (e.g. one always-visible + one in a
* modal). When the modal's canvas is empty while another instance already has content, the
* document.querySelector approach would miss the empty canvas entirely.
*/
shouldCompleteBuilderMountOnMount(ownCanvas?: HTMLElement): boolean;
/**
* Marks the builder canvas lifecycle as "missing on start" for the next mount.
* Used by PageBuilder.vue on unmount (v-if modal close) so reopen performs
* a full draft-aware initialization instead of reusing potentially stale store DOM.
*/
markCanvasUnmountedForNextMount(): void;
/**
* Completes the builder initialization process once the DOM is ready.
* @param {BuilderResourceData} [passedComponentsArray] - Optional array of components to load.
* @returns {Promise<void>}
*/
completeBuilderInitialization(passedComponentsArray?: BuilderResourceData): Promise<void>;
private completeBuilderInitializationWithSession;
private runCompleteBuilderInitialization;
/**
* Converts an array of ComponentObject into a single HTML string.
*
* @returns {string} A single HTML string containing all components.
*/
private renderComponentsToHtml;
/**
* Completes the mounting process by loading components into the DOM and setting up listeners.
* @param {string} html - The HTML string of components to mount.
* @param {boolean} [useConfigPageSettings] - Whether to use page settings from the passed data.
* @private
*/
private completeMountProcess;
/**
* Applies CSS class changes to the currently selected element.
* @param {string | undefined} cssUserSelection - The user's CSS class selection.
* @param {string[]} CSSArray - The array of possible CSS classes for this property.
* @param {string} mutationName - The name of the store mutation to call.
* @returns {string | undefined} The previously applied CSS class.
* @private
*/
private applyElementClassChanges;
private resolveNestedButtonAnchorTarget;
private removeElementClassesFromArray;
/**
* During Page Design editing, keep runtime config pageSettings aligned with the
* live #pagebuilder wrapper so Vue re-renders do not restore stale styles.
*/
private syncGlobalPageSettingsIntoRuntimeConfig;
/**
* Removes all CSS classes from the main page builder container.
* @returns {Promise<void>}
*/
clearClassesFromPage(): Promise<void>;
/**
* Removes all inline styles from the main page builder container.
* @returns {Promise<void>}
*/
clearInlineStylesFromPage(): Promise<void>;
/**
* Selects the main page builder container for global styling.
* @returns {Promise<void>}
*/
globalPageStyles(): Promise<void>;
/**
* Disconnects the MutationObserver that tracks global page style changes.
* Call when closing the global styles editor panel.
*/
stopGlobalStylesSync(): void;
/**
* Handles changes to the font weight of the selected element.
* @param {string} [userSelectedFontWeight] - The selected font weight class.
*/
handleFontWeight(userSelectedFontWeight?: string): void;
/**
* Handles changes to the base font size of the selected element.
* @param {string} [userSelectedFontSize] - The selected font size class.
*/
handleFontSizeBase(userSelectedFontSize?: string): void;
/**
* Handles changes to the desktop font size of the selected element.
* @param {string} [userSelectedFontSize] - The selected font size class for desktop.
*/
handleFontSizeDesktop(userSelectedFontSize?: string): void;
/**
* Applies helper CSS classes to elements, such as wrapping them or adding responsive text classes.
* @param {HTMLElement} element - The element to process.
* @private
*/
private ensureImagesHaveAltText;
private applyHelperCSSToElements;
private reportNonListenerTagClassViolations;
/**
* Toggles the visibility of the TipTap modal for rich text editing.
* @param {boolean} status - Whether to show or hide the modal.
* @returns {Promise<void>}
*/
toggleTipTapModal(status: boolean): Promise<void>;
/**
* Toggles direct, in-canvas rich text editing for the selected element.
* @param {boolean} status - Whether to enable inline Tiptap editing.
* @returns {Promise<void>}
*/
toggleInlineTipTapEditor(status: boolean): Promise<void>;
/**
* Restores normal builder selection after an inline TipTap editor has been torn down.
* @param {HTMLElement | null} element - The element that was edited inline.
* @param {boolean} shouldAutoSave - Whether to autosave the restored element HTML.
* @returns {Promise<void>}
*/
finishInlineTipTapEditor(element: HTMLElement | null, shouldAutoSave?: boolean): Promise<void>;
/**
* Wraps an element in a div if it's an excluded tag and adjacent to an image.
* @param {HTMLElement} element - The element to potentially wrap.
* @private
*/
private wrapElementInDivIfExcluded;
/**
* Handles the mouseover event for editable elements, showing a hover state.
* @param {Event} e - The mouse event.
* @param {HTMLElement} element - The element being hovered over.
* @private
*/
private handleMouseOver;
/**
* Handles the mouseleave event for editable elements, removing the hover state.
* @param {Event} e - The mouse event.
* @private
*/
private handleMouseLeave;
/**
* Checks if an element is editable based on its tag name.
* @param {Element | null} el - The element to check.
* @returns {boolean} True if the element is editable, false otherwise.
*/
isEditableElement(el: Element | null): boolean;
getSelectedComponentSection(): HTMLElement | null;
isSelectedComponentTopElement(): boolean;
selectedComponentIsFullWidth(): boolean;
setSelectedComponentFullWidth(enabled: boolean): Promise<void>;
isSelectedProductSection(): boolean;
getSelectedProductSectionOptions(): ProductSectionOptions;
getSelectedProductSectionContentAvailability(): {
hasPrices: boolean;
hasImages: boolean;
hasButtons: boolean;
hasLinks: boolean;
};
updateSelectedProductSection(options: ProductSectionOptions): Promise<void>;
/**
* Returns true when the global page wrapper has the full-width class applied.
*/
isGlobalFullWidth(): boolean;
/**
* Toggles the full-width class on the page wrapper so that global background
* colours stretch across the entire browser viewport.
*/
setGlobalFullWidth(enabled: boolean): Promise<void>;
/** Returns true when the currently selected element is an `<img>`. */
isSelectedElementImage(): boolean;
setImageSettingsModalOpen(open: boolean): void;
isImageSettingsModalOpen(): boolean;
private findImageAspectClass;
private removeImageAspectClasses;
handleImageObjectFit(userSelection?: string): void;
handleImageObjectPosition(userSelection?: string): void;
handleImageAspectRatio(userSelection?: string): void;
handleImageAltText(alt?: string): Promise<void>;
getSelectedImageAltText(): string;
/**
* Attaches click, mouseover, and mouseleave event listeners to all editable elements in the page builder.
* @private
*/
private addListenersToEditableElements;
private attachCanvasInlineEditListeners;
findEditableElementFromEventTarget(target: EventTarget | null): HTMLElement | null;
private handleCanvasClickCapture;
private handleCanvasDoubleClickCapture;
openInlineTipTapFromEvent(e: Event): Promise<void>;
private hasInlineTipTapElement;
/**
* Writes any active inline TipTap editor back to the live DOM synchronously.
* Used before localStorage persistence and before the builder unmounts.
*/
private commitActiveInlineTipTapEditorSync;
/**
* Commits open inline editors and persists the current canvas to localStorage.
* Call before destroying the PageBuilder component (e.g. modal v-if close).
*/
flushPendingEditsToLocalStorage(): void;
finishActiveInlineTipTapEditorFromDom(nextElement?: HTMLElement | null): Promise<void>;
/**
* Handles the click event for editable elements, setting the element as selected.
* @param {Event} e - The click event.
* @param {HTMLElement} element - The clicked element.
* @private
*/
private handleElementClick;
/**
* Opens inline rich-text editing when a valid text element is double-clicked.
* @param {Event} e - The double-click event.
* @param {HTMLElement} element - The double-clicked element.
* @private
*/
private handleElementDoubleClick;
private openInlineTipTapForElement;
/**
* Selects an editable builder element and syncs builder state.
* @param {HTMLElement} element - The element to select.
* @param {boolean} shouldAutoSave - Whether to autosave after selection.
* @returns {Promise<void>}
*/
selectEditableElement(element: HTMLElement, shouldAutoSave?: boolean): Promise<void>;
private getHistoryBaseKey;
private initializeHistory;
/**
* Triggers an auto-save of the current page builder content to local storage if enabled.
*/
handleAutoSave: () => Promise<void>;
/**
* Manually saves the current page builder content to local storage.
*/
handleManualSave: (doNoClearHTML?: boolean) => Promise<void>;
/**
* Clones a component object and prepares it for insertion into the DOM by adding unique IDs and prefixes.
* @param {ComponentObject} componentObject - The component object to clone.
* @returns {ComponentObject} The cloned and prepared component object.
*/
cloneCompObjForDOMInsertion(componentObject: ComponentObject): ComponentObject;
/**
* Removes the 'hovered' and 'selected' attributes from all elements in the page builder.
* @private
*/
private removeHoveredAndSelected;
/**
* Syncs the CSS classes of the currently selected element to the state store.
* @private
*/
private syncCurrentClasses;
/**
* Syncs the inline styles of the currently selected element to the state store.
* @private
*/
private syncCurrentStyles;
/**
* Returns the element style/class controls should mutate.
* In global page-design mode, always use #pagebuilder.
*/
private getActiveStyleTarget;
/**
* Adds a CSS class to the currently selected element.
* @param {string} userSelectedClass - The class to add.
*/
handleAddClasses(userSelectedClass: string): void;
/**
* Adds or updates an inline style property on the currently selected element.
* @param {string} property - The CSS property to add/update.
* @param {string} value - The value of the CSS property.
*/
handleAddStyle(property: string, value: string): void;
/**
* Removes an inline style property from the currently selected element.
* @param {string} property - The CSS property to remove.
*/
handleRemoveStyle(property: string): void;
/**
* Handles changes to the font family of the selected element.
* @param {string} [userSelectedFontFamily] - The selected font family class.
*/
handleFontFamily(userSelectedFontFamily?: string): Promise<void>;
/**
* Handles changes to the font style of the selected element.
* @param {string} [userSelectedFontStyle] - The selected font style class.
*/
handleFontStyle(userSelectedFontStyle?: string): void;
/**
* Removes every class that appears in any of the given arrays from the currently
* selected element. Used to strip conflicting shorthand/directional padding or
* margin classes before applying a new value (e.g. remove pbx-py-* when setting
* pbx-pt-*, so the shorthand never silently overrides the directional value).
*/
private purgeConflictingClasses;
/**
* Handles changes to the vertical padding of the selected element.
* py-* shorthand: also clear individual pt-* and pb-* so they don't override.
*/
handleVerticalPadding(userSelectedVerticalPadding?: string): void;
/**
* Handles changes to the horizontal padding of the selected element.
* px-* shorthand: also clear individual pl-* and pr-* so they don't override.
*/
handleHorizontalPadding(userSelectedHorizontalPadding?: string): void;
/**
* Handles changes to the top padding of the selected element.
* pt-*: also clear py-* shorthand which also sets padding-top.
*/
handleTopPadding(userSelectedTopPadding?: string): void;
/**
* Handles changes to the right padding of the selected element.
* pr-*: also clear px-* shorthand which also sets padding-right.
*/
handleRightPadding(userSelectedRightPadding?: string): void;
/**
* Handles changes to the bottom padding of the selected element.
* pb-*: also clear py-* shorthand which also sets padding-bottom.
*/
handleBottomPadding(userSelectedBottomPadding?: string): void;
/**
* Handles changes to the left padding of the selected element.
* pl-*: also clear px-* shorthand which also sets padding-left.
*/
handleLeftPadding(userSelectedLeftPadding?: string): void;
/**
* Handles changes to the vertical margin of the selected element.
* my-* shorthand: also clear individual mt-* and mb-*.
*/
handleVerticalMargin(userSelectedVerticalMargin?: string): void;
/**
* Handles changes to the horizontal margin of the selected element.
* mx-* shorthand: also clear individual ml-* and mr-*.
*/
handleHorizontalMargin(userSelectedHorizontalMargin?: string): void;
/**
* Handles changes to the top margin of the selected element.
* mt-*: also clear my-* shorthand.
*/
handleTopMargin(userSelectedTopMargin?: string): void;
/**
* Handles changes to the right margin of the selected element.
* mr-*: also clear mx-* shorthand.
*/
handleRightMargin(userSelectedRightMargin?: string): void;
/**
* Handles changes to the bottom margin of the selected element.
* mb-*: also clear my-* shorthand.
*/
handleBottomMargin(userSelectedBottomMargin?: string): void;
/**
* Handles changes to the left margin of the selected element.
* ml-*: also clear mx-* shorthand.
*/
handleLeftMargin(userSelectedLeftMargin?: string): void;
/**
* Handles changes to the border style of the selected element.
* @param {string} [borderStyle] - The selected border style class.
*/
handleBorderStyle(borderStyle?: string): void;
/**
* Handles changes to the border width of the selected element.
* @param {string} [borderWidth] - The selected border width class.
*/
handleBorderWidth(borderWidth?: string): void;
/**
* Handles changes to the border color of the selected element.
* @param {string} [borderColor] - The selected border color class.
*/
handleBorderColor(borderColor?: string): void;
/**
* Handles changes to the background color of the selected element.
* @param {string} [color] - The selected background color class.
*/
handleBackgroundColor(color?: string): void;
handleCustomBackgroundColor(color: string): void;
/**
* Handles changes to the text color of the selected element.
* @param {string} [color] - The selected text color class.
*/
handleTextColor(color?: string): void;
handleCustomTextColor(color: string): void;
/**
* Handles changes to the global border radius of the selected element.
* @param {string} [borderRadiusGlobal] - The selected global border radius class.
*/
handleBorderRadiusGlobal(borderRadiusGlobal?: string): void;
/**
* Handles changes to the top-left border radius of the selected element.
* @param {string} [borderRadiusTopLeft] - The selected top-left border radius class.
*/
handleBorderRadiusTopLeft(borderRadiusTopLeft?: string): void;
/**
* Handles changes to the top-right border radius of the selected element.
* @param {string} [borderRadiusTopRight] - The selected top-right border radius class.
*/
handleBorderRadiusTopRight(borderRadiusTopRight?: string): void;
/**
* Handles changes to the bottom-left border radius of the selected element.
* @param {string} [borderRadiusBottomleft] - The selected bottom-left border radius class.
*/
handleBorderRadiusBottomleft(borderRadiusBottomleft?: string): void;
/**
* Handles changes to the bottom-right border radius of the selected element.
* @param {string} [borderRadiusBottomRight] - The selected bottom-right border radius class.
*/
handleBorderRadiusBottomRight(borderRadiusBottomRight?: string): void;
/**
* Handles changes to the tablet font size of the selected element.
* @param {string} [userSelectedFontSize] - The selected font size class for tablet.
*/
handleFontSizeTablet(userSelectedFontSize?: string): void;
/**
* Handles changes to the mobile font size of the selected element.
* @param {string} [userSelectedFontSize] - The selected font size class for mobile.
*/
handleFontSizeMobile(userSelectedFontSize?: string): void;
/**
* Handles changes to the background opacity of the selected element.
* @param {string} [opacity] - The selected background opacity class.
*/
handleBackgroundOpacity(opacity?: string): void;
/**
* Handles changes to the opacity of the selected element.
* @param {string} [opacity] - The selected opacity class.
*/
handleOpacity(opacity?: string): void;
/**
* Removes all components from both the builder state and the DOM.
* @private
*/
private deleteAllComponentsFromDOM;
undo(): Promise<void>;
redo(): Promise<void>;
private hasVisibleContent;
private isSectionEmpty;
/**
* Duplicate the currently selected component from the DOM and the state.
* @returns {Promise<void>}
*/
/**
* Finds the first two-column layout container inside the selected section.
* Matches flex-row containers (including responsive variants like lg:pbx-flex-row)
* AND grid containers with a grid-cols-2 class, in each case requiring exactly
* two direct element children. Returns the container or null.
*/
findReverseableContainer(): HTMLElement | null;
/**
* Reverses the visual order of a two-column layout by physically swapping the
* two direct children of the detected container. This works for both flex-row
* and grid-cols-2 layouts and naturally toggles on repeated clicks.
* Persists the change to the store and localStorage.
*/
reverseComponentLayout(): Promise<void>;
duplicateComponent(): Promise<void>;
/**
* Deletes the currently selected component from the DOM and the state.
* @returns {Promise<void>}
*/
deleteComponentFromDOM(): Promise<void>;
/**
* Duplicates the currently selected element and inserts the copy immediately
* after it in the DOM, then syncs the change to the store.
*/
duplicateElementInDOM(): Promise<void>;
/**
* Deletes the currently selected element from the DOM and stores it for potential restoration.
* @returns {Promise<void>}
*/
deleteElementFromDOM(): Promise<void>;
/**
* Removes a CSS class from the currently selected element.
* @param {string} userSelectedClass - The class to remove.
*/
handleRemoveClasses(userSelectedClass: string): void;
/**
* Reorders the currently selected component up or down in the component list.
* @param {number} direction - The direction to move the component (-1 for up, 1 for down).
*/
reorderComponent(direction: number): Promise<void>;
/**
* Checks if the currently selected component can be moved up.
* @returns {boolean} True if the component can be moved up, false otherwise.
*/
canMoveUp(): boolean;
/**
* Checks if the currently selected component can be moved down.
* @returns {boolean} True if the component can be moved down, false otherwise.
*/
canMoveDown(): boolean;
/**
* Ensures that a text area element has content, adding a visual indicator if it's empty.
*/
ensureTextAreaHasContent: () => void;
/**
* Handles text input for an element, updating its content.
* @param {string} textContentVueModel - The new text content from the Vue model.
* @returns {Promise<void>}
*/
handleTextInput: (textContentVueModel: string) => Promise<void>;
/**
* Checks if the selected element or its first child is an iframe.
* @returns {boolean} True if it is an iframe, false otherwise.
*/
ElOrFirstChildIsIframe(): boolean;
/**
* Checks whether an element can be edited with inline TipTap (no images/div-only children).
* @param {HTMLElement | null | undefined} element - The element to validate.
* @returns {boolean} True when inline rich-text editing is allowed.
*/
isValidTextElement(element: HTMLElement | null | undefined): boolean;
/**
* Checks if the selected element is a valid text container (i.e., does not contain images or divs).
* @returns {boolean} True if it's a valid text element, otherwise false.
*/
isSelectedElementValidText(): boolean;
/**
* Generates a preview of the current page design.
*/
previewCurrentDesign(): void;
/**
* Sanitizes a string to be used as a key in local storage.
* @param {string} input - The string to sanitize.
* @returns {string} The sanitized string.
*/
sanitizeForLocalStorage(input: string): string;
/**
* Clones an element and removes selection-related attributes from the clone.
* @param {HTMLElement} element - The element to clone.
* @returns {HTMLElement} The sanitized clone.
* @private
*/
private cloneAndRemoveSelectionAttributes;
/**
* Returns section elements to persist from #pagebuilder.
* Prefer sections with data-componentid, but fall back to top-level sections
* so close/reopen cannot wipe content when ids are temporarily missing.
*/
private getPersistableSections;
/**
* Syncs the current DOM state of components to the in-memory store.
* @private
*/
syncDomToStoreOnly(): Promise<void>;
generateHtmlFromComponents(): Promise<string>;
generateFullPageHtml(): Promise<string>;
/**
* Saves the current DOM state of components to local storage.
* @private
*/
private saveDomComponentsToLocalStorage;
/**
* Removes the current page's components from local storage.
* @private
*/
private removeCurrentComponentsFromLocalStorage;
/**
* Handles the form submission process, clearing local storage and the DOM.
* By default, global page settings (classes / inline styles on the wrapper)
* are reset so a brand-new resource starts clean after submit.
*
* Pass `{ preservePageSettings: true }` when you want "remove all components"
* behavior that keeps wrapper classes/styles.
* @returns {Promise<void>}
*/
handleFormSubmission(options?: {
preservePageSettings?: boolean;
}): Promise<void>;
/**
* Reads the current page settings.
* Prioritises the live #pagebuilder element (always current) and falls back to localStorage.
*/
private readCurrentPageSettings;
private readPersistedPageSettingsFromLocalStorage;
/** Applies captured global page classes/styles to the page wrapper once. */
private applyPageSettingsToPage;
/** Reconnects the global-styles MutationObserver after a Vue remount replaces nodes. */
private reconnectGlobalStylesObserver;
/**
* Updates the component store and re-renders the page without losing global page
* styles on #pagebuilder. Settings must be captured before the remount and
* re-applied after Vue renders.
*/
private setComponentsPreservingPageSettings;
/**
* Parses a CSS style string into a key-value object.
* @param {string} style - The style string to parse.
* @returns {Record<string, string>} The parsed style object.
* @private
*/
private parseStyleString;
/**
* Deletes old page builder data from local storage (older than 2 weeks).
*/
deleteOldPageBuilderLocalStorage(): void;
/**
* Sets a flag to indicate that the user has started editing.
*/
startEditing(): void;
/**
* Re-attaches click/hover listeners to any newly added DOM elements.
* Call this after programmatically inserting elements into the builder canvas.
*/
refreshListeners(): Promise<void>;
/**
* Applies config-provided pageSettings.style to #pagebuilder when the element
* has no inline style attribute. Safe to call on every canvas refresh because
* the guard `!domStyle` means user-edited styles are never overwritten.
*/
private reapplyConfigPageSettingsIfMissing;
/**
* Resumes editing from a draft saved in local storage.
* @returns {Promise<void>}
*/
resumeEditingFromDraft(): Promise<void>;
/**
* Restores the original content that was loaded when the builder started.
* @returns {Promise<void>}
*/
restoreOriginalContent(): Promise<void>;
returnLatestComponents(): Promise<ComponentObject[]>;
/**
* Gets the local storage key for the current resource.
* @returns {string | null} The local storage key.
*/
getStorageItemNameForResource(): string | null;
/**
* Retrieves the saved page HTML from local storage.
* @returns {string | false} The HTML string or false if not found.
*/
getSavedPageHtml(): string | false;
/**
* Applies a selected image to the current element.
* @param {ImageObject} image - The image object to apply.
* @returns {Promise<void>}
*/
applySelectedImage(image: ImageObject): Promise<void>;
/**
* Sets the base primary image from the currently selected element if it's an image.
* @private
*/
private setBasePrimaryImageFromSelectedElement;
/**
* Adds or removes a hyperlink from the selected element.
* @param {boolean} hyperlinkEnable - Whether to enable or disable the hyperlink.
* @param {string | null} urlInput - The URL for the hyperlink.
* @param {boolean} openHyperlinkInNewTab - Whether the link should open in a new tab.
* @private
*/
private addHyperlinkToElement;
/**
* Checks if the selected element contains a hyperlink and updates the state accordingly.
* @private
*/
private checkForHyperlink;
/**
* Handles all hyperlink-related actions for the selected element.
* @param {boolean} [hyperlinkEnable] - Whether to enable or disable the hyperlink.
* @param {string | null} [urlInput] - The URL for the hyperlink.
* @param {boolean} [openHyperlinkInNewTab] - Whether the link should open in a new tab.
*/
handleHyperlink(hyperlinkEnable?: boolean, urlInput?: string | null, openHyperlinkInNewTab?: boolean): void;
addTheme(components: string): Promise<void>;
/**
* Replaces the entire page with a theme template (clears existing sections first).
*/
replaceTheme(themeHtml: string): Promise<void>;
getPageMeta(): PageMeta;
setPageMeta(partial: Partial<PageMeta>): Promise<void>;
analyzeSEO(): Promise<SEOSummary>;
/**
* Adds a new component to the page builder.
* @param {ComponentObject} componentObject - The component to add.
* @returns {Promise<void>}
*/
addComponent(componentObject: ComponentObject): Promise<void>;
/**
* Inserts a product section using raw HTML from a custom product picker.
*/
insertProductHtml(html: string, title?: string): Promise<void>;
/**
* Inserts products using a built-in grid layout helper.
* Hosts can also call insertProductHtml() with fully custom markup.
*/
insertProducts(products: ReadonlyArray<PageBuilderProductInput>, options?: InsertProductsOptions): Promise<void>;
/**
* Adds a prefix to Tailwind CSS classes in a string.
* @param {string} classList - The string of classes.
* @param {string} [prefix='pbx-'] - The prefix to add.
* @returns {string} The prefixed class string.
* @private
*/
private addTailwindPrefixToClasses;
/**
* Converts a style object to a CSS string.
* @param {string | Record<string, string> | null | undefined} styleObj - The style object.
* @returns {string} The CSS style string.
* @private
*/
private convertStyleObjectToString;
private hasMeaningfulPageSettings;
/**
* Parses a string of HTML and extracts builder components and global page settings.
* - This method expects an **HTML string** containing one or more `<section>...</section>` elements (such as the output from `getSavedPageHtml()` or a previously saved builder HTML string).
* - **Do NOT pass a JSON string** (such as the result of `JSON.stringify(componentsArray)`) to this method. Passing a JSON string to `DOMParser.parseFromString(..., 'text/html')` will not produce valid DOM nodes. Instead, it will treat the JSON as plain text, resulting in a `<html><head></head><body>{...json...}</body></html>` structure, not real HTML elements.
* - If you pass a JSON string, you will see lots of `\n` and strange HTML, because the parser is just wrapping your JSON in a `<body>` tag as text.
*
* Why only HTML?
* - It enforces a single source of truth for builder state (HTML).
* - It prevents misuse (e.g., passing JSON to a DOM parser, which is always a bug).
* - It makes your documentation and support much simpler.
*
* @param htmlString - The HTML string to parse (must contain `<section>...</section>` elements, not JSON).
* @returns An object with `components` (array of builder components) and `pageSettings` (global styles for the page).
*/
parsePageBuilderHTML(htmlString: string): {
components: ComponentObject[];
pageSettings: PageSettings;
};
/**
* Applies modified components by mounting them to the DOM and attaching listeners.
* @param htmlString - The HTML string to apply
* @returns {Promise<string | null>} - Returns error message if failed, otherwise null
*/
applyModifiedHTML(htmlString: string): Promise<string | null>;
private validateMountingHTML;
/**
* Applies modified components by mounting them to the DOM and attaching listeners.
* @param htmlString - The HTML string to apply
* @returns {Promise<string | null>} - Returns error message if failed, otherwise null
*/
applyModifiedComponents(htmlString: string): Promise<string | null>;
/**
* Mounts builder components to the DOM from an HTML string.
*
* Input format detection:
* - If the input starts with `[` or `{`: treated as JSON (array or object).
* - If the input starts with `<`: treated as HTML.
*
* This function should be used when:
* - Restoring the builder from a published HTML snapshot.
* - Importing a static HTML export.
* - Loading the builder from previously published or saved HTML (e.g., from `getSavedPageHtml()`).
*
* Typical use cases include restoring a published state, importing templates, or previewing published content.
*/
private mountComponentsToDOM;
private updateLocalStorageItemName;
/**
* Initializes the styles for the currently selected element.
*/
initializeElementStyles(): Promise<void>;
}
declare interface PageBuilderState {
componentArrayAddMethod: string | null;
localStorageItemName: string | null;
showModalTipTap: boolean;
inlineTipTapEditor: boolean;
menuRight: boolean;
borderStyle: string | null;
borderWidth: string | null;
borderColor: string | null;
borderRadiusGlobal: string | null;
borderRadiusTopLeft: string | null;
borderRadiusTopRight: string | null;
borderRadiusBottomleft: string | null;
borderRadiusBottomRight: string | null;
elementContainsHyperlink: boolean | null;
hyperlinkAbility: boolean | null;
hyperlinkInput: string | null;
hyperlinkMessage: string | null;
hyperlinkError: string | null;
hyberlinkEnable: boolean;
openHyperlinkinkInNewTab: boolean | null;
opacity: string | null;
backgroundOpacity: string | null;
textAreaVueModel: string | null;
currentClasses: string[];
currentStyles: Record<string, string>;
fontVerticalPadding: string | null;
fontHorizontalPadding: string | null;
fontTopPadding: string | null;
fontRightPadding: string | null;
fontBottomPadding: string | null;
fontLeftPadding: string | null;
fontVerticalMargin: string | null;
fontHorizontalMargin: string | null;
fontTopMargin: string | null;
fontRightMargin: string | null;
fontBottomMargin: string | null;
fontLeftMargin: string | null;
fontStyle: string | null;
fontFamily: string | null;
fontWeight: string | null;
fontBase: string | null;
fontDesktop: string | null;
fontTablet: string | null;
fontMob