UNPKG

@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
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