File: /home/xedaptot/ai.naniguide.com/public/builder/builder.js
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
var BuilderBundle;
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/ejs-browser/lib/ejs.js":
/*!*********************************************!*\
!*** ./node_modules/ejs-browser/lib/ejs.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
eval("/*\n * EJS Embedded JavaScript templates\n * Copyright 2112 Matthew Eernisse ([email protected])\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n*/\n\n\n\n/**\n * @file Embedded JavaScript templating engine. {@link http://ejs.co}\n * @author Matthew Eernisse <[email protected]>\n * @author Tiancheng \"Timothy\" Gu <[email protected]>\n * @project EJS\n * @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0}\n */\n\n/**\n * EJS internal functions.\n *\n * Technically this \"module\" lies in the same file as {@link module:ejs}, for\n * the sake of organization all the private functions re grouped into this\n * module.\n *\n * @module ejs-internal\n * @private\n */\n\n/**\n * Embedded JavaScript templating engine.\n *\n * @module ejs\n * @public\n */\n\n\nvar fs = {};\nvar path = {};\nvar utils = __webpack_require__(/*! ./utils */ \"./node_modules/ejs-browser/lib/utils.js\");\n\nvar scopeOptionWarned = false;\n/** @type {string} */\nvar _VERSION_STRING = (__webpack_require__(/*! ../package.json */ \"./node_modules/ejs-browser/package.json\").version);\nvar _DEFAULT_OPEN_DELIMITER = '<';\nvar _DEFAULT_CLOSE_DELIMITER = '>';\nvar _DEFAULT_DELIMITER = '%';\nvar _DEFAULT_LOCALS_NAME = 'locals';\nvar _NAME = 'ejs';\nvar _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)';\nvar _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug',\n 'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async'];\n// We don't allow 'cache' option to be passed in the data obj for\n// the normal `render` call, but this is where Express 2 & 3 put it\n// so we make an exception for `renderFile`\nvar _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache');\nvar _BOM = /^\\uFEFF/;\nvar _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;\n\n/**\n * EJS template function cache. This can be a LRU object from lru-cache NPM\n * module. By default, it is {@link module:utils.cache}, a simple in-process\n * cache that grows continuously.\n *\n * @type {Cache}\n */\n\nexports.cache = utils.cache;\n\n/**\n * Custom file loader. Useful for template preprocessing or restricting access\n * to a certain part of the filesystem.\n *\n * @type {fileLoader}\n */\n\nexports.fileLoader = fs.readFileSync;\n\n/**\n * Name of the object containing the locals.\n *\n * This variable is overridden by {@link Options}`.localsName` if it is not\n * `undefined`.\n *\n * @type {String}\n * @public\n */\n\nexports.localsName = _DEFAULT_LOCALS_NAME;\n\n/**\n * Promise implementation -- defaults to the native implementation if available\n * This is mostly just for testability\n *\n * @type {PromiseConstructorLike}\n * @public\n */\n\nexports.promiseImpl = (new Function('return this;'))().Promise;\n\n/**\n * Get the path to the included file from the parent file path and the\n * specified path.\n *\n * @param {String} name specified path\n * @param {String} filename parent file path\n * @param {Boolean} [isDir=false] whether the parent file path is a directory\n * @return {String}\n */\nexports.resolveInclude = function(name, filename, isDir) {\n var dirname = path.dirname;\n var extname = path.extname;\n var resolve = path.resolve;\n var includePath = resolve(isDir ? filename : dirname(filename), name);\n var ext = extname(name);\n if (!ext) {\n includePath += '.ejs';\n }\n return includePath;\n};\n\n/**\n * Try to resolve file path on multiple directories\n *\n * @param {String} name specified path\n * @param {Array<String>} paths list of possible parent directory paths\n * @return {String}\n */\nfunction resolvePaths(name, paths) {\n var filePath;\n if (paths.some(function (v) {\n filePath = exports.resolveInclude(name, v, true);\n return fs.existsSync(filePath);\n })) {\n return filePath;\n }\n}\n\n/**\n * Get the path to the included file by Options\n *\n * @param {String} path specified path\n * @param {Options} options compilation options\n * @return {String}\n */\nfunction getIncludePath(path, options) {\n var includePath;\n var filePath;\n var views = options.views;\n var match = /^[A-Za-z]+:\\\\|^\\//.exec(path);\n\n // Abs path\n if (match && match.length) {\n path = path.replace(/^\\/*/, '');\n if (Array.isArray(options.root)) {\n includePath = resolvePaths(path, options.root);\n } else {\n includePath = exports.resolveInclude(path, options.root || '/', true);\n }\n }\n // Relative paths\n else {\n // Look relative to a passed filename first\n if (options.filename) {\n filePath = exports.resolveInclude(path, options.filename);\n if (fs.existsSync(filePath)) {\n includePath = filePath;\n }\n }\n // Then look in any views directories\n if (!includePath && Array.isArray(views)) {\n includePath = resolvePaths(path, views);\n }\n if (!includePath && typeof options.includer !== 'function') {\n throw new Error('Could not find the include file \"' +\n options.escapeFunction(path) + '\"');\n }\n }\n return includePath;\n}\n\n/**\n * Get the template from a string or a file, either compiled on-the-fly or\n * read from cache (if enabled), and cache the template if needed.\n *\n * If `template` is not set, the file specified in `options.filename` will be\n * read.\n *\n * If `options.cache` is true, this function reads the file from\n * `options.filename` so it must be set prior to calling this function.\n *\n * @memberof module:ejs-internal\n * @param {Options} options compilation options\n * @param {String} [template] template source\n * @return {(TemplateFunction|ClientFunction)}\n * Depending on the value of `options.client`, either type might be returned.\n * @static\n */\n\nfunction handleCache(options, template) {\n var func;\n var filename = options.filename;\n var hasTemplate = arguments.length > 1;\n\n if (options.cache) {\n if (!filename) {\n throw new Error('cache option requires a filename');\n }\n func = exports.cache.get(filename);\n if (func) {\n return func;\n }\n if (!hasTemplate) {\n template = fileLoader(filename).toString().replace(_BOM, '');\n }\n }\n else if (!hasTemplate) {\n // istanbul ignore if: should not happen at all\n if (!filename) {\n throw new Error('Internal EJS error: no file name or template '\n + 'provided');\n }\n template = fileLoader(filename).toString().replace(_BOM, '');\n }\n func = exports.compile(template, options);\n if (options.cache) {\n exports.cache.set(filename, func);\n }\n return func;\n}\n\n/**\n * Try calling handleCache with the given options and data and call the\n * callback with the result. If an error occurs, call the callback with\n * the error. Used by renderFile().\n *\n * @memberof module:ejs-internal\n * @param {Options} options compilation options\n * @param {Object} data template data\n * @param {RenderFileCallback} cb callback\n * @static\n */\n\nfunction tryHandleCache(options, data, cb) {\n var result;\n if (!cb) {\n if (typeof exports.promiseImpl == 'function') {\n return new exports.promiseImpl(function (resolve, reject) {\n try {\n result = handleCache(options)(data);\n resolve(result);\n }\n catch (err) {\n reject(err);\n }\n });\n }\n else {\n throw new Error('Please provide a callback function');\n }\n }\n else {\n try {\n result = handleCache(options)(data);\n }\n catch (err) {\n return cb(err);\n }\n\n cb(null, result);\n }\n}\n\n/**\n * fileLoader is independent\n *\n * @param {String} filePath ejs file path.\n * @return {String} The contents of the specified file.\n * @static\n */\n\nfunction fileLoader(filePath){\n return exports.fileLoader(filePath);\n}\n\n/**\n * Get the template function.\n *\n * If `options.cache` is `true`, then the template is cached.\n *\n * @memberof module:ejs-internal\n * @param {String} path path for the specified file\n * @param {Options} options compilation options\n * @return {(TemplateFunction|ClientFunction)}\n * Depending on the value of `options.client`, either type might be returned\n * @static\n */\n\nfunction includeFile(path, options) {\n var opts = utils.shallowCopy(utils.createNullProtoObjWherePossible(), options);\n opts.filename = getIncludePath(path, opts);\n if (typeof options.includer === 'function') {\n var includerResult = options.includer(path, opts.filename);\n if (includerResult) {\n if (includerResult.filename) {\n opts.filename = includerResult.filename;\n }\n if (includerResult.template) {\n return handleCache(opts, includerResult.template);\n }\n }\n }\n return handleCache(opts);\n}\n\n/**\n * Re-throw the given `err` in context to the `str` of ejs, `filename`, and\n * `lineno`.\n *\n * @implements {RethrowCallback}\n * @memberof module:ejs-internal\n * @param {Error} err Error object\n * @param {String} str EJS source\n * @param {String} flnm file name of the EJS file\n * @param {Number} lineno line number of the error\n * @param {EscapeCallback} esc\n * @static\n */\n\nfunction rethrow(err, str, flnm, lineno, esc) {\n var lines = str.split('\\n');\n var start = Math.max(lineno - 3, 0);\n var end = Math.min(lines.length, lineno + 3);\n var filename = esc(flnm);\n // Error context\n var context = lines.slice(start, end).map(function (line, i){\n var curr = i + start + 1;\n return (curr == lineno ? ' >> ' : ' ')\n + curr\n + '| '\n + line;\n }).join('\\n');\n\n // Alter exception message\n err.path = filename;\n err.message = (filename || 'ejs') + ':'\n + lineno + '\\n'\n + context + '\\n\\n'\n + err.message;\n\n throw err;\n}\n\nfunction stripSemi(str){\n return str.replace(/;(\\s*$)/, '$1');\n}\n\n/**\n * Compile the given `str` of ejs into a template function.\n *\n * @param {String} template EJS template\n *\n * @param {Options} [opts] compilation options\n *\n * @return {(TemplateFunction|ClientFunction)}\n * Depending on the value of `opts.client`, either type might be returned.\n * Note that the return type of the function also depends on the value of `opts.async`.\n * @public\n */\n\nexports.compile = function compile(template, opts) {\n var templ;\n\n // v1 compat\n // 'scope' is 'context'\n // FIXME: Remove this in a future version\n if (opts && opts.scope) {\n if (!scopeOptionWarned){\n console.warn('`scope` option is deprecated and will be removed in EJS 3');\n scopeOptionWarned = true;\n }\n if (!opts.context) {\n opts.context = opts.scope;\n }\n delete opts.scope;\n }\n templ = new Template(template, opts);\n return templ.compile();\n};\n\n/**\n * Render the given `template` of ejs.\n *\n * If you would like to include options but not data, you need to explicitly\n * call this function with `data` being an empty object or `null`.\n *\n * @param {String} template EJS template\n * @param {Object} [data={}] template data\n * @param {Options} [opts={}] compilation and rendering options\n * @return {(String|Promise<String>)}\n * Return value type depends on `opts.async`.\n * @public\n */\n\nexports.render = function (template, d, o) {\n var data = d || utils.createNullProtoObjWherePossible();\n var opts = o || utils.createNullProtoObjWherePossible();\n\n // No options object -- if there are optiony names\n // in the data, copy them to options\n if (arguments.length == 2) {\n utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA);\n }\n\n return handleCache(opts, template)(data);\n};\n\n/**\n * Render an EJS file at the given `path` and callback `cb(err, str)`.\n *\n * If you would like to include options but not data, you need to explicitly\n * call this function with `data` being an empty object or `null`.\n *\n * @param {String} path path to the EJS file\n * @param {Object} [data={}] template data\n * @param {Options} [opts={}] compilation and rendering options\n * @param {RenderFileCallback} cb callback\n * @public\n */\n\nexports.renderFile = function () {\n var args = Array.prototype.slice.call(arguments);\n var filename = args.shift();\n var cb;\n var opts = {filename: filename};\n var data;\n var viewOpts;\n\n // Do we have a callback?\n if (typeof arguments[arguments.length - 1] == 'function') {\n cb = args.pop();\n }\n // Do we have data/opts?\n if (args.length) {\n // Should always have data obj\n data = args.shift();\n // Normal passed opts (data obj + opts obj)\n if (args.length) {\n // Use shallowCopy so we don't pollute passed in opts obj with new vals\n utils.shallowCopy(opts, args.pop());\n }\n // Special casing for Express (settings + opts-in-data)\n else {\n // Express 3 and 4\n if (data.settings) {\n // Pull a few things from known locations\n if (data.settings.views) {\n opts.views = data.settings.views;\n }\n if (data.settings['view cache']) {\n opts.cache = true;\n }\n // Undocumented after Express 2, but still usable, esp. for\n // items that are unsafe to be passed along with data, like `root`\n viewOpts = data.settings['view options'];\n if (viewOpts) {\n utils.shallowCopy(opts, viewOpts);\n }\n }\n // Express 2 and lower, values set in app.locals, or people who just\n // want to pass options in their data. NOTE: These values will override\n // anything previously set in settings or settings['view options']\n utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS);\n }\n opts.filename = filename;\n }\n else {\n data = utils.createNullProtoObjWherePossible();\n }\n\n return tryHandleCache(opts, data, cb);\n};\n\n/**\n * Clear intermediate JavaScript cache. Calls {@link Cache#reset}.\n * @public\n */\n\n/**\n * EJS template class\n * @public\n */\nexports.Template = Template;\n\nexports.clearCache = function () {\n exports.cache.reset();\n};\n\nfunction Template(text, opts) {\n opts = opts || utils.createNullProtoObjWherePossible();\n var options = utils.createNullProtoObjWherePossible();\n this.templateText = text;\n /** @type {string | null} */\n this.mode = null;\n this.truncate = false;\n this.currentLine = 1;\n this.source = '';\n options.client = opts.client || false;\n options.escapeFunction = opts.escape || opts.escapeFunction || utils.escapeXML;\n options.compileDebug = opts.compileDebug !== false;\n options.debug = !!opts.debug;\n options.filename = opts.filename;\n options.openDelimiter = opts.openDelimiter || exports.openDelimiter || _DEFAULT_OPEN_DELIMITER;\n options.closeDelimiter = opts.closeDelimiter || exports.closeDelimiter || _DEFAULT_CLOSE_DELIMITER;\n options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER;\n options.strict = opts.strict || false;\n options.context = opts.context;\n options.cache = opts.cache || false;\n options.rmWhitespace = opts.rmWhitespace;\n options.root = opts.root;\n options.includer = opts.includer;\n options.outputFunctionName = opts.outputFunctionName;\n options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME;\n options.views = opts.views;\n options.async = opts.async;\n options.destructuredLocals = opts.destructuredLocals;\n options.legacyInclude = typeof opts.legacyInclude != 'undefined' ? !!opts.legacyInclude : true;\n\n if (options.strict) {\n options._with = false;\n }\n else {\n options._with = typeof opts._with != 'undefined' ? opts._with : true;\n }\n\n this.opts = options;\n\n this.regex = this.createRegex();\n}\n\nTemplate.modes = {\n EVAL: 'eval',\n ESCAPED: 'escaped',\n RAW: 'raw',\n COMMENT: 'comment',\n LITERAL: 'literal'\n};\n\nTemplate.prototype = {\n createRegex: function () {\n var str = _REGEX_STRING;\n var delim = utils.escapeRegExpChars(this.opts.delimiter);\n var open = utils.escapeRegExpChars(this.opts.openDelimiter);\n var close = utils.escapeRegExpChars(this.opts.closeDelimiter);\n str = str.replace(/%/g, delim)\n .replace(/</g, open)\n .replace(/>/g, close);\n return new RegExp(str);\n },\n\n compile: function () {\n /** @type {string} */\n var src;\n /** @type {ClientFunction} */\n var fn;\n var opts = this.opts;\n var prepended = '';\n var appended = '';\n /** @type {EscapeCallback} */\n var escapeFn = opts.escapeFunction;\n /** @type {FunctionConstructor} */\n var ctor;\n /** @type {string} */\n var sanitizedFilename = opts.filename ? JSON.stringify(opts.filename) : 'undefined';\n\n if (!this.source) {\n this.generateSource();\n prepended +=\n ' var __output = \"\";\\n' +\n ' function __append(s) { if (s !== undefined && s !== null) __output += s }\\n';\n if (opts.outputFunctionName) {\n if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) {\n throw new Error('outputFunctionName is not a valid JS identifier.');\n }\n prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\\n';\n }\n if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) {\n throw new Error('localsName is not a valid JS identifier.');\n }\n if (opts.destructuredLocals && opts.destructuredLocals.length) {\n var destructuring = ' var __locals = (' + opts.localsName + ' || {}),\\n';\n for (var i = 0; i < opts.destructuredLocals.length; i++) {\n var name = opts.destructuredLocals[i];\n if (!_JS_IDENTIFIER.test(name)) {\n throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.');\n }\n if (i > 0) {\n destructuring += ',\\n ';\n }\n destructuring += name + ' = __locals.' + name;\n }\n prepended += destructuring + ';\\n';\n }\n if (opts._with !== false) {\n prepended += ' with (' + opts.localsName + ' || {}) {' + '\\n';\n appended += ' }' + '\\n';\n }\n appended += ' return __output;' + '\\n';\n this.source = prepended + this.source + appended;\n }\n\n if (opts.compileDebug) {\n src = 'var __line = 1' + '\\n'\n + ' , __lines = ' + JSON.stringify(this.templateText) + '\\n'\n + ' , __filename = ' + sanitizedFilename + ';' + '\\n'\n + 'try {' + '\\n'\n + this.source\n + '} catch (e) {' + '\\n'\n + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\\n'\n + '}' + '\\n';\n }\n else {\n src = this.source;\n }\n\n if (opts.client) {\n src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\\n' + src;\n if (opts.compileDebug) {\n src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\\n' + src;\n }\n }\n\n if (opts.strict) {\n src = '\"use strict\";\\n' + src;\n }\n if (opts.debug) {\n console.log(src);\n }\n if (opts.compileDebug && opts.filename) {\n src = src + '\\n'\n + '//# sourceURL=' + sanitizedFilename + '\\n';\n }\n\n try {\n if (opts.async) {\n // Have to use generated function for this, since in envs without support,\n // it breaks in parsing\n try {\n ctor = (new Function('return (async function(){}).constructor;'))();\n }\n catch(e) {\n if (e instanceof SyntaxError) {\n throw new Error('This environment does not support async/await');\n }\n else {\n throw e;\n }\n }\n }\n else {\n ctor = Function;\n }\n fn = new ctor(opts.localsName + ', escapeFn, include, rethrow', src);\n }\n catch(e) {\n // istanbul ignore else\n if (e instanceof SyntaxError) {\n if (opts.filename) {\n e.message += ' in ' + opts.filename;\n }\n e.message += ' while compiling ejs\\n\\n';\n e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\\n';\n e.message += 'https://github.com/RyanZim/EJS-Lint';\n if (!opts.async) {\n e.message += '\\n';\n e.message += 'Or, if you meant to create an async function, pass `async: true` as an option.';\n }\n }\n throw e;\n }\n\n // Return a callable function which will execute the function\n // created by the source-code, with the passed data as locals\n // Adds a local `include` function which allows full recursive include\n var returnedFn = opts.client ? fn : function anonymous(data) {\n var include = function (path, includeData) {\n var d = utils.shallowCopy(utils.createNullProtoObjWherePossible(), data);\n if (includeData) {\n d = utils.shallowCopy(d, includeData);\n }\n return includeFile(path, opts)(d);\n };\n return fn.apply(opts.context,\n [data || utils.createNullProtoObjWherePossible(), escapeFn, include, rethrow]);\n };\n if (opts.filename && typeof Object.defineProperty === 'function') {\n var filename = opts.filename;\n var basename = path.basename(filename, path.extname(filename));\n try {\n Object.defineProperty(returnedFn, 'name', {\n value: basename,\n writable: false,\n enumerable: false,\n configurable: true\n });\n } catch (e) {/* ignore */}\n }\n return returnedFn;\n },\n\n generateSource: function () {\n var opts = this.opts;\n\n if (opts.rmWhitespace) {\n // Have to use two separate replace here as `^` and `$` operators don't\n // work well with `\\r` and empty lines don't work well with the `m` flag.\n this.templateText =\n this.templateText.replace(/[\\r\\n]+/g, '\\n').replace(/^\\s+|\\s+$/gm, '');\n }\n\n // Slurp spaces and tabs before <%_ and after _%>\n this.templateText =\n this.templateText.replace(/[ \\t]*<%_/gm, '<%_').replace(/_%>[ \\t]*/gm, '_%>');\n\n var self = this;\n var matches = this.parseTemplateText();\n var d = this.opts.delimiter;\n var o = this.opts.openDelimiter;\n var c = this.opts.closeDelimiter;\n\n if (matches && matches.length) {\n matches.forEach(function (line, index) {\n var closing;\n // If this is an opening tag, check for closing tags\n // FIXME: May end up with some false positives here\n // Better to store modes as k/v with openDelimiter + delimiter as key\n // Then this can simply check against the map\n if ( line.indexOf(o + d) === 0 // If it is a tag\n && line.indexOf(o + d + d) !== 0) { // and is not escaped\n closing = matches[index + 2];\n if (!(closing == d + c || closing == '-' + d + c || closing == '_' + d + c)) {\n throw new Error('Could not find matching close tag for \"' + line + '\".');\n }\n }\n self.scanLine(line);\n });\n }\n\n },\n\n parseTemplateText: function () {\n var str = this.templateText;\n var pat = this.regex;\n var result = pat.exec(str);\n var arr = [];\n var firstPos;\n\n while (result) {\n firstPos = result.index;\n\n if (firstPos !== 0) {\n arr.push(str.substring(0, firstPos));\n str = str.slice(firstPos);\n }\n\n arr.push(result[0]);\n str = str.slice(result[0].length);\n result = pat.exec(str);\n }\n\n if (str) {\n arr.push(str);\n }\n\n return arr;\n },\n\n _addOutput: function (line) {\n if (this.truncate) {\n // Only replace single leading linebreak in the line after\n // -%> tag -- this is the single, trailing linebreak\n // after the tag that the truncation mode replaces\n // Handle Win / Unix / old Mac linebreaks -- do the \\r\\n\n // combo first in the regex-or\n line = line.replace(/^(?:\\r\\n|\\r|\\n)/, '');\n this.truncate = false;\n }\n if (!line) {\n return line;\n }\n\n // Preserve literal slashes\n line = line.replace(/\\\\/g, '\\\\\\\\');\n\n // Convert linebreaks\n line = line.replace(/\\n/g, '\\\\n');\n line = line.replace(/\\r/g, '\\\\r');\n\n // Escape double-quotes\n // - this will be the delimiter during execution\n line = line.replace(/\"/g, '\\\\\"');\n this.source += ' ; __append(\"' + line + '\")' + '\\n';\n },\n\n scanLine: function (line) {\n var self = this;\n var d = this.opts.delimiter;\n var o = this.opts.openDelimiter;\n var c = this.opts.closeDelimiter;\n var newLineCount = 0;\n\n newLineCount = (line.split('\\n').length - 1);\n\n switch (line) {\n case o + d:\n case o + d + '_':\n this.mode = Template.modes.EVAL;\n break;\n case o + d + '=':\n this.mode = Template.modes.ESCAPED;\n break;\n case o + d + '-':\n this.mode = Template.modes.RAW;\n break;\n case o + d + '#':\n this.mode = Template.modes.COMMENT;\n break;\n case o + d + d:\n this.mode = Template.modes.LITERAL;\n this.source += ' ; __append(\"' + line.replace(o + d + d, o + d) + '\")' + '\\n';\n break;\n case d + d + c:\n this.mode = Template.modes.LITERAL;\n this.source += ' ; __append(\"' + line.replace(d + d + c, d + c) + '\")' + '\\n';\n break;\n case d + c:\n case '-' + d + c:\n case '_' + d + c:\n if (this.mode == Template.modes.LITERAL) {\n this._addOutput(line);\n }\n\n this.mode = null;\n this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0;\n break;\n default:\n // In script mode, depends on type of tag\n if (this.mode) {\n // If '//' is found without a line break, add a line break.\n switch (this.mode) {\n case Template.modes.EVAL:\n case Template.modes.ESCAPED:\n case Template.modes.RAW:\n if (line.lastIndexOf('//') > line.lastIndexOf('\\n')) {\n line += '\\n';\n }\n }\n switch (this.mode) {\n // Just executing code\n case Template.modes.EVAL:\n this.source += ' ; ' + line + '\\n';\n break;\n // Exec, esc, and output\n case Template.modes.ESCAPED:\n this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\\n';\n break;\n // Exec and output\n case Template.modes.RAW:\n this.source += ' ; __append(' + stripSemi(line) + ')' + '\\n';\n break;\n case Template.modes.COMMENT:\n // Do nothing\n break;\n // Literal <%% mode, append as raw output\n case Template.modes.LITERAL:\n this._addOutput(line);\n break;\n }\n }\n // In string mode, just add the output\n else {\n this._addOutput(line);\n }\n }\n\n if (self.opts.compileDebug && newLineCount) {\n this.currentLine += newLineCount;\n this.source += ' ; __line = ' + this.currentLine + '\\n';\n }\n }\n};\n\n/**\n * Escape characters reserved in XML.\n *\n * This is simply an export of {@link module:utils.escapeXML}.\n *\n * If `markup` is `undefined` or `null`, the empty string is returned.\n *\n * @param {String} markup Input string\n * @return {String} Escaped string\n * @public\n * @func\n * */\nexports.escapeXML = utils.escapeXML;\n\n/**\n * Express.js support.\n *\n * This is an alias for {@link module:ejs.renderFile}, in order to support\n * Express.js out-of-the-box.\n *\n * @func\n */\n\nexports.__express = exports.renderFile;\n\n/**\n * Version of EJS.\n *\n * @readonly\n * @type {String}\n * @public\n */\n\nexports.VERSION = _VERSION_STRING;\n\n/**\n * Name for detection of EJS.\n *\n * @readonly\n * @type {String}\n * @public\n */\n\nexports.name = _NAME;\n\n/* istanbul ignore if */\nif (typeof window != 'undefined') {\n window.ejs = exports;\n}\n\n\n//# sourceURL=webpack://BuilderBundle/./node_modules/ejs-browser/lib/ejs.js?");
/***/ }),
/***/ "./node_modules/ejs-browser/lib/utils.js":
/*!***********************************************!*\
!*** ./node_modules/ejs-browser/lib/utils.js ***!
\***********************************************/
/***/ ((__unused_webpack_module, exports) => {
eval("/*\n * EJS Embedded JavaScript templates\n * Copyright 2112 Matthew Eernisse ([email protected])\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n*/\n\n/**\n * Private utility functions\n * @module utils\n * @private\n */\n\n\n\nvar regExpChars = /[|\\\\{}()[\\]^$+*?.]/g;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); };\n\n/**\n * Escape characters reserved in regular expressions.\n *\n * If `string` is `undefined` or `null`, the empty string is returned.\n *\n * @param {String} string Input string\n * @return {String} Escaped string\n * @static\n * @private\n */\nexports.escapeRegExpChars = function (string) {\n // istanbul ignore if\n if (!string) {\n return '';\n }\n return String(string).replace(regExpChars, '\\\\$&');\n};\n\nvar _ENCODE_HTML_RULES = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n};\nvar _MATCH_HTML = /[&<>'\"]/g;\n\nfunction encode_char(c) {\n return _ENCODE_HTML_RULES[c] || c;\n}\n\n/**\n * Stringified version of constants used by {@link module:utils.escapeXML}.\n *\n * It is used in the process of generating {@link ClientFunction}s.\n *\n * @readonly\n * @type {String}\n */\n\nvar escapeFuncStr =\n 'var _ENCODE_HTML_RULES = {\\n'\n+ ' \"&\": \"&\"\\n'\n+ ' , \"<\": \"<\"\\n'\n+ ' , \">\": \">\"\\n'\n+ ' , \\'\"\\': \""\"\\n'\n+ ' , \"\\'\": \"'\"\\n'\n+ ' }\\n'\n+ ' , _MATCH_HTML = /[&<>\\'\"]/g;\\n'\n+ 'function encode_char(c) {\\n'\n+ ' return _ENCODE_HTML_RULES[c] || c;\\n'\n+ '};\\n';\n\n/**\n * Escape characters reserved in XML.\n *\n * If `markup` is `undefined` or `null`, the empty string is returned.\n *\n * @implements {EscapeCallback}\n * @param {String} markup Input string\n * @return {String} Escaped string\n * @static\n * @private\n */\n\nexports.escapeXML = function (markup) {\n return markup == undefined\n ? ''\n : String(markup)\n .replace(_MATCH_HTML, encode_char);\n};\n\nfunction escapeXMLToString() {\n return Function.prototype.toString.call(this) + ';\\n' + escapeFuncStr;\n}\n\ntry {\n if (typeof Object.defineProperty === 'function') {\n // If the Function prototype is frozen, the \"toString\" property is non-writable. This means that any objects which inherit this property\n // cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not using strict\n // mode, attempting that will be silently ignored.\n // However, we can still explicitly shadow the prototype's \"toString\" property by defining a new \"toString\" property on this object.\n Object.defineProperty(exports.escapeXML, 'toString', { value: escapeXMLToString });\n } else {\n // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator.\n exports.escapeXML.toString = escapeXMLToString;\n }\n} catch (err) {\n console.warn('Unable to set escapeXML.toString (is the Function prototype frozen?)');\n}\n\n/**\n * Naive copy of properties from one object to another.\n * Does not recurse into non-scalar properties\n * Does not check to see if the property has a value before copying\n *\n * @param {Object} to Destination object\n * @param {Object} from Source object\n * @return {Object} Destination object\n * @static\n * @private\n */\nexports.shallowCopy = function (to, from) {\n from = from || {};\n if ((to !== null) && (to !== undefined)) {\n for (var p in from) {\n if (!hasOwn(from, p)) {\n continue;\n }\n if (p === '__proto__' || p === 'constructor') {\n continue;\n }\n to[p] = from[p];\n }\n }\n return to;\n};\n\n/**\n * Naive copy of a list of key names, from one object to another.\n * Only copies property if it is actually defined\n * Does not recurse into non-scalar properties\n *\n * @param {Object} to Destination object\n * @param {Object} from Source object\n * @param {Array} list List of properties to copy\n * @return {Object} Destination object\n * @static\n * @private\n */\nexports.shallowCopyFromList = function (to, from, list) {\n list = list || [];\n from = from || {};\n if ((to !== null) && (to !== undefined)) {\n for (var i = 0; i < list.length; i++) {\n var p = list[i];\n if (typeof from[p] != 'undefined') {\n if (!hasOwn(from, p)) {\n continue;\n }\n if (p === '__proto__' || p === 'constructor') {\n continue;\n }\n to[p] = from[p];\n }\n }\n }\n return to;\n};\n\n/**\n * Simple in-process cache implementation. Does not implement limits of any\n * sort.\n *\n * @implements {Cache}\n * @static\n * @private\n */\nexports.cache = {\n _data: {},\n set: function (key, val) {\n this._data[key] = val;\n },\n get: function (key) {\n return this._data[key];\n },\n remove: function (key) {\n delete this._data[key];\n },\n reset: function () {\n this._data = {};\n }\n};\n\n/**\n * Transforms hyphen case variable into camel case.\n *\n * @param {String} string Hyphen case string\n * @return {String} Camel case string\n * @static\n * @private\n */\nexports.hyphenToCamel = function (str) {\n return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); });\n};\n\n/**\n * Returns a null-prototype object in runtimes that support it\n *\n * @return {Object} Object, prototype will be set to null where possible\n * @static\n * @private\n */\nexports.createNullProtoObjWherePossible = (function () {\n if (typeof Object.create == 'function') {\n return function () {\n return Object.create(null);\n };\n }\n if (!({__proto__: null} instanceof Object)) {\n return function () {\n return {__proto__: null};\n };\n }\n // Not possible, just pass through\n return function () {\n return {};\n };\n})();\n\n\n\n\n//# sourceURL=webpack://BuilderBundle/./node_modules/ejs-browser/lib/utils.js?");
/***/ }),
/***/ "./node_modules/ejs-browser/package.json":
/*!***********************************************!*\
!*** ./node_modules/ejs-browser/package.json ***!
\***********************************************/
/***/ ((module) => {
eval("module.exports = /*#__PURE__*/JSON.parse('{\"name\":\"ejs-browser\",\"description\":\"Embedded JavaScript templates\",\"keywords\":[\"template\",\"engine\",\"ejs\"],\"version\":\"3.2.2\",\"author\":\"Matthew Eernisse <[email protected]> (http://fleegix.org)\",\"license\":\"Apache-2.0\",\"bin\":{\"ejs\":\"./bin/cli.js\"},\"main\":\"./lib/ejs.js\",\"jsdelivr\":\"ejs.min.js\",\"unpkg\":\"ejs.min.js\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/mde/ejs.git\"},\"bugs\":\"https://github.com/mde/ejs/issues\",\"homepage\":\"https://github.com/mde/ejs\",\"dependencies\":{\"jake\":\"^10.8.5\"},\"devDependencies\":{\"browserify\":\"^16.5.1\",\"eslint\":\"^6.8.0\",\"git-directory-deploy\":\"^1.5.1\",\"jsdoc\":\"^4.0.2\",\"lru-cache\":\"^4.0.1\",\"mocha\":\"^10.2.0\",\"uglify-js\":\"^3.3.16\"},\"engines\":{\"node\":\">=0.10.0\"},\"scripts\":{\"test\":\"mocha -u tdd\",\"publish\":\"npm publish\"}}');\n\n//# sourceURL=webpack://BuilderBundle/./node_modules/ejs-browser/package.json?");
/***/ }),
/***/ "./src/builder.js":
/*!************************!*\
!*** ./src/builder.js ***!
\************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _includes_Builder_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./includes/Builder.js */ \"./src/includes/Builder.js\");\n/* harmony import */ var _includes_I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./includes/I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _includes_BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./includes/BuilderjsPopup.js */ \"./src/includes/BuilderjsPopup.js\");\n/* harmony import */ var _includes_ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./includes/ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _includes_InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./includes/InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\n/* harmony import */ var _includes_overlays_TextInlineToolbarOverlay_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./includes/overlays/TextInlineToolbarOverlay.js */ \"./src/includes/overlays/TextInlineToolbarOverlay.js\");\n/* harmony import */ var _includes_overlays_RichDropdownMenuOverlay_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./includes/overlays/RichDropdownMenuOverlay.js */ \"./src/includes/overlays/RichDropdownMenuOverlay.js\");\n/* harmony import */ var _includes_TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./includes/TextSelectionTracker.js */ \"./src/includes/TextSelectionTracker.js\");\n/* harmony import */ var _includes_WidgetsBox_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./includes/WidgetsBox.js */ \"./src/includes/WidgetsBox.js\");\n/* harmony import */ var _includes_HeadingWidget_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./includes/HeadingWidget.js */ \"./src/includes/HeadingWidget.js\");\n/* harmony import */ var _includes_ParagraphWidget_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./includes/ParagraphWidget.js */ \"./src/includes/ParagraphWidget.js\");\n/* harmony import */ var _includes_WelcomeWidget_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./includes/WelcomeWidget.js */ \"./src/includes/WelcomeWidget.js\");\n/* harmony import */ var _includes_MenuWidget_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./includes/MenuWidget.js */ \"./src/includes/MenuWidget.js\");\n/* harmony import */ var _includes_ListWidget_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./includes/ListWidget.js */ \"./src/includes/ListWidget.js\");\n/* harmony import */ var _includes_ListElement_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./includes/ListElement.js */ \"./src/includes/ListElement.js\");\n/* harmony import */ var _includes_ImageWidget_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./includes/ImageWidget.js */ \"./src/includes/ImageWidget.js\");\n/* harmony import */ var _includes_GridWidget_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./includes/GridWidget.js */ \"./src/includes/GridWidget.js\");\n/* harmony import */ var _includes_SelectWidget_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./includes/SelectWidget.js */ \"./src/includes/SelectWidget.js\");\n/* harmony import */ var _includes_RadioWidget_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./includes/RadioWidget.js */ \"./src/includes/RadioWidget.js\");\n/* harmony import */ var _includes_CheckboxWidget_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./includes/CheckboxWidget.js */ \"./src/includes/CheckboxWidget.js\");\n/* harmony import */ var _includes_PricingCardsWidget_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./includes/PricingCardsWidget.js */ \"./src/includes/PricingCardsWidget.js\");\n/* harmony import */ var _includes_H1Element_js__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./includes/H1Element.js */ \"./src/includes/H1Element.js\");\n/* harmony import */ var _includes_PElement_js__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./includes/PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _includes_MenuElement_js__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./includes/MenuElement.js */ \"./src/includes/MenuElement.js\");\n/* harmony import */ var _includes_GridElement_js__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./includes/GridElement.js */ \"./src/includes/GridElement.js\");\n/* harmony import */ var _includes_CellElement_js__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./includes/CellElement.js */ \"./src/includes/CellElement.js\");\n/* harmony import */ var _includes_ButtonElement_js__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./includes/ButtonElement.js */ \"./src/includes/ButtonElement.js\");\n/* harmony import */ var _includes_ButtonWidget_js__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./includes/ButtonWidget.js */ \"./src/includes/ButtonWidget.js\");\n/* harmony import */ var _includes_VideoElement_js__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./includes/VideoElement.js */ \"./src/includes/VideoElement.js\");\n/* harmony import */ var _includes_VideoWidget_js__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./includes/VideoWidget.js */ \"./src/includes/VideoWidget.js\");\n/* harmony import */ var _includes_AlertElement_js__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./includes/AlertElement.js */ \"./src/includes/AlertElement.js\");\n/* harmony import */ var _includes_AlertWidget_js__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./includes/AlertWidget.js */ \"./src/includes/AlertWidget.js\");\n/* harmony import */ var _includes_TabsManager_js__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ./includes/TabsManager.js */ \"./src/includes/TabsManager.js\");\n/* harmony import */ var _includes_UIManager_js__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./includes/UIManager.js */ \"./src/includes/UIManager.js\");\n/* harmony import */ var _includes_BaseElement_js__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./includes/BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _includes_TextControl_js__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./includes/TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _includes_ImageElement_js__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./includes/ImageElement.js */ \"./src/includes/ImageElement.js\");\n/* harmony import */ var _includes_BaseWidget_js__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./includes/BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _includes_ElementFactory_js__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ./includes/ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _includes_LinkElement_js__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ./includes/LinkElement.js */ \"./src/includes/LinkElement.js\");\n/* harmony import */ var _includes_H2Element_js__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ./includes/H2Element.js */ \"./src/includes/H2Element.js\");\n/* harmony import */ var _includes_H3Element_js__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ./includes/H3Element.js */ \"./src/includes/H3Element.js\");\n/* harmony import */ var _includes_H4Element_js__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ./includes/H4Element.js */ \"./src/includes/H4Element.js\");\n/* harmony import */ var _includes_H5Element_js__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ./includes/H5Element.js */ \"./src/includes/H5Element.js\");\n/* harmony import */ var _includes_TextInputElement_js__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ./includes/TextInputElement.js */ \"./src/includes/TextInputElement.js\");\n/* harmony import */ var _includes_ListControl_js__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ./includes/ListControl.js */ \"./src/includes/ListControl.js\");\n/* harmony import */ var _includes_PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ./includes/PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _includes_InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! ./includes/InnerPaddingControl.js */ \"./src/includes/InnerPaddingControl.js\");\n/* harmony import */ var _includes_RSSElement_js__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! ./includes/RSSElement.js */ \"./src/includes/RSSElement.js\");\n/* harmony import */ var _includes_RSSWidget_js__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! ./includes/RSSWidget.js */ \"./src/includes/RSSWidget.js\");\n/* harmony import */ var _includes_RSSControl_js__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(/*! ./includes/RSSControl.js */ \"./src/includes/RSSControl.js\");\n/* harmony import */ var _includes_FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(/*! ./includes/FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _includes_FontWeightControl_js__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(/*! ./includes/FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _includes_ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(/*! ./includes/ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _includes_RichTextControl_js__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(/*! ./includes/RichTextControl.js */ \"./src/includes/RichTextControl.js\");\n/* harmony import */ var _includes_BlockElement_js__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(/*! ./includes/BlockElement.js */ \"./src/includes/BlockElement.js\");\n/* harmony import */ var _includes_GridControl_js__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(/*! ./includes/GridControl.js */ \"./src/includes/GridControl.js\");\n/* harmony import */ var _includes_SettingsTabManager_js__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(/*! ./includes/SettingsTabManager.js */ \"./src/includes/SettingsTabManager.js\");\n/* harmony import */ var _includes_CheckboxControl_js__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(/*! ./includes/CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _includes_RadiosControl_js__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(/*! ./includes/RadiosControl.js */ \"./src/includes/RadiosControl.js\");\n/* harmony import */ var _includes_DropdownControl_js__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(/*! ./includes/DropdownControl.js */ \"./src/includes/DropdownControl.js\");\n/* harmony import */ var _includes_SocialIconsElement_js__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(/*! ./includes/SocialIconsElement.js */ \"./src/includes/SocialIconsElement.js\");\n/* harmony import */ var _includes_SocialIconsControl_js__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(/*! ./includes/SocialIconsControl.js */ \"./src/includes/SocialIconsControl.js\");\n/* harmony import */ var _includes_RangeControl_js__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(/*! ./includes/RangeControl.js */ \"./src/includes/RangeControl.js\");\n/* harmony import */ var _includes_SAlert_js__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(/*! ./includes/SAlert.js */ \"./src/includes/SAlert.js\");\n/* harmony import */ var _includes_BackgroundControl_js__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(/*! ./includes/BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _includes_ImageEffectControl_js__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(/*! ./includes/ImageEffectControl.js */ \"./src/includes/ImageEffectControl.js\");\n/* harmony import */ var _includes_LabelElement_js__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(/*! ./includes/LabelElement.js */ \"./src/includes/LabelElement.js\");\n/* harmony import */ var _includes_FontSizeControl_js__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(/*! ./includes/FontSizeControl.js */ \"./src/includes/FontSizeControl.js\");\n/* harmony import */ var _includes_NumberControl_js__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(/*! ./includes/NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _includes_TextColorControl_js__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(/*! ./includes/TextColorControl.js */ \"./src/includes/TextColorControl.js\");\n/* harmony import */ var _includes_LinkColorControl_js__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(/*! ./includes/LinkColorControl.js */ \"./src/includes/LinkColorControl.js\");\n/* harmony import */ var _includes_LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./includes/LinkConfigControl.js */ \"./src/includes/LinkConfigControl.js\");\n/* harmony import */ var _includes_ParagraphSpacingControl_js__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(/*! ./includes/ParagraphSpacingControl.js */ \"./src/includes/ParagraphSpacingControl.js\");\n/* harmony import */ var _includes_LineHeightControl_js__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(/*! ./includes/LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _includes_LetterSpacingControl_js__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(/*! ./includes/LetterSpacingControl.js */ \"./src/includes/LetterSpacingControl.js\");\n/* harmony import */ var _includes_TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(/*! ./includes/TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _includes_HTMLElement_js__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(/*! ./includes/HTMLElement.js */ \"./src/includes/HTMLElement.js\");\n/* harmony import */ var _includes_Formatter_js__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(/*! ./includes/Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _includes_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(/*! ./includes/BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\n/* harmony import */ var _includes_PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(/*! ./includes/PointerCaptureRegistry.js */ \"./src/includes/PointerCaptureRegistry.js\");\n/* harmony import */ var _includes_BJS_js__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(/*! ./includes/BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _includes_overlays_DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(/*! ./includes/overlays/DraggableHandleOverlay.js */ \"./src/includes/overlays/DraggableHandleOverlay.js\");\n/* harmony import */ var _includes_overlays_NativeDragHandleOverlay_js__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(/*! ./includes/overlays/NativeDragHandleOverlay.js */ \"./src/includes/overlays/NativeDragHandleOverlay.js\");\n/* harmony import */ var _includes_overlays_EdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(/*! ./includes/overlays/EdgeResizerOverlay.js */ \"./src/includes/overlays/EdgeResizerOverlay.js\");\n/* harmony import */ var _includes_overlays_FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(/*! ./includes/overlays/FloatingActionBarOverlay.js */ \"./src/includes/overlays/FloatingActionBarOverlay.js\");\n/* harmony import */ var _includes_overlays_StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(/*! ./includes/overlays/StructureVisualizerOverlay.js */ \"./src/includes/overlays/StructureVisualizerOverlay.js\");\n/* harmony import */ var _includes_overlays_InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(/*! ./includes/overlays/InlineEditorOverlay.js */ \"./src/includes/overlays/InlineEditorOverlay.js\");\n/* harmony import */ var _includes_overlays_ResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(/*! ./includes/overlays/ResizeCornerOverlay.js */ \"./src/includes/overlays/ResizeCornerOverlay.js\");\n/* harmony import */ var _includes_overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(/*! ./includes/overlays/PaddingVisualizerOverlay.js */ \"./src/includes/overlays/PaddingVisualizerOverlay.js\");\n/* harmony import */ var _includes_SelectElement_js__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(/*! ./includes/SelectElement.js */ \"./src/includes/SelectElement.js\");\n/* harmony import */ var _includes_SelectControl_js__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(/*! ./includes/SelectControl.js */ \"./src/includes/SelectControl.js\");\n/* harmony import */ var _includes_RadioElement_js__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(/*! ./includes/RadioElement.js */ \"./src/includes/RadioElement.js\");\n/* harmony import */ var _includes_CheckboxElement_js__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(/*! ./includes/CheckboxElement.js */ \"./src/includes/CheckboxElement.js\");\n/* harmony import */ var _includes_PricingCardsElement_js__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(/*! ./includes/PricingCardsElement.js */ \"./src/includes/PricingCardsElement.js\");\n/* harmony import */ var _includes_PricingCardElement_js__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(/*! ./includes/PricingCardElement.js */ \"./src/includes/PricingCardElement.js\");\n/* harmony import */ var _includes_StyleControl_js__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(/*! ./includes/StyleControl.js */ \"./src/includes/StyleControl.js\");\n/* harmony import */ var _includes_IconPickerControl_js__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(/*! ./includes/IconPickerControl.js */ \"./src/includes/IconPickerControl.js\");\n/* harmony import */ var _includes_YoutubeElement_js__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(/*! ./includes/YoutubeElement.js */ \"./src/includes/YoutubeElement.js\");\n/* harmony import */ var _includes_YoutubeWidget_js__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(/*! ./includes/YoutubeWidget.js */ \"./src/includes/YoutubeWidget.js\");\n/* harmony import */ var _includes_HorizonAlignmentControl_js__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(/*! ./includes/HorizonAlignmentControl.js */ \"./src/includes/HorizonAlignmentControl.js\");\n/* harmony import */ var _includes_CustomRangeControl_js__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(/*! ./includes/CustomRangeControl.js */ \"./src/includes/CustomRangeControl.js\");\n/* harmony import */ var _includes_BorderControl_js__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(/*! ./includes/BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _includes_BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_103__ = __webpack_require__(/*! ./includes/BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _includes_HeadingElement_js__WEBPACK_IMPORTED_MODULE_104__ = __webpack_require__(/*! ./includes/HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _includes_HeadingControl_js__WEBPACK_IMPORTED_MODULE_105__ = __webpack_require__(/*! ./includes/HeadingControl.js */ \"./src/includes/HeadingControl.js\");\n/* harmony import */ var _includes_SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_106__ = __webpack_require__(/*! ./includes/SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _includes_FormContainerCell_js__WEBPACK_IMPORTED_MODULE_107__ = __webpack_require__(/*! ./includes/FormContainerCell.js */ \"./src/includes/FormContainerCell.js\");\n/* harmony import */ var _includes_FieldElement_js__WEBPACK_IMPORTED_MODULE_108__ = __webpack_require__(/*! ./includes/FieldElement.js */ \"./src/includes/FieldElement.js\");\n/* harmony import */ var _includes_FieldConfigControl_js__WEBPACK_IMPORTED_MODULE_109__ = __webpack_require__(/*! ./includes/FieldConfigControl.js */ \"./src/includes/FieldConfigControl.js\");\n/* harmony import */ var _includes_SubmitButtonElement_js__WEBPACK_IMPORTED_MODULE_110__ = __webpack_require__(/*! ./includes/SubmitButtonElement.js */ \"./src/includes/SubmitButtonElement.js\");\n/* harmony import */ var _includes_TermsConfigControl_js__WEBPACK_IMPORTED_MODULE_111__ = __webpack_require__(/*! ./includes/TermsConfigControl.js */ \"./src/includes/TermsConfigControl.js\");\n/* harmony import */ var _includes_TermsOfServiceElement_js__WEBPACK_IMPORTED_MODULE_112__ = __webpack_require__(/*! ./includes/TermsOfServiceElement.js */ \"./src/includes/TermsOfServiceElement.js\");\n/* harmony import */ var _includes_TermsOfServiceWidget_js__WEBPACK_IMPORTED_MODULE_113__ = __webpack_require__(/*! ./includes/TermsOfServiceWidget.js */ \"./src/includes/TermsOfServiceWidget.js\");\n/* harmony import */ var _includes_CheckoutElement_js__WEBPACK_IMPORTED_MODULE_114__ = __webpack_require__(/*! ./includes/CheckoutElement.js */ \"./src/includes/CheckoutElement.js\");\n/* harmony import */ var _includes_CheckoutControl_js__WEBPACK_IMPORTED_MODULE_115__ = __webpack_require__(/*! ./includes/CheckoutControl.js */ \"./src/includes/CheckoutControl.js\");\n/* harmony import */ var _includes_CheckoutWidget_js__WEBPACK_IMPORTED_MODULE_116__ = __webpack_require__(/*! ./includes/CheckoutWidget.js */ \"./src/includes/CheckoutWidget.js\");\n/* harmony import */ var _includes_CheckoutSimpleElement_js__WEBPACK_IMPORTED_MODULE_117__ = __webpack_require__(/*! ./includes/CheckoutSimpleElement.js */ \"./src/includes/CheckoutSimpleElement.js\");\n/* harmony import */ var _includes_CheckoutSimpleControl_js__WEBPACK_IMPORTED_MODULE_118__ = __webpack_require__(/*! ./includes/CheckoutSimpleControl.js */ \"./src/includes/CheckoutSimpleControl.js\");\n/* harmony import */ var _includes_CheckoutSimpleWidget_js__WEBPACK_IMPORTED_MODULE_119__ = __webpack_require__(/*! ./includes/CheckoutSimpleWidget.js */ \"./src/includes/CheckoutSimpleWidget.js\");\n/* harmony import */ var _includes_DividerStyleControl_js__WEBPACK_IMPORTED_MODULE_120__ = __webpack_require__(/*! ./includes/DividerStyleControl.js */ \"./src/includes/DividerStyleControl.js\");\n/* harmony import */ var _includes_DividerElement_js__WEBPACK_IMPORTED_MODULE_121__ = __webpack_require__(/*! ./includes/DividerElement.js */ \"./src/includes/DividerElement.js\");\n/* harmony import */ var _includes_DividerWidget_js__WEBPACK_IMPORTED_MODULE_122__ = __webpack_require__(/*! ./includes/DividerWidget.js */ \"./src/includes/DividerWidget.js\");\n/* harmony import */ var _includes_AlignControl_js__WEBPACK_IMPORTED_MODULE_123__ = __webpack_require__(/*! ./includes/AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _includes_ImageTextLeftWidget_js__WEBPACK_IMPORTED_MODULE_124__ = __webpack_require__(/*! ./includes/ImageTextLeftWidget.js */ \"./src/includes/ImageTextLeftWidget.js\");\n/* harmony import */ var _includes_ImageTextRightWidget_js__WEBPACK_IMPORTED_MODULE_125__ = __webpack_require__(/*! ./includes/ImageTextRightWidget.js */ \"./src/includes/ImageTextRightWidget.js\");\n/* harmony import */ var _includes_ImageTextTopWidget_js__WEBPACK_IMPORTED_MODULE_126__ = __webpack_require__(/*! ./includes/ImageTextTopWidget.js */ \"./src/includes/ImageTextTopWidget.js\");\n/* harmony import */ var _includes_ImageTextBottomWidget_js__WEBPACK_IMPORTED_MODULE_127__ = __webpack_require__(/*! ./includes/ImageTextBottomWidget.js */ \"./src/includes/ImageTextBottomWidget.js\");\n/* harmony import */ var _includes_ImageTextDoubleWidget_js__WEBPACK_IMPORTED_MODULE_128__ = __webpack_require__(/*! ./includes/ImageTextDoubleWidget.js */ \"./src/includes/ImageTextDoubleWidget.js\");\n/* harmony import */ var _includes_TextCenterWidget_js__WEBPACK_IMPORTED_MODULE_129__ = __webpack_require__(/*! ./includes/TextCenterWidget.js */ \"./src/includes/TextCenterWidget.js\");\n/* harmony import */ var _includes_TextLeftWidget_js__WEBPACK_IMPORTED_MODULE_130__ = __webpack_require__(/*! ./includes/TextLeftWidget.js */ \"./src/includes/TextLeftWidget.js\");\n/* harmony import */ var _includes_TextDoubleWidget_js__WEBPACK_IMPORTED_MODULE_131__ = __webpack_require__(/*! ./includes/TextDoubleWidget.js */ \"./src/includes/TextDoubleWidget.js\");\n/* harmony import */ var _includes_ads_AdHeadlineWidget_js__WEBPACK_IMPORTED_MODULE_132__ = __webpack_require__(/*! ./includes/ads/AdHeadlineWidget.js */ \"./src/includes/ads/AdHeadlineWidget.js\");\n/* harmony import */ var _includes_ads_AdPrimaryTextWidget_js__WEBPACK_IMPORTED_MODULE_133__ = __webpack_require__(/*! ./includes/ads/AdPrimaryTextWidget.js */ \"./src/includes/ads/AdPrimaryTextWidget.js\");\n/* harmony import */ var _includes_ads_AdDescriptionWidget_js__WEBPACK_IMPORTED_MODULE_134__ = __webpack_require__(/*! ./includes/ads/AdDescriptionWidget.js */ \"./src/includes/ads/AdDescriptionWidget.js\");\n/* harmony import */ var _includes_ads_AdCTAWidget_js__WEBPACK_IMPORTED_MODULE_135__ = __webpack_require__(/*! ./includes/ads/AdCTAWidget.js */ \"./src/includes/ads/AdCTAWidget.js\");\n/* harmony import */ var _includes_ads_AdImageSlotWidget_js__WEBPACK_IMPORTED_MODULE_136__ = __webpack_require__(/*! ./includes/ads/AdImageSlotWidget.js */ \"./src/includes/ads/AdImageSlotWidget.js\");\n/* harmony import */ var _includes_ads_AdLogoSlotWidget_js__WEBPACK_IMPORTED_MODULE_137__ = __webpack_require__(/*! ./includes/ads/AdLogoSlotWidget.js */ \"./src/includes/ads/AdLogoSlotWidget.js\");\n/* harmony import */ var _includes_ads_AdCarouselCardWidget_js__WEBPACK_IMPORTED_MODULE_138__ = __webpack_require__(/*! ./includes/ads/AdCarouselCardWidget.js */ \"./src/includes/ads/AdCarouselCardWidget.js\");\n/* harmony import */ var ejs_browser__WEBPACK_IMPORTED_MODULE_139__ = __webpack_require__(/*! ejs-browser */ \"./node_modules/ejs-browser/lib/ejs.js\");\n/* harmony import */ var ejs_browser__WEBPACK_IMPORTED_MODULE_139___default = /*#__PURE__*/__webpack_require__.n(ejs_browser__WEBPACK_IMPORTED_MODULE_139__);\n\n\n\n\n\n\n\n\nwindow.BuilderjsPopup = _includes_BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"];\n// Pure static utility; exposed globally so the demo page showcase can\n// visualise its decisions without spinning up a full Builder instance.\n// PLAN_EFFECT W0.3.\nwindow.ToolbarPositioner = _includes_ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"];\n// TEXT_INLINE_PLAN W0.5 — inline whitelist primitive. Stateless class\n// with three entry points (sanitize / normalize / emit). Exposed\n// globally so the showcase paste-playground + future W1-W6 toolbar\n// consumers can reach it without a Builder instance.\nwindow.InlineSanitizer = _includes_InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"];\n// TEXT_INLINE_PLAN W1.1 — floating inline text formatting toolbar. Class\n// exposed globally so host apps can invoke `builder._textInlineToolbar.*`\n// for test introspection; the instance itself is lifecycle-managed by\n// Builder._textInlineToolbarInit() and never user-instantiated.\nwindow.TextInlineToolbarOverlay = _includes_overlays_TextInlineToolbarOverlay_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"];\n// TEXT_INLINE_PLAN W2.1 — sectioned dropdown menu primitive with full\n// keyboard nav + ARIA + submenu. Standalone — the showcase demo pages\n// and future kebab menus instantiate it directly. Backs W2.2 (clipboard)\n// + W2.3 (paragraph / case / insert / semantic submenus).\nwindow.RichDropdownMenuOverlay = _includes_overlays_RichDropdownMenuOverlay_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"];\n// TEXT_INLINE_PLAN W5.2 — selection save/restore helper. Exposed globally\n// so future popover consumers outside the core bundle can wrap their\n// apply handlers + so test harnesses can probe save/restore/run\n// behaviour without a mount-point dependency.\nwindow.SelectionGuard = _includes_TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_7__.SelectionGuard;\n// TEXT_INLINE_PLAN W4.3 — link config composite (type-first URL +\n// target + rel chips + title + aria-label + download + UTM builder).\n// Shared by LinkElement + ButtonElement + W1.3 inline link popover;\n// exposed on window so test harnesses + future consumers can mount\n// standalone without reaching into the Builder graph.\nwindow.LinkConfigControl = _includes_LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"];\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nwindow.Formatter = _includes_Formatter_js__WEBPACK_IMPORTED_MODULE_78__[\"default\"];\nwindow.I18n = _includes_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"];\n\n// ─────────────────────────────────────────────────────────────────\n// Canvas Overlay system\n// See docs/core/OVERLAY.md for design spec.\n// See docs/archived/OVERLAY_PLAN.md for phased rollout.\n// CSS lives in src/builder.css (appended — webpack has no JS→CSS\n// module loader; builder.css is copied whole via CopyWebpackPlugin).\n// ─────────────────────────────────────────────────────────────────\n// Phase 1.1 — foundation\n\n\nwindow.BaseOverlay = _includes_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_79__[\"default\"];\nwindow.PointerCaptureRegistry = _includes_PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_80__[\"default\"];\n\n// Phase 1.9 — framework debug namespace. Eager import so\n// `window.__bjsDebug = true` in DevTools immediately enables BJS.log tracing.\n\nwindow.BJS = _includes_BJS_js__WEBPACK_IMPORTED_MODULE_81__[\"default\"];\n\n// Phase 1.2 — 7 primitive base classes. No element consumes them yet;\n// Phase 1.3+ subclasses them for Grid / Image / Cell / Block affordances.\n\n\n\n\n\n\n\n\nwindow.DraggableHandleOverlay = _includes_overlays_DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_82__[\"default\"];\nwindow.NativeDragHandleOverlay = _includes_overlays_NativeDragHandleOverlay_js__WEBPACK_IMPORTED_MODULE_83__[\"default\"];\nwindow.EdgeResizerOverlay = _includes_overlays_EdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_84__[\"default\"];\nwindow.FloatingActionBarOverlay = _includes_overlays_FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_85__[\"default\"];\nwindow.StructureVisualizerOverlay = _includes_overlays_StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_86__[\"default\"];\nwindow.InlineEditorOverlay = _includes_overlays_InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_87__[\"default\"];\nwindow.ResizeCornerOverlay = _includes_overlays_ResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_88__[\"default\"];\nwindow.PaddingVisualizerOverlay = _includes_overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_89__[\"default\"];\n\n// Phase 1.3 — Grid element overlays (GridStructureOverlay + GridColumnResizeOverlay)\n// are imported INSIDE GridElement.js itself; no separate window exposure needed\n// since they're element-specific and instantiated via GridElement.getOverlays().\n\n//*temporal elements\n\n\n\n\n\n\n\n\n\n\n\n\n// temporal elements*\n\n\n\n\n\n\n\nwindow.SectionLabelControl = _includes_SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_106__[\"default\"];\n\n//\n\nwindow.FormContainerCell = _includes_FormContainerCell_js__WEBPACK_IMPORTED_MODULE_107__[\"default\"];\n\nwindow.FieldElement = _includes_FieldElement_js__WEBPACK_IMPORTED_MODULE_108__[\"default\"];\n\nwindow.FieldConfigControl = _includes_FieldConfigControl_js__WEBPACK_IMPORTED_MODULE_109__[\"default\"];\n\nwindow.SubmitButtonElement = _includes_SubmitButtonElement_js__WEBPACK_IMPORTED_MODULE_110__[\"default\"];\n\nwindow.TermsConfigControl = _includes_TermsConfigControl_js__WEBPACK_IMPORTED_MODULE_111__[\"default\"];\n\nwindow.TermsOfServiceElement = _includes_TermsOfServiceElement_js__WEBPACK_IMPORTED_MODULE_112__[\"default\"];\n\nwindow.TermsOfServiceWidget = _includes_TermsOfServiceWidget_js__WEBPACK_IMPORTED_MODULE_113__[\"default\"];\n\nwindow.CheckoutElement = _includes_CheckoutElement_js__WEBPACK_IMPORTED_MODULE_114__[\"default\"];\n\nwindow.CheckoutControl = _includes_CheckoutControl_js__WEBPACK_IMPORTED_MODULE_115__[\"default\"];\n\nwindow.CheckoutWidget = _includes_CheckoutWidget_js__WEBPACK_IMPORTED_MODULE_116__[\"default\"];\n\nwindow.CheckoutSimpleElement = _includes_CheckoutSimpleElement_js__WEBPACK_IMPORTED_MODULE_117__[\"default\"];\n\nwindow.CheckoutSimpleControl = _includes_CheckoutSimpleControl_js__WEBPACK_IMPORTED_MODULE_118__[\"default\"];\n\nwindow.CheckoutSimpleWidget = _includes_CheckoutSimpleWidget_js__WEBPACK_IMPORTED_MODULE_119__[\"default\"];\n\n//\n\nwindow.DividerStyleControl = _includes_DividerStyleControl_js__WEBPACK_IMPORTED_MODULE_120__[\"default\"];\n\nwindow.DividerElement = _includes_DividerElement_js__WEBPACK_IMPORTED_MODULE_121__[\"default\"];\n\nwindow.DividerWidget = _includes_DividerWidget_js__WEBPACK_IMPORTED_MODULE_122__[\"default\"];\n\nwindow.AlignControl = _includes_AlignControl_js__WEBPACK_IMPORTED_MODULE_123__[\"default\"];\n\n//\n\nwindow.ImageTextLeftWidget = _includes_ImageTextLeftWidget_js__WEBPACK_IMPORTED_MODULE_124__[\"default\"];\n\nwindow.ImageTextRightWidget = _includes_ImageTextRightWidget_js__WEBPACK_IMPORTED_MODULE_125__[\"default\"];\n\nwindow.ImageTextTopWidget = _includes_ImageTextTopWidget_js__WEBPACK_IMPORTED_MODULE_126__[\"default\"];\n\nwindow.ImageTextBottomWidget = _includes_ImageTextBottomWidget_js__WEBPACK_IMPORTED_MODULE_127__[\"default\"];\n\nwindow.ImageTextDoubleWidget = _includes_ImageTextDoubleWidget_js__WEBPACK_IMPORTED_MODULE_128__[\"default\"];\n\nwindow.TextCenterWidget = _includes_TextCenterWidget_js__WEBPACK_IMPORTED_MODULE_129__[\"default\"];\n\nwindow.TextLeftWidget = _includes_TextLeftWidget_js__WEBPACK_IMPORTED_MODULE_130__[\"default\"];\n\nwindow.TextDoubleWidget = _includes_TextDoubleWidget_js__WEBPACK_IMPORTED_MODULE_131__[\"default\"];\n\n// ─────────────────────────────────────────────────────────────────\n// Ads widgets — drag-drop building blocks for paid ad creative\n// (Meta / Google / TikTok / LinkedIn). All use existing core\n// elements under the hood; no new Element classes, no registry\n// changes. Consumer (host app) registers these in the ads-mode\n// builder via `builder.widgetsBox.addWidget(new AdXxxWidget(), ...)`.\n// See docs/BUILDER.md → \"Ads mode\" section for the full design.\n// ─────────────────────────────────────────────────────────────────\n\nwindow.AdHeadlineWidget = _includes_ads_AdHeadlineWidget_js__WEBPACK_IMPORTED_MODULE_132__[\"default\"];\n\nwindow.AdPrimaryTextWidget = _includes_ads_AdPrimaryTextWidget_js__WEBPACK_IMPORTED_MODULE_133__[\"default\"];\n\nwindow.AdDescriptionWidget = _includes_ads_AdDescriptionWidget_js__WEBPACK_IMPORTED_MODULE_134__[\"default\"];\n\nwindow.AdCTAWidget = _includes_ads_AdCTAWidget_js__WEBPACK_IMPORTED_MODULE_135__[\"default\"];\n\nwindow.AdImageSlotWidget = _includes_ads_AdImageSlotWidget_js__WEBPACK_IMPORTED_MODULE_136__[\"default\"];\n\nwindow.AdLogoSlotWidget = _includes_ads_AdLogoSlotWidget_js__WEBPACK_IMPORTED_MODULE_137__[\"default\"];\n\nwindow.AdCarouselCardWidget = _includes_ads_AdCarouselCardWidget_js__WEBPACK_IMPORTED_MODULE_138__[\"default\"];\n\n// Attach all classes to the global `window` object\nwindow.Builder = _includes_Builder_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"];\nwindow.WidgetsBox = _includes_WidgetsBox_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"];\nwindow.HeadingWidget = _includes_HeadingWidget_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"];\nwindow.ParagraphWidget = _includes_ParagraphWidget_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"];\nwindow.WelcomeWidget = _includes_WelcomeWidget_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"];\nwindow.MenuWidget = _includes_MenuWidget_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"];\nwindow.ListWidget = _includes_ListWidget_js__WEBPACK_IMPORTED_MODULE_14__[\"default\"];\nwindow.ListElement = _includes_ListElement_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"];\nwindow.ImageWidget = _includes_ImageWidget_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"];\nwindow.GridWidget = _includes_GridWidget_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"];\nwindow.SelectWidget = _includes_SelectWidget_js__WEBPACK_IMPORTED_MODULE_18__[\"default\"];\nwindow.RadioWidget = _includes_RadioWidget_js__WEBPACK_IMPORTED_MODULE_19__[\"default\"];\nwindow.CheckboxWidget = _includes_CheckboxWidget_js__WEBPACK_IMPORTED_MODULE_20__[\"default\"];\nwindow.PricingCardsWidget = _includes_PricingCardsWidget_js__WEBPACK_IMPORTED_MODULE_21__[\"default\"];\nwindow.H1Element = _includes_H1Element_js__WEBPACK_IMPORTED_MODULE_22__[\"default\"];\nwindow.PElement = _includes_PElement_js__WEBPACK_IMPORTED_MODULE_23__[\"default\"];\nwindow.MenuElement = _includes_MenuElement_js__WEBPACK_IMPORTED_MODULE_24__[\"default\"];\nwindow.GridElement = _includes_GridElement_js__WEBPACK_IMPORTED_MODULE_25__[\"default\"];\nwindow.CellElement = _includes_CellElement_js__WEBPACK_IMPORTED_MODULE_26__[\"default\"];\nwindow.ButtonElement = _includes_ButtonElement_js__WEBPACK_IMPORTED_MODULE_27__[\"default\"];\nwindow.ButtonWidget = _includes_ButtonWidget_js__WEBPACK_IMPORTED_MODULE_28__[\"default\"];\nwindow.VideoElement = _includes_VideoElement_js__WEBPACK_IMPORTED_MODULE_29__[\"default\"];\nwindow.VideoWidget = _includes_VideoWidget_js__WEBPACK_IMPORTED_MODULE_30__[\"default\"];\nwindow.AlertElement = _includes_AlertElement_js__WEBPACK_IMPORTED_MODULE_31__[\"default\"];\nwindow.AlertWidget = _includes_AlertWidget_js__WEBPACK_IMPORTED_MODULE_32__[\"default\"];\nwindow.TabsManager = _includes_TabsManager_js__WEBPACK_IMPORTED_MODULE_33__[\"default\"];\nwindow.UIManager = _includes_UIManager_js__WEBPACK_IMPORTED_MODULE_34__[\"default\"];\nwindow.BaseElement = _includes_BaseElement_js__WEBPACK_IMPORTED_MODULE_35__[\"default\"];\nwindow.TextControl = _includes_TextControl_js__WEBPACK_IMPORTED_MODULE_36__[\"default\"];\nwindow.ImageElement = _includes_ImageElement_js__WEBPACK_IMPORTED_MODULE_37__[\"default\"];\nwindow.BaseWidget = _includes_BaseWidget_js__WEBPACK_IMPORTED_MODULE_38__[\"default\"];\nwindow.ElementFactory = _includes_ElementFactory_js__WEBPACK_IMPORTED_MODULE_39__[\"default\"];\nwindow.LinkElement = _includes_LinkElement_js__WEBPACK_IMPORTED_MODULE_40__[\"default\"];\nwindow.H2Element = _includes_H2Element_js__WEBPACK_IMPORTED_MODULE_41__[\"default\"];\nwindow.H3Element = _includes_H3Element_js__WEBPACK_IMPORTED_MODULE_42__[\"default\"];\nwindow.H4Element = _includes_H4Element_js__WEBPACK_IMPORTED_MODULE_43__[\"default\"];\nwindow.H5Element = _includes_H5Element_js__WEBPACK_IMPORTED_MODULE_44__[\"default\"];\nwindow.TextInputElement = _includes_TextInputElement_js__WEBPACK_IMPORTED_MODULE_45__[\"default\"];\nwindow.ListControl = _includes_ListControl_js__WEBPACK_IMPORTED_MODULE_46__[\"default\"];\nwindow.PaddingMarginControl = _includes_PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_47__[\"default\"];\nwindow.InnerPaddingControl = _includes_InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_48__[\"default\"];\nwindow.RSSElement = _includes_RSSElement_js__WEBPACK_IMPORTED_MODULE_49__[\"default\"];\nwindow.RSSWidget = _includes_RSSWidget_js__WEBPACK_IMPORTED_MODULE_50__[\"default\"];\nwindow.RSSControl = _includes_RSSControl_js__WEBPACK_IMPORTED_MODULE_51__[\"default\"];\nwindow.FontFamilyControl = _includes_FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_52__[\"default\"];\nwindow.FontWeightControl = _includes_FontWeightControl_js__WEBPACK_IMPORTED_MODULE_53__[\"default\"];\nwindow.ColorPickerControl = _includes_ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_54__[\"default\"];\nwindow.RichTextControl = _includes_RichTextControl_js__WEBPACK_IMPORTED_MODULE_55__[\"default\"];\nwindow.BlockElement = _includes_BlockElement_js__WEBPACK_IMPORTED_MODULE_56__[\"default\"];\nwindow.GridControl = _includes_GridControl_js__WEBPACK_IMPORTED_MODULE_57__[\"default\"];\nwindow.SettingsTabManager = _includes_SettingsTabManager_js__WEBPACK_IMPORTED_MODULE_58__[\"default\"];\nwindow.CheckboxControl = _includes_CheckboxControl_js__WEBPACK_IMPORTED_MODULE_59__[\"default\"];\nwindow.RadiosControl = _includes_RadiosControl_js__WEBPACK_IMPORTED_MODULE_60__[\"default\"];\nwindow.DropdownControl = _includes_DropdownControl_js__WEBPACK_IMPORTED_MODULE_61__[\"default\"];\nwindow.SocialIconsElement = _includes_SocialIconsElement_js__WEBPACK_IMPORTED_MODULE_62__[\"default\"];\nwindow.SocialIconsControl = _includes_SocialIconsControl_js__WEBPACK_IMPORTED_MODULE_63__[\"default\"];\nwindow.RangeControl = _includes_RangeControl_js__WEBPACK_IMPORTED_MODULE_64__[\"default\"];\nwindow.SAlert = _includes_SAlert_js__WEBPACK_IMPORTED_MODULE_65__[\"default\"];\nwindow.BackgroundControl = _includes_BackgroundControl_js__WEBPACK_IMPORTED_MODULE_66__[\"default\"];\nwindow.ImageEffectControl = _includes_ImageEffectControl_js__WEBPACK_IMPORTED_MODULE_67__[\"default\"];\nwindow.LabelElement = _includes_LabelElement_js__WEBPACK_IMPORTED_MODULE_68__[\"default\"];\nwindow.YoutubeElement = _includes_YoutubeElement_js__WEBPACK_IMPORTED_MODULE_98__[\"default\"];\nwindow.YoutubeWidget = _includes_YoutubeWidget_js__WEBPACK_IMPORTED_MODULE_99__[\"default\"];\nwindow.FontSizeControl = _includes_FontSizeControl_js__WEBPACK_IMPORTED_MODULE_69__[\"default\"];\nwindow.NumberControl = _includes_NumberControl_js__WEBPACK_IMPORTED_MODULE_70__[\"default\"];\nwindow.TextColorControl = _includes_TextColorControl_js__WEBPACK_IMPORTED_MODULE_71__[\"default\"];\nwindow.LinkColorControl = _includes_LinkColorControl_js__WEBPACK_IMPORTED_MODULE_72__[\"default\"];\nwindow.LinkConfigControl = _includes_LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"];\nwindow.ParagraphSpacingControl = _includes_ParagraphSpacingControl_js__WEBPACK_IMPORTED_MODULE_73__[\"default\"];\nwindow.LineHeightControl = _includes_LineHeightControl_js__WEBPACK_IMPORTED_MODULE_74__[\"default\"];\nwindow.LetterSpacingControl = _includes_LetterSpacingControl_js__WEBPACK_IMPORTED_MODULE_75__[\"default\"];\nwindow.TextDirectionControl = _includes_TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_76__[\"default\"];\nwindow.HTMLElement = _includes_HTMLElement_js__WEBPACK_IMPORTED_MODULE_77__[\"default\"];\nwindow.HorizonAlignmentControl = _includes_HorizonAlignmentControl_js__WEBPACK_IMPORTED_MODULE_100__[\"default\"];\n\n//*temporal elements\nwindow.SelectElement = _includes_SelectElement_js__WEBPACK_IMPORTED_MODULE_90__[\"default\"];\nwindow.SelectControl = _includes_SelectControl_js__WEBPACK_IMPORTED_MODULE_91__[\"default\"];\nwindow.RadioElement = _includes_RadioElement_js__WEBPACK_IMPORTED_MODULE_92__[\"default\"];\nwindow.CheckboxElement = _includes_CheckboxElement_js__WEBPACK_IMPORTED_MODULE_93__[\"default\"];\nwindow.PricingCardsElement = _includes_PricingCardsElement_js__WEBPACK_IMPORTED_MODULE_94__[\"default\"];\nwindow.PricingCardElement = _includes_PricingCardElement_js__WEBPACK_IMPORTED_MODULE_95__[\"default\"];\nwindow.StyleControl = _includes_StyleControl_js__WEBPACK_IMPORTED_MODULE_96__[\"default\"];\nwindow.IconPickerControl = _includes_IconPickerControl_js__WEBPACK_IMPORTED_MODULE_97__[\"default\"];\n// temporal elements*\n\nwindow.CustomRangeControl = _includes_CustomRangeControl_js__WEBPACK_IMPORTED_MODULE_101__[\"default\"];\nwindow.BorderControl = _includes_BorderControl_js__WEBPACK_IMPORTED_MODULE_102__[\"default\"];\nwindow.BorderRadiusControl = _includes_BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_103__[\"default\"];\nwindow.HeadingControl = _includes_HeadingControl_js__WEBPACK_IMPORTED_MODULE_105__[\"default\"];\nwindow.HeadingElement = _includes_HeadingElement_js__WEBPACK_IMPORTED_MODULE_104__[\"default\"];\n\nwindow.ejs = (ejs_browser__WEBPACK_IMPORTED_MODULE_139___default());\n\n//# sourceURL=webpack://BuilderBundle/./src/builder.js?");
/***/ }),
/***/ "./src/includes/ActionButtonControl.js":
/*!*********************************************!*\
!*** ./src/includes/ActionButtonControl.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\n/**\n * ActionButtonControl — single-click action row for settings panels.\n *\n * Renders a labelled button + optional one-line hint. Used for \"reset to\n * defaults\", \"clean up\", \"duplicate\" style actions — anything that's not a\n * value edit but a discrete user action.\n *\n * Styling piggybacks on `.bjs-info-banner` (tinted surface) + a native\n * button inside. Keeps the panel visually consistent with InfoBannerControl.\n *\n * Usage:\n * new ActionButtonControl({\n * label: 'Reset this card',\n * hint: 'Re-applies the current style defaults to every element.',\n * buttonText: 'Reset',\n * variant: 'danger' | 'default', // default = subtle\n * onClick: () => cell.applyStylePreset(),\n * })\n */\nvar ActionButtonControl = /*#__PURE__*/_createClass(function ActionButtonControl() {\n var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},\n _ref$label = _ref.label,\n label = _ref$label === void 0 ? '' : _ref$label,\n _ref$hint = _ref.hint,\n hint = _ref$hint === void 0 ? '' : _ref$hint,\n _ref$buttonText = _ref.buttonText,\n buttonText = _ref$buttonText === void 0 ? 'Run' : _ref$buttonText,\n _ref$variant = _ref.variant,\n variant = _ref$variant === void 0 ? 'default' : _ref$variant,\n _ref$onClick = _ref.onClick,\n onClick = _ref$onClick === void 0 ? function () {} : _ref$onClick;\n _classCallCheck(this, ActionButtonControl);\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-action-row');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-action-row-body\\\">\\n <div class=\\\"bjs-action-row-label\\\">\".concat(label, \"</div>\\n \").concat(hint ? \"<div class=\\\"bjs-action-row-hint\\\">\".concat(hint, \"</div>\") : '', \"\\n </div>\\n <button type=\\\"button\\\"\\n class=\\\"bjs-action-row-btn \").concat(variant === 'danger' ? 'is-danger' : '', \"\\\">\\n \").concat(buttonText, \"\\n </button>\\n \");\n var btn = this.domNode.querySelector('.bjs-action-row-btn');\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n try {\n onClick();\n } catch (err) {\n console.error('[ActionButtonControl]', err);\n }\n });\n});\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ActionButtonControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ActionButtonControl.js?");
/***/ }),
/***/ "./src/includes/AlertElement.js":
/*!**************************************!*\
!*** ./src/includes/AlertElement.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar AlertElement = /*#__PURE__*/function (_BaseElement) {\n function AlertElement(template) {\n var _this;\n var text = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'This is an alert!';\n _classCallCheck(this, AlertElement);\n _this = _callSuper(this, AlertElement); // Call the parent class constructor\n _this.template = template;\n _this.text = text;\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['text'];\n\n // Formatter - Bootstrap alert component default styles\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"]({\n // text styles\n font_family: \"inherit\",\n font_weight: \"400\",\n font_size: \"16px\",\n text_color: \"#084298\",\n link_color: \"#06357a\",\n paragraph_spacing: \"0\",\n text_align: 'left',\n // left, center, right,\n line_height: \"1.5\",\n letter_spacing: null,\n text_direction: \"ltr\",\n // ltr, rtl\n\n // background - Bootstrap alert-primary background\n background_color: \"#cff4fc\",\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n // spacing - Bootstrap alert padding\n padding_top: \"0.75rem\",\n padding_right: \"1.25rem\",\n padding_bottom: \"0.75rem\",\n padding_left: \"1.25rem\",\n // border - Bootstrap alert border (subtle)\n border_top_style: \"solid\",\n border_top_width: \"1px\",\n border_top_color: \"#b6effb\",\n border_right_style: \"solid\",\n border_right_width: \"1px\",\n border_right_color: \"#b6effb\",\n border_bottom_style: \"solid\",\n border_bottom_width: \"1px\",\n border_bottom_color: \"#b6effb\",\n border_left_width: \"1px\",\n border_left_style: \"solid\",\n border_left_color: \"#b6effb\",\n // border radius - Bootstrap alert radius\n border_radius: \"0.375rem\"\n });\n\n // Inline edit\n // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n _this.registerInlineEdit('text');\n return _this;\n }\n _inherits(AlertElement, _BaseElement);\n return _createClass(AlertElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.alert');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter + text auto-merged (W0.2c); inline-edit auto-wires (W0.2b)\n this.domNode.innerHTML = this.renderTemplate({});\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(AlertElement, \"getData\", this, 3)([])), {}, {\n text: this.text\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this,\n _this$host;\n // W3.1 — bus wiring for dual-view sync with FontPopoverOverlay.\n var busOpts = function busOpts(key) {\n var _this2$host;\n return {\n bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n elementUid: _this2.id,\n formatterKey: key\n };\n };\n return [\n // TEXT_INLINE_PLAN W8 (2026-04-24) — RichTextControl retired.\n // Canvas inline-edit = text surface; sidebar = config panel only.\n new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('font_family', value);\n _this2.render();\n }\n }, busOpts('font_family')), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('font_weight', value);\n _this2.render();\n }\n }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('font_size', value);\n _this2.render();\n }\n }, _objectSpread({\n defaultValue: 16,\n minValue: 8,\n maxValue: 72,\n suffix: 'px',\n allowZero: false\n }, busOpts('font_size'))), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('text_color', value);\n _this2.render();\n }\n }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('link_color', value);\n _this2.render();\n }\n }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_alignment'), this.formatter.getFormat('text_align'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('text_align', value);\n _this2.render();\n }\n }, ['left', 'justify', 'center', 'right'], {\n bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n elementUid: this.id,\n formatterKey: 'text_align'\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('paragraph_spacing', value);\n _this2.render();\n }\n }, {\n defaultValue: 0,\n minValue: 0,\n maxValue: 50,\n suffix: 'px',\n allowZero: true\n }), new _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('line_height', value);\n _this2.render();\n }\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('letter_spacing', value);\n _this2.render();\n }\n }, {\n defaultValue: 0,\n minValue: -5,\n maxValue: 10,\n step: 0.1,\n suffix: 'px',\n allowZero: true,\n allowNegative: true\n }), new _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('text_direction', value);\n _this2.render();\n }\n }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n color: this.formatter.getFormat('background_color'),\n image: this.formatter.getFormat('background_image'),\n position: this.formatter.getFormat('background_position'),\n size: this.formatter.getFormat('background_size'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n }, {\n setBackground: function setBackground(values) {\n _this2.formatter.setFormat('background_color', values.color);\n _this2.formatter.setFormat('background_image', values.image);\n _this2.formatter.setFormat('background_position', values.position);\n _this2.formatter.setFormat('background_size', values.size);\n _this2.formatter.setFormat('background_repeat', values.repeat);\n _this2.render();\n }\n }, {\n features: ['color', 'image', 'size', 'repeat', 'gradient']\n }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style'),\n border_top_width: this.formatter.getFormat('border_top_width'),\n border_top_color: this.formatter.getFormat('border_top_color'),\n border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n border_left_style: this.formatter.getFormat('border_left_style'),\n border_left_width: this.formatter.getFormat('border_left_width'),\n border_left_color: this.formatter.getFormat('border_left_color'),\n border_right_style: this.formatter.getFormat('border_right_style'),\n border_right_width: this.formatter.getFormat('border_right_width'),\n border_right_color: this.formatter.getFormat('border_right_color')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this2.formatter.setFormat('border_top_style', border_top_style);\n _this2.formatter.setFormat('border_top_width', border_top_width);\n _this2.formatter.setFormat('border_top_color', border_top_color);\n _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this2.formatter.setFormat('border_left_style', border_left_style);\n _this2.formatter.setFormat('border_left_width', border_left_width);\n _this2.formatter.setFormat('border_left_color', border_left_color);\n _this2.formatter.setFormat('border_right_style', border_right_style);\n _this2.formatter.setFormat('border_right_width', border_right_width);\n _this2.formatter.setFormat('border_right_color', border_right_color);\n\n // re-render\n _this2.render();\n }\n }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n setRadius: function setRadius(v) {\n _this2.formatter.setFormat('border_radius', v);\n _this2.render();\n }\n }),\n // W3.8b — InnerPaddingControl (intrinsic shape).\n new InnerPaddingControl(\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alert_padding'),\n // value\n {\n top: this.formatter.getFormat('padding_top'),\n right: this.formatter.getFormat('padding_right'),\n bottom: this.formatter.getFormat('padding_bottom'),\n left: this.formatter.getFormat('padding_left')\n },\n // callback\n {\n setValues: function setValues(values) {\n _this2.formatter.setFormat('padding_top', values.top);\n _this2.formatter.setFormat('padding_right', values.right);\n _this2.formatter.setFormat('padding_bottom', values.bottom);\n _this2.formatter.setFormat('padding_left', values.left);\n _this2.render();\n }\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.text), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AlertElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/AlertElement.js?");
/***/ }),
/***/ "./src/includes/AlertWidget.js":
/*!*************************************!*\
!*** ./src/includes/AlertWidget.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _AlertElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AlertElement.js */ \"./src/includes/AlertElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar AlertWidget = /*#__PURE__*/function (_BaseWidget) {\n function AlertWidget() {\n var _this;\n _classCallCheck(this, AlertWidget);\n _this = _callSuper(this, AlertWidget); // Call the parent class constructor\n\n // Add an AlertElement to the widget\n var alert = new _AlertElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Alert', 'This is an alert!');\n\n // Append the new element to the block\n _this.block.appendElements([alert]);\n return _this;\n }\n _inherits(AlertWidget, _BaseWidget);\n return _createClass(AlertWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.alert');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'notification_important';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AlertWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/AlertWidget.js?");
/***/ }),
/***/ "./src/includes/AlignControl.js":
/*!**************************************!*\
!*** ./src/includes/AlignControl.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * AlignControl — segmented radio picker for 2-N mutually-exclusive values.\n *\n * Primary use: text alignment (left/center/right/justify) on text-bearing\n * elements (PElement, HeadingElement, LinkElement, ButtonElement,\n * AlertElement, LabelElement, SubmitButtonElement). Also re-used with\n * custom icons for orientation (MenuElement), block alignment (ImageElement,\n * GridElement cell-alignment), and other 2-3-option pickers.\n *\n * ── Bus subscription (TEXT_INLINE_PLAN W1.1b — D13 v5 dual-view sync) ──\n * When constructed with `options = { bus, elementUid, formatterKey }` the\n * control subscribes to `formatter:change` on the bus and mirrors its UI\n * state whenever another surface (inline toolbar / future W4.1 advanced\n * popover / any surface writing via `element.formatter.*`) writes the same\n * `{ elementUid, formatterKey }` pair. Echoes are skipped via a unique\n * `source` tag stamped on every emit. The control also emits on user click\n * so the inverse direction is already wired for later subscribers (e.g.\n * the inline toolbar itself when it wants to mirror sidebar clicks).\n *\n * Without `options` the control behaves exactly as pre-W1.1b — zero\n * behaviour change for non-text-align callsites (MenuElement orientation,\n * GridElement align-items, etc.). Opt-in only.\n *\n * ── Lifecycle ──\n * `destroy()` tears down the bus subscription. `Builder.renderElementControls`\n * (Builder.js:1117) calls it on every outgoing control before the sidebar\n * rebuilds (BaseControl invariant I14), so subscriptions never outlive the\n * control instance.\n */\nvar AlignControl = /*#__PURE__*/function () {\n /**\n * @param {string} label\n * @param {string} value\n * @param {object} callback\n * @param {Array<string|{value: string, icon: string}>} possibleValues\n * Each entry is either a raw value string (icon auto-derived as\n * `format_align_<value>` — the text-alignment default) or an object\n * with an explicit Material Symbol icon name. Use the explicit form\n * when the value isn't a text alignment (e.g. MenuElement orientation:\n * `[{value: 'horizontal', icon: 'view_column'}, {value: 'vertical', icon: 'view_agenda'}]`).\n * `format_align_horizontal` is NOT a valid Material Symbol — falling\n * back to the ligature renders the raw uppercase text.\n * @param {{bus?: object, elementUid?: string, formatterKey?: string}} [options]\n * Optional D13 v5 dual-view bus wiring. When all three fields are\n * present and `bus` exposes `on(event, fn) → disposer` + `emit(event, payload)`\n * (CanvasHighlightBus contract), the control subscribes to\n * `formatter:change` and also emits on user clicks. Omit for callsites\n * whose formatter key is not shared with another surface.\n */\n function AlignControl(label, value, callback) {\n var possibleValues = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ['left', 'justify', 'center', 'right'];\n var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};\n _classCallCheck(this, AlignControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = value;\n this.callback = callback;\n\n // W1.1b dual-view bus wiring. _busSource is stamped on every emit so\n // our own subscriber filter can drop self-echoes deterministically.\n this._options = options || {};\n this._busOff = null;\n this._busSource = 'sidebar-align-control:' + this.id;\n this.options = possibleValues.map(function (entry) {\n if (entry && _typeof(entry) === 'object') {\n return {\n icon: entry.icon,\n value: entry.value\n };\n }\n return {\n icon: \"format_align_\".concat(entry),\n value: entry\n };\n });\n this.domNode = document.createElement(\"div\");\n this.render();\n this._attachBusSubscription();\n }\n return _createClass(AlignControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var buttons = this.options.map(function (option) {\n var isActive = _this.value === option.value;\n return \"\\n <button type=\\\"button\\\"\\n class=\\\"bjs-segmented-btn\".concat(isActive ? ' is-active' : '', \"\\\"\\n role=\\\"radio\\\"\\n aria-checked=\\\"\").concat(isActive, \"\\\"\\n data-value=\\\"\").concat(option.value, \"\\\"\\n data-tooltip=\\\"\").concat(option.value, \"\\\"\\n aria-label=\\\"\").concat(option.value, \"\\\"\\n tabindex=\\\"\").concat(isActive ? '0' : '-1', \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\").concat(option.icon, \"</span>\\n </button>\\n \");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\"><span>\".concat(this.label, \"</span></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-segmented\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(this.label, \"\\\">\\n \").concat(buttons, \"\\n </div>\\n </div>\\n </div>\\n \");\n this._bindEvents();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this2 = this;\n var group = this.domNode.querySelector('.bjs-segmented');\n if (!group) return;\n group.addEventListener('click', function (e) {\n var btn = e.target.closest('.bjs-segmented-btn');\n if (!btn || !group.contains(btn)) return;\n _this2._selectValue(btn.dataset.value, {\n focus: true\n });\n });\n group.addEventListener('keydown', function (e) {\n if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) return;\n e.preventDefault();\n var buttons = Array.from(group.querySelectorAll('.bjs-segmented-btn'));\n var currentIndex = buttons.findIndex(function (b) {\n return b.classList.contains('is-active');\n });\n var nextIndex = currentIndex;\n if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n nextIndex = (currentIndex - 1 + buttons.length) % buttons.length;\n } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n nextIndex = (currentIndex + 1) % buttons.length;\n } else if (e.key === 'Home') {\n nextIndex = 0;\n } else if (e.key === 'End') {\n nextIndex = buttons.length - 1;\n }\n var nextBtn = buttons[nextIndex];\n if (nextBtn) _this2._selectValue(nextBtn.dataset.value, {\n focus: true\n });\n });\n }\n }, {\n key: \"_selectValue\",\n value: function _selectValue(value) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$focus = _ref.focus,\n focus = _ref$focus === void 0 ? false : _ref$focus;\n if (value === this.value) return;\n this.value = value;\n this._updateActiveState();\n if (focus) {\n var active = this.domNode.querySelector('.bjs-segmented-btn.is-active');\n if (active) active.focus();\n }\n this._fireCallback();\n // Broadcast so inline toolbar / other subscribers mirror this user\n // action. `source` lets our own subscriber skip the echo.\n this._emitBus();\n }\n }, {\n key: \"_updateActiveState\",\n value: function _updateActiveState() {\n var _this3 = this;\n this.domNode.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n var isActive = btn.dataset.value === _this3.value;\n btn.classList.toggle('is-active', isActive);\n btn.setAttribute('aria-checked', String(isActive));\n btn.setAttribute('tabindex', isActive ? '0' : '-1');\n });\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n /**\n * External entry point. Used by both legacy callers (pre-W1.1b, no\n * `options`) and the W1.1b bus subscriber (with `{ silent: true }` so\n * the subscribed-side mirror does NOT refire the callback — otherwise\n * the formatter would be written twice and any future subscriber would\n * see duplicate emits.\n *\n * Legacy callsite contract is preserved: a bare `setValue(x)` still\n * fires the callback exactly as before.\n */\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref2$silent = _ref2.silent,\n silent = _ref2$silent === void 0 ? false : _ref2$silent;\n if (newValue === this.value) return;\n this.value = newValue;\n this._updateActiveState();\n if (silent) return;\n this._fireCallback();\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n\n /** Control teardown — drops the bus subscription. Called by\n * `Builder.renderElementControls` (Phase 1.8 SA I14) on sidebar rebuild. */\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this._busOff) {\n this._busOff();\n this._busOff = null;\n }\n }\n\n // ─── private ──────────────────────────────────────────────────────────\n }, {\n key: \"_fireCallback\",\n value: function _fireCallback() {\n if (typeof this.callback === 'function') {\n this.callback(this.value);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(this.value);\n }\n }\n }, {\n key: \"_attachBusSubscription\",\n value: function _attachBusSubscription() {\n var _this4 = this;\n var _this$_options = this._options,\n bus = _this$_options.bus,\n elementUid = _this$_options.elementUid,\n formatterKey = _this$_options.formatterKey;\n if (!bus || !elementUid || !formatterKey) return;\n if (typeof bus.on !== 'function') return;\n this._busOff = bus.on('formatter:change', function (payload) {\n if (!payload) return;\n if (payload.elementUid !== elementUid) return;\n if (payload.key !== formatterKey) return;\n if (payload.source === _this4._busSource) return;\n // Silent setValue — UI updates, callback does NOT fire (the other\n // surface already wrote the formatter; refiring would double-write\n // and re-broadcast causing an emit storm).\n _this4.setValue(payload.value, {\n silent: true\n });\n });\n }\n }, {\n key: \"_emitBus\",\n value: function _emitBus() {\n var _this$_options2 = this._options,\n bus = _this$_options2.bus,\n elementUid = _this$_options2.elementUid,\n formatterKey = _this$_options2.formatterKey;\n if (!bus || !elementUid || !formatterKey) return;\n if (typeof bus.emit !== 'function') return;\n bus.emit('formatter:change', {\n elementUid: elementUid,\n key: formatterKey,\n value: this.value,\n source: this._busSource\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AlignControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/AlignControl.js?");
/***/ }),
/***/ "./src/includes/BJS.js":
/*!*****************************!*\
!*** ./src/includes/BJS.js ***!
\*****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/**\n * BJS — debug namespace (Phase 1.9).\n *\n * Single entry-point for framework-internal logging. Gated by\n * `window.__bjsDebug = true` (off by default). Keeps diagnostic noise out\n * of production consoles while giving developers a one-liner to turn on\n * detailed overlay/control/element lifecycle tracing.\n *\n * // In a DevTools console, to trace overlay lifecycle:\n * window.__bjsDebug = true\n *\n * // Back off:\n * window.__bjsDebug = false\n *\n * Severity levels:\n * - BJS.log — lifecycle + info events (overlay mounted, listener registered)\n * - BJS.warn — recoverable misuse (re-entrant sync, template drift)\n * - BJS.error — errors that were caught by an error boundary\n *\n * warn + error are ALWAYS surfaced (even when __bjsDebug is off) because\n * they're recoverable-but-noteworthy conditions users + support need to\n * see. Only `log` is debug-gated.\n */\n\nfunction dbg() {\n return typeof window !== 'undefined' && window.__bjsDebug === true;\n}\nvar BJS = {\n log: function log(tag) {\n var _console;\n if (!dbg()) return;\n // eslint-disable-next-line no-console\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n (_console = console).log.apply(_console, [\"[bjs] \".concat(tag)].concat(args));\n },\n warn: function warn(tag) {\n var _console2;\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n // eslint-disable-next-line no-console\n (_console2 = console).warn.apply(_console2, [\"[bjs] \".concat(tag)].concat(args));\n },\n error: function error(tag) {\n var _console3;\n for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n args[_key3 - 1] = arguments[_key3];\n }\n // eslint-disable-next-line no-console\n (_console3 = console).error.apply(_console3, [\"[bjs] \".concat(tag)].concat(args));\n },\n /** Wrap a fn so errors are caught + logged under `tag` instead of\n * propagating. Returns a function with the same signature. Useful for\n * user-installed callbacks (overlay render, control subscribers) where\n * one bug shouldn't crash the framework. */\n safely: function safely(tag, fn) {\n return function bjsSafeWrapper() {\n try {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n return fn.apply(this, args);\n } catch (err) {\n BJS.error(tag, err);\n return undefined;\n }\n };\n }\n};\n\n// Expose on window so DevTools users can enable/disable without imports.\nif (typeof window !== 'undefined') {\n window.BJS = BJS;\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BJS);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BJS.js?");
/***/ }),
/***/ "./src/includes/BackgroundControl.js":
/*!*******************************************!*\
!*** ./src/includes/BackgroundControl.js ***!
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n// BackgroundControl v2 — interactive background editor.\n//\n// Sections (top → bottom, all collapsible into one panel):\n// 1. Section header (title + desc) — always visible\n// 2. Color — swatch + hex input\n// 3. Image (live preview, drag focus, scroll zoom) — toggle per-section\n// 4. Size (chips: Cover · Contain · Original · custom %) — image-gated\n// 5. Repeat (chips: None · Tile · Tile X · Tile Y) — image-gated\n// 6. Gradient (type · 2 colors · angle · opacity stop) — toggle per-section\n// 7. Effects (opacity · blend mode · filter sliders) — toggle per-section\n// 8. Reset button\n//\n// Public API (backward compatible — existing 12 consumer elements keep working):\n// new BackgroundControl(label, values, callback, options)\n// callback.setBackground(values) — receives composed values\n// values shape IN: { color, image, size, position, toRepeat,\n// opacity?, blendMode?, filter?, gradient? }\n// values shape OUT (getValues): same + internalPosition, posX%, posY%\n// image IS COMPOSED (gradient + url) when gradient is on\n//\n// CSS namespace: .bbg-* (self-scoped, no Bootstrap dependency).\n//\n// Design mirrors ImageCropControl for consistency — same preview/drag/zoom/chips patterns.\n\n\n\nvar BackgroundControl = /*#__PURE__*/function () {\n function BackgroundControl(label) {\n var values = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n _classCallCheck(this, BackgroundControl);\n this.label = label || _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.background_settings');\n this.id = '_bbg_' + Math.random().toString(36).substr(2, 9);\n this.callback = callback;\n\n // Feature flags — all on by default. Consumers can pass options.features\n // (array) to hide sections, e.g. { features: ['color','image','repeat'] }.\n var DEFAULT_FEATURES = ['color', 'image', 'size', 'repeat', 'gradient', 'effects'];\n this.features = Array.isArray(options.features) && options.features.length ? options.features : DEFAULT_FEATURES;\n\n // Flatten consumer values into our state.\n this.state = this._normalizeIn(values);\n this.domNode = document.createElement('div');\n this.domNode.className = 'BackgroundControl bbg-root';\n this._dragging = false;\n this._lastFocusedField = null;\n this.render();\n }\n\n // -------------------- input/output helpers --------------------\n return _createClass(BackgroundControl, [{\n key: \"_normalizeIn\",\n value: function _normalizeIn(values) {\n // position \"top-left\" / \"center\" → internal form + posX%/posY%\n var pos = values.position || 'center';\n var posX = values.posX !== undefined ? this._clampPct(values.posX) : this._posToPct(pos, 'x');\n var posY = values.posY !== undefined ? this._clampPct(values.posY) : this._posToPct(pos, 'y');\n\n // Detect if the incoming `image` was a composite (gradient or url).\n // We extract the raw URL (if any) for the Image section preview/input,\n // keeping the control truthful about what's actually persisted.\n var rawImg = this._extractImageUrl(values.image);\n\n // Gradient: either explicit `gradient` object or parsed from `image` if it's a gradient.\n var gradient = values.gradient && _typeof(values.gradient) === 'object' ? this._normalizeGradient(values.gradient) : this._parseGradientFromImage(values.image) || this._defaultGradient();\n return {\n color: values.color || '',\n image: rawImg,\n sizeMode: this._sizeMode(values.size),\n // 'cover' | 'contain' | 'custom'\n sizePct: this._sizePct(values.size),\n // 10-400 when mode=custom\n posX: posX,\n posY: posY,\n repeat: this._normalizeRepeat(values),\n opacity: values.opacity === undefined || values.opacity === null ? 100 : this._clampPct(values.opacity),\n blendMode: values.blendMode || 'normal',\n filter: this._normalizeFilter(values.filter),\n gradient: gradient\n };\n }\n }, {\n key: \"_sizeMode\",\n value: function _sizeMode(v) {\n if (v === 'cover' || v === 'contain') return v;\n return 'custom';\n }\n }, {\n key: \"_sizePct\",\n value: function _sizePct(v) {\n if (typeof v === 'number') return Math.max(10, Math.min(400, v));\n if (typeof v === 'string') {\n if (v === 'cover' || v === 'contain') return 100;\n var n = parseInt(String(v).replace('%', ''), 10);\n return Number.isFinite(n) ? Math.max(10, Math.min(400, n)) : 100;\n }\n return 100;\n }\n }, {\n key: \"_normalizeRepeat\",\n value: function _normalizeRepeat(values) {\n // Legacy: toRepeat:true/false. Modern: repeat:'no-repeat'|'repeat'|'repeat-x'|'repeat-y'\n if (values.repeat) return values.repeat;\n return values.toRepeat ? 'repeat' : 'no-repeat';\n }\n }, {\n key: \"_normalizeFilter\",\n value: function _normalizeFilter(f) {\n var def = {\n blur: 0,\n brightness: 100,\n contrast: 100,\n saturate: 100,\n grayscale: 0\n };\n if (!f || _typeof(f) !== 'object') return def;\n return {\n blur: this._clampN(f.blur, 0, 20, 0),\n brightness: this._clampN(f.brightness, 0, 200, 100),\n contrast: this._clampN(f.contrast, 0, 200, 100),\n saturate: this._clampN(f.saturate, 0, 200, 100),\n grayscale: this._clampN(f.grayscale, 0, 100, 0)\n };\n }\n }, {\n key: \"_normalizeGradient\",\n value: function _normalizeGradient(g) {\n return {\n enabled: !!g.enabled,\n type: g.type === 'radial' ? 'radial' : 'linear',\n angle: this._clampN(g.angle, 0, 360, 180),\n color1: g.color1 || '#ffffff',\n color2: g.color2 || '#000000',\n stop1: this._clampN(g.stop1, 0, 100, 0),\n stop2: this._clampN(g.stop2, 0, 100, 100)\n };\n }\n }, {\n key: \"_defaultGradient\",\n value: function _defaultGradient() {\n return {\n enabled: false,\n type: 'linear',\n angle: 180,\n color1: '#8b5cf6',\n color2: '#ec4899',\n stop1: 0,\n stop2: 100\n };\n }\n }, {\n key: \"_parseGradientFromImage\",\n value: function _parseGradientFromImage(img) {\n if (typeof img !== 'string') return null;\n var m = img.trim().match(/^(linear|radial)-gradient\\s*\\(([^)]*)\\)/i);\n if (!m) return null;\n var type = m[1].toLowerCase();\n var inner = m[2];\n // linear-gradient(180deg, #aaa 0%, #bbb 100%) — best-effort parse\n var parts = inner.split(',').map(function (s) {\n return s.trim();\n });\n var g = this._defaultGradient();\n g.enabled = true;\n g.type = type === 'radial' ? 'radial' : 'linear';\n if (type === 'linear' && parts.length >= 3 && /deg|rad|turn/.test(parts[0])) {\n var ang = parseFloat(parts[0]);\n if (Number.isFinite(ang)) g.angle = (ang % 360 + 360) % 360;\n parts.shift();\n }\n if (parts[0]) {\n var _this$_splitStop = this._splitStop(parts[0]),\n _this$_splitStop2 = _slicedToArray(_this$_splitStop, 2),\n c = _this$_splitStop2[0],\n p = _this$_splitStop2[1];\n if (c) g.color1 = c;\n if (p !== null) g.stop1 = p;\n }\n if (parts[1]) {\n var _this$_splitStop3 = this._splitStop(parts[1]),\n _this$_splitStop4 = _slicedToArray(_this$_splitStop3, 2),\n _c = _this$_splitStop4[0],\n _p = _this$_splitStop4[1];\n if (_c) g.color2 = _c;\n if (_p !== null) g.stop2 = _p;\n }\n return g;\n }\n }, {\n key: \"_splitStop\",\n value: function _splitStop(str) {\n var m = str.match(/^(\\S+)\\s*(\\d+)%$/);\n if (m) return [m[1], parseInt(m[2], 10)];\n return [str, null];\n }\n }, {\n key: \"_extractImageUrl\",\n value: function _extractImageUrl(img) {\n if (!img || typeof img !== 'string') return '';\n var trimmed = img.trim();\n // If it's purely a gradient (no url(...)), image URL is empty.\n if (/^(linear|radial|conic)-gradient\\s*\\(/i.test(trimmed) && !/\\burl\\s*\\(/i.test(trimmed)) {\n return '';\n }\n // Extract url(...) if present. Take the LAST url() (composite \"grad, url(...)\" has url at end).\n var urls = _toConsumableArray(trimmed.matchAll(/url\\s*\\(\\s*(['\"]?)([^'\")]+)\\1\\s*\\)/gi));\n if (urls.length) return urls[urls.length - 1][2];\n return trimmed;\n }\n }, {\n key: \"_clampN\",\n value: function _clampN(v, min, max, def) {\n var n = parseFloat(v);\n if (!Number.isFinite(n)) return def;\n return Math.max(min, Math.min(max, n));\n }\n }, {\n key: \"_clampPct\",\n value: function _clampPct(v) {\n var n = parseFloat(v);\n if (!Number.isFinite(n)) return 50;\n return Math.max(0, Math.min(100, n));\n }\n }, {\n key: \"_posToPct\",\n value: function _posToPct(pos, axis) {\n var s = String(pos || '').trim();\n // Percent form: \"33% 67%\" / \"50% 50%\" — split into X then Y\n var pctMatch = s.match(/(-?\\d+(?:\\.\\d+)?)\\s*%\\s+(-?\\d+(?:\\.\\d+)?)\\s*%/);\n if (pctMatch) {\n return axis === 'x' ? this._clampPct(parseFloat(pctMatch[1])) : this._clampPct(parseFloat(pctMatch[2]));\n }\n // Single percent (axis-specific, e.g. \"50%\") — apply to both axes\n var single = s.match(/^(-?\\d+(?:\\.\\d+)?)\\s*%$/);\n if (single) return this._clampPct(parseFloat(single[1]));\n // Keyword form\n if (axis === 'x') {\n if (s.includes('left')) return 0;\n if (s.includes('right')) return 100;\n return 50;\n }\n if (s.includes('top')) return 0;\n if (s.includes('bottom')) return 100;\n return 50;\n }\n }, {\n key: \"_pctToPos\",\n value: function _pctToPos(x, y) {\n // Snap to named keywords when at exact edges (0/50/100) for legacy compat.\n var sx = x === 0 ? 'left' : x === 100 ? 'right' : x === 50 ? 'center' : null;\n var sy = y === 0 ? 'top' : y === 100 ? 'bottom' : y === 50 ? 'center' : null;\n if (sx === 'center' && sy === 'center') return 'center';\n if (sx && sy) return \"\".concat(sy, \"-\").concat(sx);\n // Non-snapped: emit CSS percent\n return \"\".concat(x, \"% \").concat(y, \"%\");\n }\n\n // Output shape — preserves backward-compat with pre-v2 consumer callbacks.\n }, {\n key: \"getValues\",\n value: function getValues() {\n var s = this.state;\n var cssImage = this._composeCssBackgroundImage();\n // Emit as CSS-ready string — 'cover'/'contain' or 'N%'. This is what\n // callers pipe straight into formatter.setFormat('background_size').\n // (Formatter has no unit auto-add for background-size, so we commit the % here.)\n var cssSize = s.sizeMode === 'custom' ? \"\".concat(s.sizePct, \"%\") : s.sizeMode;\n var cssPosition = this._pctToPos(Math.round(s.posX), Math.round(s.posY));\n var filterStr = this._composeFilter();\n return {\n color: s.color,\n image: cssImage,\n // composed (gradient + url) — legacy consumers pipe into background_image\n rawImage: s.image,\n // raw url (for re-hydration)\n size: cssSize,\n // 'cover' | 'contain' | number\n position: cssPosition,\n // legacy keyword form\n internalPosition: cssPosition,\n // back-compat alias\n posX: Math.round(s.posX),\n posY: Math.round(s.posY),\n repeat: s.repeat,\n toRepeat: s.repeat === 'repeat' || s.repeat === 'repeat-x' || s.repeat === 'repeat-y',\n // legacy\n opacity: s.opacity / 100,\n // element-level opacity (0..1)\n opacityPct: Math.round(s.opacity),\n blendMode: s.blendMode,\n filter: filterStr,\n // composed CSS filter string ('' when inert)\n filterRaw: _objectSpread({}, s.filter),\n gradient: _objectSpread({}, s.gradient)\n };\n }\n }, {\n key: \"_composeCssBackgroundImage\",\n value: function _composeCssBackgroundImage() {\n var s = this.state;\n var gradStr = s.gradient.enabled ? this._gradientCss() : '';\n var urlStr = s.image ? \"url(\".concat(s.image, \")\") : '';\n if (gradStr && urlStr) return \"\".concat(gradStr, \", \").concat(urlStr);\n return gradStr || urlStr || '';\n }\n }, {\n key: \"_gradientCss\",\n value: function _gradientCss() {\n var g = this.state.gradient;\n var stops = \"\".concat(g.color1, \" \").concat(g.stop1, \"%, \").concat(g.color2, \" \").concat(g.stop2, \"%\");\n if (g.type === 'radial') {\n return \"radial-gradient(circle at center, \".concat(stops, \")\");\n }\n return \"linear-gradient(\".concat(g.angle, \"deg, \").concat(stops, \")\");\n }\n }, {\n key: \"_composeFilter\",\n value: function _composeFilter() {\n var f = this.state.filter;\n var parts = [];\n if (f.blur > 0) parts.push(\"blur(\".concat(f.blur, \"px)\"));\n if (f.brightness !== 100) parts.push(\"brightness(\".concat(f.brightness, \"%)\"));\n if (f.contrast !== 100) parts.push(\"contrast(\".concat(f.contrast, \"%)\"));\n if (f.saturate !== 100) parts.push(\"saturate(\".concat(f.saturate, \"%)\"));\n if (f.grayscale > 0) parts.push(\"grayscale(\".concat(f.grayscale, \"%)\"));\n return parts.join(' ');\n }\n }, {\n key: \"_emit\",\n value: function _emit() {\n if (this.callback && typeof this.callback.setBackground === 'function') {\n this.callback.setBackground(this.getValues());\n }\n }\n\n // -------------------- URL helpers (match v1) --------------------\n }, {\n key: \"resolveImageUrl\",\n value: function resolveImageUrl(url) {\n var _this$host;\n var n = this._normalizeImageReference(url);\n if (!n) return '';\n if (n.startsWith('/theme/assets/')) return n;\n if (/^https?:\\/\\//i.test(n) || n.startsWith('/assets/') || n.startsWith('#') || n.startsWith('[') || n.startsWith('{') || n.startsWith('data:image')) return n;\n if (typeof ((_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.transferMediaAbsUrl) === 'function') {\n return this.host.transferMediaAbsUrl(n);\n }\n return n;\n }\n }, {\n key: \"toStoredImageUrl\",\n value: function toStoredImageUrl(url) {\n var _this$host2;\n var n = this._normalizeImageReference(url);\n if (!n) return '';\n var themed = this._extractThemeAssetPath(n);\n if (themed) return themed;\n if ((_this$host2 = this.host) !== null && _this$host2 !== void 0 && _this$host2.themeMediaUrl) {\n var prefix = this.host.themeMediaUrl.replace(/\\/$/, '') + '/';\n if (prefix !== '/' && n.startsWith(prefix)) return n.slice(prefix.length);\n }\n return n;\n }\n }, {\n key: \"_normalizeImageReference\",\n value: function _normalizeImageReference(url) {\n if (!url || typeof url !== 'string') return '';\n var v = url.trim();\n var m = v.match(/^url\\((.*)\\)$/i);\n if (m) v = m[1].trim();\n return v.replace(/^['\"]|['\"]$/g, '');\n }\n }, {\n key: \"_extractThemeAssetPath\",\n value: function _extractThemeAssetPath(url) {\n var n = this._normalizeImageReference(url);\n if (!n) return '';\n var m1 = n.match(/^\\/theme\\/assets\\/[^/]+\\/f\\/(.+)$/);\n if (m1) return m1[1];\n var m2 = n.match(/^\\/?(master|others|assets|image)\\/.+$/);\n if (m2) return n.replace(/^\\/+/, '');\n return '';\n }\n\n // -------------------- rendering --------------------\n\n /** Builder hook — fires after host injection + DOM mount. Re-render\n * so resolveImageUrl() / toStoredImageUrl() can route through\n * this.host.transferMediaAbsUrl + this.host.themeMediaUrl now that\n * host is set. The constructor's initial render uses the raw stored\n * path as a fallback (host?.X chains gracefully) — afterRender()\n * upgrades the preview to the per-instance absolute URL. */\n }, {\n key: \"afterRender\",\n value: function afterRender() {\n this.render();\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this = this;\n var has = function has(f) {\n return _this.features.includes(f);\n };\n var s = this.state;\n var id = this.id;\n var previewImg = this.resolveImageUrl(s.image);\n var hasImage = !!previewImg;\n var effectsActive = s.opacity !== 100 || s.blendMode !== 'normal' || this._composeFilter() !== '';\n this.domNode.innerHTML = \"\\n <style>\".concat(this._styles(), \"</style>\\n <div class=\\\"bbg-panel\\\" id=\\\"panel_\").concat(id, \"\\\">\\n\\n <div class=\\\"bbg-header\\\">\\n <div class=\\\"bbg-title\\\">\").concat(this.label, \"</div>\\n <div class=\\\"bbg-desc\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('background.desc'), \"</div>\\n </div>\\n\\n \").concat(has('color') ? \"\\n <div class=\\\"bbg-section\\\" data-section=\\\"color\\\">\\n <div id=\\\"bbgColorHost_\".concat(id, \"\\\" class=\\\"bbg-color-host\\\"></div>\\n </div>\") : '', \"\\n\\n \").concat(has('image') ? \"\\n <div class=\\\"bbg-section\\\" data-section=\\\"image\\\">\\n <div class=\\\"bbg-section-head\\\">\\n <span class=\\\"bbg-section-label\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.image'), \"</span>\\n </div>\\n\\n <div class=\\\"bbg-image-hero\\\">\\n <div class=\\\"bbg-preview-wrap \").concat(hasImage ? '' : 'is-empty', \"\\\" data-role=\\\"preview-wrap\\\">\\n <div class=\\\"bbg-preview\\\" data-role=\\\"preview\\\"\\n style=\\\"\").concat(this._previewStyle(previewImg), \"\\\">\\n \").concat(hasImage ? \"<div class=\\\"bbg-focus-dot\\\" style=\\\"left:\".concat(s.posX, \"%; top:\").concat(s.posY, \"%;\\\"></div>\\n <div class=\\\"bbg-grid\\\" aria-hidden=\\\"true\\\"><span></span><span></span><span></span><span></span></div>\") : \"<div class=\\\"bbg-empty-hint\\\">\\n <svg width=\\\"22\\\" height=\\\"22\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" aria-hidden=\\\"true\\\">\\n <rect x=\\\"3\\\" y=\\\"5\\\" width=\\\"18\\\" height=\\\"14\\\" rx=\\\"2\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\"/>\\n <circle cx=\\\"9\\\" cy=\\\"11\\\" r=\\\"1.6\\\" fill=\\\"currentColor\\\"/>\\n <path d=\\\"M3 17l5-5 4 4 3-3 6 6\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\\n </div>\", \"\\n </div>\\n </div>\\n <div class=\\\"bbg-image-side\\\">\\n <div class=\\\"bbg-image-info\\\" data-role=\\\"image-info\\\">\\n <span class=\\\"bbg-image-filename \").concat(hasImage ? '' : 'is-muted', \"\\\" data-role=\\\"filename\\\">\").concat(hasImage ? '' : _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.no_image'), \"</span>\\n <span class=\\\"bbg-image-meta\\\" data-role=\\\"meta\\\">\").concat(hasImage ? '' : _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.no_image_hint'), \"</span>\\n </div>\\n <div class=\\\"bbg-image-actions\\\">\\n <button type=\\\"button\\\" class=\\\"bbg-action-btn\\\" data-action=\\\"upload\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.upload'), \"\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.upload'), \"\\\">\\n <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 16 16\\\" fill=\\\"none\\\"><path d=\\\"M8 2v9M8 2L4 6M8 2l4 4M3 13h10\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/></svg>\\n </button>\\n <button type=\\\"button\\\" class=\\\"bbg-action-btn\\\" data-action=\\\"paste-url\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.paste_url'), \"\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.paste_url'), \"\\\">\\n <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 16 16\\\" fill=\\\"none\\\"><path d=\\\"M7 9a2.5 2.5 0 0 1 0-3.5l2-2a2.5 2.5 0 0 1 3.5 3.5L11 8.5\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/><path d=\\\"M9 7a2.5 2.5 0 0 1 0 3.5l-2 2a2.5 2.5 0 0 1-3.5-3.5L5 7.5\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/></svg>\\n </button>\\n <button type=\\\"button\\\" class=\\\"bbg-action-btn bbg-action-btn--danger \").concat(hasImage ? '' : 'is-disabled', \"\\\" data-action=\\\"remove\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.remove'), \"\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.remove'), \"\\\" \").concat(hasImage ? '' : 'disabled', \">\\n <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 16 16\\\" fill=\\\"none\\\"><path d=\\\"M3 5h10M6 5V3h4v2M5 5l1 9h4l1-9\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/></svg>\\n </button>\\n </div>\\n </div>\\n </div>\\n\\n <div class=\\\"bbg-url-row \").concat(this._urlRowVisible ? 'is-open' : 'is-hidden', \"\\\" data-role=\\\"url-row\\\">\\n <input type=\\\"text\\\" class=\\\"bbg-url-input\\\" data-role=\\\"url\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.enter_url'), \"\\\"\\n value=\\\"\").concat(hasImage ? this.toStoredImageUrl(s.image) : '', \"\\\">\\n </div>\\n\\n \").concat(has('size') ? \"\\n <div class=\\\"bbg-sub\\\" \".concat(hasImage ? '' : 'hidden', \" data-role=\\\"size-sub\\\">\\n <div class=\\\"bbg-sub-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.size'), \"</div>\\n <div class=\\\"bbg-chips\\\" data-role=\\\"size-chips\\\">\\n \").concat(this._sizeChipsHtml(), \"\\n </div>\\n <div class=\\\"bbg-row \").concat(s.sizeMode === 'custom' ? '' : 'is-muted', \"\\\" data-role=\\\"size-custom\\\">\\n <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.size_custom'), \"</label>\\n <div class=\\\"bbg-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"sizePct\\\"\\n min=\\\"10\\\" max=\\\"400\\\" step=\\\"1\\\" value=\\\"\").concat(s.sizePct, \"\\\"\\n style=\\\"--pct:\").concat((s.sizePct - 10) / (400 - 10) * 100, \"%\\\">\\n </div>\\n <div class=\\\"bbg-value-wrap\\\">\\n <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"sizePct-num\\\"\\n min=\\\"10\\\" max=\\\"400\\\" step=\\\"1\\\" value=\\\"\").concat(s.sizePct, \"\\\">\\n <span class=\\\"bbg-unit\\\">%</span>\\n </div>\\n </div>\\n </div>\") : '', \"\\n\\n <div class=\\\"bbg-sub\\\" \").concat(hasImage ? '' : 'hidden', \" data-role=\\\"position-sub\\\">\\n <div class=\\\"bbg-sub-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.focus'), \"</div>\\n <div class=\\\"bbg-row\\\">\\n <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.focus_x'), \"</label>\\n <div class=\\\"bbg-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"posX\\\"\\n min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(s.posX, \"\\\"\\n style=\\\"--pct:\").concat(s.posX, \"%\\\">\\n </div>\\n <div class=\\\"bbg-value-wrap\\\">\\n <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"posX-num\\\"\\n min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(Math.round(s.posX), \"\\\">\\n <span class=\\\"bbg-unit\\\">%</span>\\n </div>\\n </div>\\n <div class=\\\"bbg-row\\\">\\n <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.focus_y'), \"</label>\\n <div class=\\\"bbg-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"posY\\\"\\n min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(s.posY, \"\\\"\\n style=\\\"--pct:\").concat(s.posY, \"%\\\">\\n </div>\\n <div class=\\\"bbg-value-wrap\\\">\\n <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"posY-num\\\"\\n min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(Math.round(s.posY), \"\\\">\\n <span class=\\\"bbg-unit\\\">%</span>\\n </div>\\n </div>\\n </div>\\n\\n \").concat(has('repeat') ? \"\\n <div class=\\\"bbg-sub\\\" \".concat(hasImage ? '' : 'hidden', \" data-role=\\\"repeat-sub\\\">\\n <div class=\\\"bbg-sub-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.repeat'), \"</div>\\n <div class=\\\"bbg-chips\\\" data-role=\\\"repeat-chips\\\">\\n \").concat(this._repeatChipsHtml(), \"\\n </div>\\n </div>\") : '', \"\\n </div>\") : '', \"\\n\\n \").concat(has('gradient') ? \"\\n <div class=\\\"bbg-section\\\" data-section=\\\"gradient\\\">\\n <div class=\\\"bbg-section-head\\\">\\n <span class=\\\"bbg-section-label\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient'), \"</span>\\n <label class=\\\"bbg-toggle\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_hint'), \"\\\">\\n <input type=\\\"checkbox\\\" class=\\\"bbg-toggle-input\\\" data-role=\\\"gradient-toggle\\\" \").concat(s.gradient.enabled ? 'checked' : '', \">\\n <span class=\\\"bbg-toggle-slider\\\"></span>\\n </label>\\n </div>\\n <div class=\\\"bbg-sub-body\\\" \").concat(s.gradient.enabled ? '' : 'hidden', \" data-role=\\\"gradient-body\\\">\\n <div class=\\\"bbg-gradient-preview\\\" data-role=\\\"gradient-preview\\\"\\n style=\\\"background:\").concat(this._gradientCss(), \";\\\"></div>\\n\\n <div class=\\\"bbg-sub-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_type'), \"</div>\\n <div class=\\\"bbg-chips\\\" data-role=\\\"gradient-type-chips\\\">\\n <button type=\\\"button\\\" class=\\\"bbg-chip \").concat(s.gradient.type === 'linear' ? 'is-active' : '', \"\\\" data-gtype=\\\"linear\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_linear'), \"</button>\\n <button type=\\\"button\\\" class=\\\"bbg-chip \").concat(s.gradient.type === 'radial' ? 'is-active' : '', \"\\\" data-gtype=\\\"radial\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_radial'), \"</button>\\n </div>\\n\\n <div class=\\\"bbg-row \").concat(s.gradient.type === 'linear' ? '' : 'is-muted', \"\\\" data-role=\\\"gradient-angle-row\\\">\\n <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_angle'), \"</label>\\n <div class=\\\"bbg-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"gradient-angle\\\"\\n min=\\\"0\\\" max=\\\"360\\\" step=\\\"1\\\" value=\\\"\").concat(s.gradient.angle, \"\\\"\\n style=\\\"--pct:\").concat(s.gradient.angle / 360 * 100, \"%\\\">\\n </div>\\n <div class=\\\"bbg-value-wrap\\\">\\n <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"gradient-angle-num\\\"\\n min=\\\"0\\\" max=\\\"360\\\" step=\\\"1\\\" value=\\\"\").concat(s.gradient.angle, \"\\\">\\n <span class=\\\"bbg-unit\\\">\\xB0</span>\\n </div>\\n </div>\\n\\n <div class=\\\"bbg-gradient-stops\\\">\\n <div class=\\\"bbg-gradient-stop\\\">\\n <div class=\\\"bbg-stop-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_color_1'), \"</div>\\n <div class=\\\"bbg-stop-row\\\">\\n <label class=\\\"bbg-swatch-wrap\\\">\\n <input type=\\\"color\\\" class=\\\"bbg-swatch-input\\\" data-role=\\\"gradient-color1\\\" value=\\\"\").concat(s.gradient.color1, \"\\\">\\n <span class=\\\"bbg-swatch\\\" style=\\\"background:\").concat(s.gradient.color1, \";\\\"></span>\\n </label>\\n <input type=\\\"text\\\" class=\\\"bbg-hex-input\\\" data-role=\\\"gradient-color1-hex\\\" value=\\\"\").concat(s.gradient.color1, \"\\\">\\n <input type=\\\"number\\\" class=\\\"bbg-value-input bbg-value-input--mini\\\" data-role=\\\"gradient-stop1\\\" min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(s.gradient.stop1, \"\\\">\\n <span class=\\\"bbg-unit\\\">%</span>\\n </div>\\n </div>\\n <div class=\\\"bbg-gradient-stop\\\">\\n <div class=\\\"bbg-stop-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_color_2'), \"</div>\\n <div class=\\\"bbg-stop-row\\\">\\n <label class=\\\"bbg-swatch-wrap\\\">\\n <input type=\\\"color\\\" class=\\\"bbg-swatch-input\\\" data-role=\\\"gradient-color2\\\" value=\\\"\").concat(s.gradient.color2, \"\\\">\\n <span class=\\\"bbg-swatch\\\" style=\\\"background:\").concat(s.gradient.color2, \";\\\"></span>\\n </label>\\n <input type=\\\"text\\\" class=\\\"bbg-hex-input\\\" data-role=\\\"gradient-color2-hex\\\" value=\\\"\").concat(s.gradient.color2, \"\\\">\\n <input type=\\\"number\\\" class=\\\"bbg-value-input bbg-value-input--mini\\\" data-role=\\\"gradient-stop2\\\" min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(s.gradient.stop2, \"\\\">\\n <span class=\\\"bbg-unit\\\">%</span>\\n </div>\\n </div>\\n </div>\\n\\n <div class=\\\"bbg-gradient-presets\\\">\\n <div class=\\\"bbg-sub-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_presets'), \"</div>\\n <div class=\\\"bbg-preset-grid\\\" data-role=\\\"gradient-preset-grid\\\">\\n \").concat(this._gradientPresetsHtml(), \"\\n </div>\\n </div>\\n </div>\\n </div>\") : '', \"\\n\\n \").concat(has('effects') ? \"\\n <div class=\\\"bbg-section\\\" data-section=\\\"effects\\\">\\n <div class=\\\"bbg-section-head\\\">\\n <span class=\\\"bbg-section-label\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.effects'), \"</span>\\n \").concat(effectsActive ? \"<span class=\\\"bbg-active-pill\\\" data-tooltip=\\\"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.effects_active'), \"\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.active'), \"</span>\") : '', \"\\n </div>\\n <div class=\\\"bbg-info\\\">\\n <span class=\\\"bbg-info-icon\\\" aria-hidden=\\\"true\\\">\\n <svg width=\\\"13\\\" height=\\\"13\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\"><circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"10\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\"/><path d=\\\"M12 8v5\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\" stroke-linecap=\\\"round\\\"/><circle cx=\\\"12\\\" cy=\\\"16.2\\\" r=\\\"1\\\" fill=\\\"currentColor\\\"/></svg>\\n </span>\\n <span class=\\\"bbg-info-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.effects_email_warning'), \"</span>\\n </div>\\n\\n <div class=\\\"bbg-row\\\">\\n <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.opacity'), \"</label>\\n <div class=\\\"bbg-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"opacity\\\"\\n min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(s.opacity, \"\\\"\\n style=\\\"--pct:\").concat(s.opacity, \"%\\\">\\n </div>\\n <div class=\\\"bbg-value-wrap\\\">\\n <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"opacity-num\\\"\\n min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(Math.round(s.opacity), \"\\\">\\n <span class=\\\"bbg-unit\\\">%</span>\\n </div>\\n </div>\\n\\n <div class=\\\"bbg-row\\\">\\n <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.blend_mode'), \"</label>\\n <select class=\\\"bbg-select\\\" data-role=\\\"blendMode\\\">\\n \").concat(this._blendOptionsHtml(), \"\\n </select>\\n </div>\\n\\n \").concat(['blur', 'brightness', 'contrast', 'saturate', 'grayscale'].map(function (k) {\n return _this._filterRowHtml(k);\n }).join(''), \"\\n\\n <div class=\\\"bbg-actions\\\">\\n <button type=\\\"button\\\" class=\\\"bbg-text-btn\\\" data-action=\\\"reset-effects\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.reset_effects'), \"</button>\\n </div>\\n </div>\") : '', \"\\n\\n <div class=\\\"bbg-footer\\\">\\n <button type=\\\"button\\\" class=\\\"bbg-reset-all\\\" data-action=\\\"reset-all\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.reset_all'), \"\\\">\\n <svg width=\\\"11\\\" height=\\\"11\\\" viewBox=\\\"0 0 12 12\\\" fill=\\\"none\\\"><path d=\\\"M2 6a4 4 0 1 0 1.2-2.83\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/><path d=\\\"M2 2v3h3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/></svg>\\n \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.reset_all'), \"\\n </button>\\n </div>\\n </div>\\n \");\n this._mountColorPicker();\n this._attachListeners();\n if (hasImage) this._updateImageMeta(this.resolveImageUrl(s.image));\n }\n }, {\n key: \"_previewStyle\",\n value: function _previewStyle(previewImg) {\n var s = this.state;\n if (!previewImg) return 'background:repeating-conic-gradient(#eef2f7 0% 25%, #fff 0% 50%) 50% / 16px 16px;';\n var sz = s.sizeMode === 'custom' ? \"\".concat(s.sizePct, \"%\") : s.sizeMode;\n return [\"background-image:url('\".concat(previewImg, \"')\"), \"background-repeat:\".concat(s.repeat), \"background-size:\".concat(sz), \"background-position:\".concat(s.posX, \"% \").concat(s.posY, \"%\")].join(';');\n }\n }, {\n key: \"_sizeChipsHtml\",\n value: function _sizeChipsHtml() {\n var s = this.state;\n var presets = [{\n mode: 'cover',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.size_cover')\n }, {\n mode: 'contain',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.size_contain')\n }, {\n mode: 'custom',\n pct: 50,\n label: '50%'\n }, {\n mode: 'custom',\n pct: 100,\n label: '100%'\n }, {\n mode: 'custom',\n pct: 150,\n label: '150%'\n }, {\n mode: 'custom',\n pct: 200,\n label: '200%'\n }];\n return presets.map(function (p) {\n var isActive = p.mode === 'cover' || p.mode === 'contain' ? s.sizeMode === p.mode : s.sizeMode === 'custom' && s.sizePct === p.pct;\n var dataAttrs = p.mode === 'custom' ? \"data-size-mode=\\\"custom\\\" data-size-pct=\\\"\".concat(p.pct, \"\\\"\") : \"data-size-mode=\\\"\".concat(p.mode, \"\\\"\");\n return \"<button type=\\\"button\\\" class=\\\"bbg-chip\".concat(isActive ? ' is-active' : '', \"\\\" \").concat(dataAttrs, \">\").concat(p.label, \"</button>\");\n }).join('');\n }\n }, {\n key: \"_repeatChipsHtml\",\n value: function _repeatChipsHtml() {\n var s = this.state;\n var presets = [{\n v: 'no-repeat',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.repeat_none'),\n icon: 'M4 4h8v8H4z'\n }, {\n v: 'repeat',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.repeat_tile'),\n icon: 'M2 2h5v5H2zM9 2h5v5H9zM2 9h5v5H2zM9 9h5v5H9z'\n }, {\n v: 'repeat-x',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.repeat_x'),\n icon: 'M2 5h4v6H2zM7 5h4v6H7zM12 5h4v6h-4z'\n }, {\n v: 'repeat-y',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.repeat_y'),\n icon: 'M5 2h6v4H5zM5 7h6v4H5zM5 12h6v4H5z'\n }];\n return presets.map(function (p) {\n var isActive = s.repeat === p.v;\n return \"<button type=\\\"button\\\" class=\\\"bbg-chip bbg-chip--icon\".concat(isActive ? ' is-active' : '', \"\\\" data-repeat=\\\"\").concat(p.v, \"\\\" data-tooltip=\\\"\").concat(p.label, \"\\\">\\n <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 16 16\\\" fill=\\\"currentColor\\\" aria-hidden=\\\"true\\\"><path d=\\\"\").concat(p.icon, \"\\\"/></svg>\\n <span>\").concat(p.label, \"</span>\\n </button>\");\n }).join('');\n }\n }, {\n key: \"_gradientPresetsHtml\",\n value: function _gradientPresetsHtml() {\n var presets = [{\n c1: '#8b5cf6',\n c2: '#ec4899',\n angle: 180\n },\n // purple-pink\n {\n c1: '#3b82f6',\n c2: '#06b6d4',\n angle: 135\n },\n // blue-cyan\n {\n c1: '#f59e0b',\n c2: '#ef4444',\n angle: 180\n },\n // sunset\n {\n c1: '#10b981',\n c2: '#3b82f6',\n angle: 180\n },\n // emerald-blue\n {\n c1: '#0f172a',\n c2: '#334155',\n angle: 180\n },\n // slate\n {\n c1: '#fef3c7',\n c2: '#fb923c',\n angle: 180\n },\n // cream-orange\n {\n c1: '#0ea5e9',\n c2: '#6366f1',\n angle: 225\n },\n // sky-indigo\n {\n c1: '#f9fafb',\n c2: '#e5e7eb',\n angle: 180\n } // soft gray\n ];\n return presets.map(function (p, i) {\n var css = \"linear-gradient(\".concat(p.angle, \"deg, \").concat(p.c1, \" 0%, \").concat(p.c2, \" 100%)\");\n return \"<button type=\\\"button\\\" class=\\\"bbg-preset-chip\\\" data-gpreset=\\\"\".concat(i, \"\\\"\\n data-gc1=\\\"\").concat(p.c1, \"\\\" data-gc2=\\\"\").concat(p.c2, \"\\\" data-gangle=\\\"\").concat(p.angle, \"\\\"\\n style=\\\"background:\").concat(css, \";\\\" data-tooltip=\\\"\").concat(p.c1, \" \\u2192 \").concat(p.c2, \"\\\"></button>\");\n }).join('');\n }\n }, {\n key: \"_blendOptionsHtml\",\n value: function _blendOptionsHtml() {\n var _this2 = this;\n var modes = ['normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'color-burn', 'soft-light', 'hard-light', 'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity'];\n return modes.map(function (m) {\n return \"<option value=\\\"\".concat(m, \"\\\" \").concat(_this2.state.blendMode === m ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.blend_' + m.replace('-', '_')), \"</option>\");\n }).join('');\n }\n }, {\n key: \"_filterRowHtml\",\n value: function _filterRowHtml(role) {\n var s = this.state;\n var cfg = {\n blur: {\n min: 0,\n max: 20,\n step: 0.5,\n unit: 'px',\n def: 0\n },\n brightness: {\n min: 0,\n max: 200,\n step: 1,\n unit: '%',\n def: 100\n },\n contrast: {\n min: 0,\n max: 200,\n step: 1,\n unit: '%',\n def: 100\n },\n saturate: {\n min: 0,\n max: 200,\n step: 1,\n unit: '%',\n def: 100\n },\n grayscale: {\n min: 0,\n max: 100,\n step: 1,\n unit: '%',\n def: 0\n }\n }[role];\n var v = s.filter[role];\n var pct = (v - cfg.min) / (cfg.max - cfg.min) * 100;\n return \"\\n <div class=\\\"bbg-row\\\">\\n <label class=\\\"bbg-row-label\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.filter_' + role), \"</label>\\n <div class=\\\"bbg-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"filter-\").concat(role, \"\\\"\\n min=\\\"\").concat(cfg.min, \"\\\" max=\\\"\").concat(cfg.max, \"\\\" step=\\\"\").concat(cfg.step, \"\\\" value=\\\"\").concat(v, \"\\\"\\n style=\\\"--pct:\").concat(pct, \"%\\\">\\n </div>\\n <div class=\\\"bbg-value-wrap\\\">\\n <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"filter-\").concat(role, \"-num\\\"\\n min=\\\"\").concat(cfg.min, \"\\\" max=\\\"\").concat(cfg.max, \"\\\" step=\\\"\").concat(cfg.step, \"\\\" value=\\\"\").concat(v, \"\\\">\\n <span class=\\\"bbg-unit\\\">\").concat(cfg.unit, \"</span>\\n </div>\\n </div>\");\n }\n }, {\n key: \"_mountColorPicker\",\n value: function _mountColorPicker() {\n var _this3 = this;\n var host = this.domNode.querySelector(\"#bbgColorHost_\".concat(this.id));\n if (!host) return;\n this.colorPicker = new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.color'), this.state.color, function (newColor) {\n _this3.state.color = newColor || '';\n _this3._emit();\n });\n host.appendChild(this.colorPicker.domNode);\n }\n\n // -------------------- listeners --------------------\n }, {\n key: \"_attachListeners\",\n value: function _attachListeners() {\n var _this4 = this;\n var root = this.domNode;\n var q = function q(sel) {\n return root.querySelector(sel);\n };\n var qa = function qa(sel) {\n return root.querySelectorAll(sel);\n };\n\n // --- Image actions ---\n var uploadBtn = q('[data-action=\"upload\"]');\n if (uploadBtn) uploadBtn.addEventListener('click', function () {\n return _this4._promptFileUpload();\n });\n var pasteBtn = q('[data-action=\"paste-url\"]');\n if (pasteBtn) pasteBtn.addEventListener('click', function () {\n return _this4._toggleUrlRow();\n });\n var removeBtn = q('[data-action=\"remove\"]');\n if (removeBtn) removeBtn.addEventListener('click', function () {\n return _this4._removeImage();\n });\n var urlInput = q('[data-role=\"url\"]');\n if (urlInput) {\n var t = null;\n urlInput.addEventListener('input', function (e) {\n _this4.state.image = e.target.value;\n clearTimeout(t);\n t = setTimeout(function () {\n _this4._softRefreshImage();\n _this4._emit();\n }, 300);\n });\n urlInput.addEventListener('blur', function () {\n _this4._softRefreshImage();\n _this4._emit();\n });\n }\n\n // --- Preview drag + wheel ---\n this._wirePreviewDrag();\n\n // --- Size chips ---\n qa('[data-role=\"size-chips\"] .bbg-chip').forEach(function (chip) {\n chip.addEventListener('click', function () {\n var mode = chip.dataset.sizeMode;\n if (mode === 'custom') {\n _this4.state.sizeMode = 'custom';\n _this4.state.sizePct = parseInt(chip.dataset.sizePct, 10) || 100;\n } else {\n _this4.state.sizeMode = mode;\n }\n _this4._refreshPreview();\n _this4._refreshSizeUi();\n _this4._emit();\n });\n });\n\n // --- Size slider ---\n this._wireSliderRow('sizePct', function (v) {\n _this4.state.sizeMode = 'custom';\n _this4.state.sizePct = Math.round(v);\n _this4._refreshPreview();\n _this4._refreshSizeChipsActive();\n });\n\n // --- Focus sliders ---\n this._wireSliderRow('posX', function (v) {\n _this4.state.posX = Math.round(v);\n _this4._refreshPreview();\n });\n this._wireSliderRow('posY', function (v) {\n _this4.state.posY = Math.round(v);\n _this4._refreshPreview();\n });\n\n // --- Repeat chips ---\n qa('[data-role=\"repeat-chips\"] .bbg-chip').forEach(function (chip) {\n chip.addEventListener('click', function () {\n _this4.state.repeat = chip.dataset.repeat;\n qa('[data-role=\"repeat-chips\"] .bbg-chip').forEach(function (c) {\n return c.classList.toggle('is-active', c === chip);\n });\n _this4._refreshPreview();\n _this4._emit();\n });\n });\n\n // --- Gradient toggle ---\n var gToggle = q('[data-role=\"gradient-toggle\"]');\n if (gToggle) gToggle.addEventListener('change', function (e) {\n _this4.state.gradient.enabled = e.target.checked;\n _this4._refreshGradientBodyVisibility();\n _this4._emit();\n });\n\n // --- Gradient type chips ---\n qa('[data-role=\"gradient-type-chips\"] .bbg-chip').forEach(function (chip) {\n chip.addEventListener('click', function () {\n _this4.state.gradient.type = chip.dataset.gtype;\n qa('[data-role=\"gradient-type-chips\"] .bbg-chip').forEach(function (c) {\n return c.classList.toggle('is-active', c === chip);\n });\n _this4._refreshGradientPreview();\n _this4._refreshGradientAngleRowMuted();\n _this4._emit();\n });\n });\n\n // --- Gradient angle slider ---\n this._wireSliderRow('gradient-angle', function (v) {\n _this4.state.gradient.angle = Math.round(v);\n _this4._refreshGradientPreview();\n });\n\n // --- Gradient color swatches + hex ---\n ['color1', 'color2'].forEach(function (which) {\n var swatch = q(\"[data-role=\\\"gradient-\".concat(which, \"\\\"]\"));\n var hex = q(\"[data-role=\\\"gradient-\".concat(which, \"-hex\\\"]\"));\n var stopNum = q(\"[data-role=\\\"gradient-stop\".concat(which === 'color1' ? '1' : '2', \"\\\"]\"));\n if (swatch) swatch.addEventListener('input', function (e) {\n var v = e.target.value;\n _this4.state.gradient[which] = v;\n if (hex) hex.value = v;\n swatch.parentElement.querySelector('.bbg-swatch').style.background = v;\n _this4._refreshGradientPreview();\n _this4._emit();\n });\n if (hex) {\n var commit = function commit() {\n var v = (hex.value || '').trim();\n if (/^#?[0-9a-f]{3,8}$/i.test(v)) {\n var normalized = v.startsWith('#') ? v : '#' + v;\n _this4.state.gradient[which] = normalized;\n hex.value = normalized;\n if (swatch) swatch.value = normalized;\n swatch.parentElement.querySelector('.bbg-swatch').style.background = normalized;\n hex.classList.remove('is-invalid');\n _this4._refreshGradientPreview();\n _this4._emit();\n } else if (v !== '') {\n hex.classList.add('is-invalid');\n }\n };\n hex.addEventListener('blur', commit);\n hex.addEventListener('keydown', function (e) {\n if (e.key === 'Enter') {\n e.preventDefault();\n commit();\n }\n });\n }\n if (stopNum) {\n stopNum.addEventListener('input', function (e) {\n var v = parseInt(e.target.value, 10);\n if (!Number.isFinite(v)) return;\n var key = which === 'color1' ? 'stop1' : 'stop2';\n _this4.state.gradient[key] = Math.max(0, Math.min(100, v));\n _this4._refreshGradientPreview();\n _this4._emit();\n });\n }\n });\n\n // --- Gradient presets ---\n qa('[data-role=\"gradient-preset-grid\"] .bbg-preset-chip').forEach(function (chip) {\n chip.addEventListener('click', function () {\n var c1 = chip.dataset.gc1;\n var c2 = chip.dataset.gc2;\n var angle = parseInt(chip.dataset.gangle, 10);\n _this4.state.gradient.color1 = c1;\n _this4.state.gradient.color2 = c2;\n _this4.state.gradient.angle = Number.isFinite(angle) ? angle : 180;\n _this4.state.gradient.stop1 = 0;\n _this4.state.gradient.stop2 = 100;\n _this4.state.gradient.enabled = true;\n _this4.render();\n _this4._emit();\n });\n });\n\n // --- Opacity ---\n this._wireSliderRow('opacity', function (v) {\n _this4.state.opacity = Math.round(v);\n _this4._refreshEffectsActivePill();\n });\n\n // --- Blend mode ---\n var blend = q('[data-role=\"blendMode\"]');\n if (blend) blend.addEventListener('change', function (e) {\n _this4.state.blendMode = e.target.value;\n _this4._refreshEffectsActivePill();\n _this4._emit();\n });\n\n // --- Filter sliders ---\n ['blur', 'brightness', 'contrast', 'saturate', 'grayscale'].forEach(function (key) {\n _this4._wireSliderRow('filter-' + key, function (v) {\n _this4.state.filter[key] = key === 'blur' ? Math.round(v * 10) / 10 : Math.round(v);\n _this4._refreshEffectsActivePill();\n });\n });\n\n // --- Reset buttons ---\n var resetEffects = q('[data-action=\"reset-effects\"]');\n if (resetEffects) resetEffects.addEventListener('click', function () {\n _this4.state.opacity = 100;\n _this4.state.blendMode = 'normal';\n _this4.state.filter = _this4._normalizeFilter();\n _this4.render();\n _this4._emit();\n });\n var resetAll = q('[data-action=\"reset-all\"]');\n if (resetAll) resetAll.addEventListener('click', function () {\n var keepColor = _this4.state.color;\n _this4.state = _this4._normalizeIn({\n color: keepColor\n });\n _this4.render();\n _this4._emit();\n });\n }\n }, {\n key: \"_wireSliderRow\",\n value: function _wireSliderRow(role, onChange) {\n var _this5 = this;\n var slider = this.domNode.querySelector(\"[data-role=\\\"\".concat(role, \"\\\"]\"));\n var numInput = this.domNode.querySelector(\"[data-role=\\\"\".concat(role, \"-num\\\"]\"));\n if (!slider || !numInput) return;\n var min = parseFloat(slider.min);\n var max = parseFloat(slider.max);\n var syncPct = function syncPct() {\n var pct = (parseFloat(slider.value) - min) / (max - min) * 100;\n slider.style.setProperty('--pct', pct + '%');\n };\n var debounce = null;\n slider.addEventListener('input', function (e) {\n var v = parseFloat(e.target.value);\n numInput.value = v;\n onChange(v);\n syncPct();\n clearTimeout(debounce);\n debounce = setTimeout(function () {\n return _this5._emit();\n }, 80);\n });\n numInput.addEventListener('input', function (e) {\n var v = parseFloat(e.target.value);\n if (!Number.isFinite(v)) return;\n var clamped = Math.max(min, Math.min(max, v));\n slider.value = clamped;\n onChange(clamped);\n syncPct();\n clearTimeout(debounce);\n debounce = setTimeout(function () {\n return _this5._emit();\n }, 150);\n });\n numInput.addEventListener('blur', function (e) {\n var v = parseFloat(e.target.value);\n if (!Number.isFinite(v)) v = parseFloat(slider.value);\n v = Math.max(min, Math.min(max, v));\n slider.value = v;\n numInput.value = v;\n onChange(v);\n syncPct();\n _this5._emit();\n });\n }\n }, {\n key: \"_wirePreviewDrag\",\n value: function _wirePreviewDrag() {\n var _this6 = this;\n var preview = this.domNode.querySelector('[data-role=\"preview\"]');\n if (!preview || !this.state.image) return;\n var move = function move(clientX, clientY) {\n var rect = preview.getBoundingClientRect();\n var x = Math.max(0, Math.min(100, (clientX - rect.left) / rect.width * 100));\n var y = Math.max(0, Math.min(100, (clientY - rect.top) / rect.height * 100));\n _this6.state.posX = Math.round(x);\n _this6.state.posY = Math.round(y);\n _this6._syncSlider('posX');\n _this6._syncSlider('posY');\n _this6._refreshPreview();\n };\n var onDown = function onDown(e) {\n e.preventDefault();\n _this6._dragging = true;\n preview.classList.add('is-dragging');\n var ev = e.touches ? e.touches[0] : e;\n move(ev.clientX, ev.clientY);\n };\n var onMove = function onMove(e) {\n if (!_this6._dragging) return;\n var ev = e.touches ? e.touches[0] : e;\n move(ev.clientX, ev.clientY);\n };\n var onUp = function onUp() {\n if (!_this6._dragging) return;\n _this6._dragging = false;\n preview.classList.remove('is-dragging');\n _this6._emit();\n };\n preview.addEventListener('mousedown', onDown);\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', onUp);\n preview.addEventListener('touchstart', onDown, {\n passive: false\n });\n window.addEventListener('touchmove', onMove, {\n passive: false\n });\n window.addEventListener('touchend', onUp);\n\n // Wheel zoom → adjust sizePct\n preview.addEventListener('wheel', function (e) {\n e.preventDefault();\n var delta = e.deltaY > 0 ? -10 : 10;\n var next = Math.max(10, Math.min(400, _this6.state.sizePct + delta));\n _this6.state.sizeMode = 'custom';\n _this6.state.sizePct = next;\n _this6._syncSlider('sizePct');\n _this6._refreshSizeChipsActive();\n _this6._refreshPreview();\n _this6._emit();\n }, {\n passive: false\n });\n }\n }, {\n key: \"_syncSlider\",\n value: function _syncSlider(role) {\n var slider = this.domNode.querySelector(\"[data-role=\\\"\".concat(role, \"\\\"]\"));\n var numInput = this.domNode.querySelector(\"[data-role=\\\"\".concat(role, \"-num\\\"]\"));\n var v = role === 'sizePct' ? this.state.sizePct : this.state[role];\n if (slider) {\n slider.value = v;\n var min = parseFloat(slider.min);\n var max = parseFloat(slider.max);\n slider.style.setProperty('--pct', (v - min) / (max - min) * 100 + '%');\n }\n if (numInput) numInput.value = Math.round(v);\n }\n\n // -------------------- structure-preserving refreshes --------------------\n }, {\n key: \"_refreshPreview\",\n value: function _refreshPreview() {\n var preview = this.domNode.querySelector('[data-role=\"preview\"]');\n var previewImg = this.resolveImageUrl(this.state.image);\n if (!preview) return;\n preview.setAttribute('style', this._previewStyle(previewImg));\n var dot = preview.querySelector('.bbg-focus-dot');\n if (dot) {\n dot.style.left = this.state.posX + '%';\n dot.style.top = this.state.posY + '%';\n }\n }\n }, {\n key: \"_refreshSizeUi\",\n value: function _refreshSizeUi() {\n this._refreshSizeChipsActive();\n var custom = this.domNode.querySelector('[data-role=\"size-custom\"]');\n if (custom) custom.classList.toggle('is-muted', this.state.sizeMode !== 'custom');\n this._syncSlider('sizePct');\n }\n }, {\n key: \"_refreshSizeChipsActive\",\n value: function _refreshSizeChipsActive() {\n var _this7 = this;\n this.domNode.querySelectorAll('[data-role=\"size-chips\"] .bbg-chip').forEach(function (c) {\n var mode = c.dataset.sizeMode;\n var pct = parseInt(c.dataset.sizePct, 10);\n var isActive = mode === 'custom' ? _this7.state.sizeMode === 'custom' && _this7.state.sizePct === pct : _this7.state.sizeMode === mode;\n c.classList.toggle('is-active', !!isActive);\n });\n }\n }, {\n key: \"_refreshGradientPreview\",\n value: function _refreshGradientPreview() {\n var box = this.domNode.querySelector('[data-role=\"gradient-preview\"]');\n if (box) box.style.background = this._gradientCss();\n }\n }, {\n key: \"_refreshGradientBodyVisibility\",\n value: function _refreshGradientBodyVisibility() {\n var body = this.domNode.querySelector('[data-role=\"gradient-body\"]');\n if (body) {\n if (this.state.gradient.enabled) body.removeAttribute('hidden');else body.setAttribute('hidden', '');\n }\n }\n }, {\n key: \"_refreshGradientAngleRowMuted\",\n value: function _refreshGradientAngleRowMuted() {\n var row = this.domNode.querySelector('[data-role=\"gradient-angle-row\"]');\n if (row) row.classList.toggle('is-muted', this.state.gradient.type !== 'linear');\n }\n }, {\n key: \"_refreshEffectsActivePill\",\n value: function _refreshEffectsActivePill() {\n var head = this.domNode.querySelector('[data-section=\"effects\"] .bbg-section-head');\n if (!head) return;\n var existing = head.querySelector('.bbg-active-pill');\n var active = this.state.opacity !== 100 || this.state.blendMode !== 'normal' || this._composeFilter() !== '';\n if (active && !existing) {\n var span = document.createElement('span');\n span.className = 'bbg-active-pill';\n span.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.active');\n head.appendChild(span);\n } else if (!active && existing) {\n existing.remove();\n }\n }\n\n // -------------------- image handlers --------------------\n }, {\n key: \"_promptFileUpload\",\n value: function _promptFileUpload() {\n var _this8 = this;\n var input = document.createElement('input');\n input.type = 'file';\n input.accept = 'image/*';\n input.addEventListener('change', function (e) {\n var f = e.target.files && e.target.files[0];\n if (!f) return;\n var reader = new FileReader();\n reader.onload = function () {\n _this8.state.image = reader.result;\n _this8.render();\n _this8._emit();\n };\n reader.onerror = function () {\n _this8._showImageError(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.image_read_failed'));\n };\n reader.readAsDataURL(f);\n });\n input.click();\n }\n }, {\n key: \"_toggleUrlRow\",\n value: function _toggleUrlRow() {\n var row = this.domNode.querySelector('[data-role=\"url-row\"]');\n if (!row) return;\n this._urlRowVisible = !row.classList.contains('is-open');\n row.classList.toggle('is-open', this._urlRowVisible);\n row.classList.toggle('is-hidden', !this._urlRowVisible);\n if (this._urlRowVisible) {\n var input = row.querySelector('input');\n if (input) input.focus();\n }\n }\n }, {\n key: \"_removeImage\",\n value: function _removeImage() {\n this.state.image = '';\n this.state.posX = 50;\n this.state.posY = 50;\n this.render();\n this._emit();\n }\n }, {\n key: \"_softRefreshImage\",\n value: function _softRefreshImage() {\n // Re-render the image section without destroying focus on the URL input.\n // We update the preview background in-place + update info row.\n var previewWrap = this.domNode.querySelector('[data-role=\"preview-wrap\"]');\n var preview = this.domNode.querySelector('[data-role=\"preview\"]');\n var subs = this.domNode.querySelectorAll('.bbg-section[data-section=\"image\"] .bbg-sub');\n var removeBtn = this.domNode.querySelector('[data-action=\"remove\"]');\n var hasImage = !!this.state.image;\n if (previewWrap) previewWrap.classList.toggle('is-empty', !hasImage);\n if (preview) preview.setAttribute('style', this._previewStyle(this.resolveImageUrl(this.state.image)));\n subs.forEach(function (sub) {\n if (hasImage) sub.removeAttribute('hidden');else sub.setAttribute('hidden', '');\n });\n if (removeBtn) {\n removeBtn.disabled = !hasImage;\n removeBtn.classList.toggle('is-disabled', !hasImage);\n }\n\n // If preview switched from empty → populated (or vice versa), the inner\n // layout differs (empty hint vs focus dot + grid; info-text content also\n // flips between static empty hint and dynamic filename/meta). Full\n // re-render is required in that case; otherwise stay in-place.\n if (preview) {\n var hasDot = preview.querySelector('.bbg-focus-dot');\n if (hasImage && !hasDot) this.render();else if (!hasImage && hasDot) this.render();\n }\n if (hasImage) this._updateImageMeta(this.resolveImageUrl(this.state.image));\n }\n }, {\n key: \"_updateImageMeta\",\n value: function () {\n var _updateImageMeta2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(url) {\n var filename, meta, approxBytes, res, blob, img, objUrl, rawName, ext, dims, size;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n filename = this.domNode.querySelector('[data-role=\"filename\"]');\n meta = this.domNode.querySelector('[data-role=\"meta\"]');\n if (url) {\n _context.next = 4;\n break;\n }\n return _context.abrupt(\"return\");\n case 4:\n if (filename) filename.classList.remove('is-muted');\n if (!url.startsWith('data:')) {\n _context.next = 9;\n break;\n }\n if (filename) filename.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.embedded');\n if (meta) {\n approxBytes = Math.ceil((url.length - url.indexOf(',') - 1) * 0.75);\n meta.textContent = this._formatBytes(approxBytes);\n }\n return _context.abrupt(\"return\");\n case 9:\n _context.prev = 9;\n _context.next = 12;\n return fetch(url, {\n credentials: 'same-origin'\n });\n case 12:\n res = _context.sent;\n if (res.ok) {\n _context.next = 15;\n break;\n }\n throw new Error('Fetch failed: ' + res.status);\n case 15:\n _context.next = 17;\n return res.blob();\n case 17:\n blob = _context.sent;\n img = new Image();\n objUrl = URL.createObjectURL(blob);\n _context.next = 22;\n return new Promise(function (resolve, reject) {\n img.onload = resolve;\n img.onerror = function () {\n return reject(new Error('Invalid image'));\n };\n img.src = objUrl;\n });\n case 22:\n URL.revokeObjectURL(objUrl);\n rawName = (url.split('/').pop() || '').split('?')[0] || _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.no_image');\n ext = (rawName.split('.').pop() || '').toUpperCase();\n dims = \"\".concat(img.width, \"\\xD7\").concat(img.height);\n size = this._formatBytes(blob.size);\n if (filename) filename.textContent = decodeURIComponent(rawName);\n if (meta) meta.textContent = ext && ext.length <= 4 ? \"\".concat(dims, \" \\xB7 \").concat(ext, \" \\xB7 \").concat(size) : \"\".concat(dims, \" \\xB7 \").concat(size);\n _context.next = 35;\n break;\n case 31:\n _context.prev = 31;\n _context.t0 = _context[\"catch\"](9);\n if (filename) filename.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.invalid_image');\n if (meta) meta.textContent = _context.t0 && _context.t0.message || '';\n case 35:\n case \"end\":\n return _context.stop();\n }\n }, _callee, this, [[9, 31]]);\n }));\n function _updateImageMeta(_x) {\n return _updateImageMeta2.apply(this, arguments);\n }\n return _updateImageMeta;\n }()\n }, {\n key: \"_formatBytes\",\n value: function _formatBytes(bytes) {\n if (!bytes || bytes < 0) return '0 B';\n if (bytes < 1024) return \"\".concat(bytes, \" B\");\n if (bytes < 1024 * 1024) return \"\".concat((bytes / 1024).toFixed(1), \" kB\");\n return \"\".concat((bytes / (1024 * 1024)).toFixed(2), \" MB\");\n }\n }, {\n key: \"_showImageError\",\n value: function _showImageError(msg) {\n var info = this.domNode.querySelector('[data-role=\"image-info\"]');\n if (info) {\n info.removeAttribute('hidden');\n info.innerHTML = \"<span class=\\\"bbg-image-filename is-error\\\">\".concat(msg, \"</span>\");\n }\n }\n\n // -------------------- inline styles --------------------\n }, {\n key: \"_styles\",\n value: function _styles() {\n return \"\\n .bbg-root { font-family: inherit; }\\n .bbg-panel { display: flex; flex-direction: column; gap: 0; padding: 0; color: #111827; }\\n .bbg-header { padding: 12px 16px 4px; }\\n .bbg-title { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #374151; }\\n .bbg-desc { font-size: 11px; color: #6b7280; margin-top: 2px; }\\n\\n .bbg-section { padding: 10px 16px; border-top: 1px solid #f1f5f9; }\\n .bbg-section:first-of-type { border-top: 0; }\\n .bbg-section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; gap: 8px; }\\n .bbg-section-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: #374151; }\\n .bbg-sub { padding-top: 10px; margin-top: 10px; border-top: 1px dashed #eef2f7; }\\n .bbg-sub-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; margin-bottom: 6px; }\\n .bbg-sub-body { margin-top: 8px; }\\n\\n /* ColorPickerControl lives inside .bbg-section (which already has\\n padding: 10px 16px). Neutralise the nested .bjs-control-row's own\\n padding so the row aligns flush with the section's section-label. */\\n .bbg-color-host > * { padding: 0 !important; }\\n .bbg-color-host .bjs-control-row { padding: 0 !important; }\\n\\n /* Image hero \\u2014 2-column: large preview (~50%) | info + actions */\\n .bbg-image-hero { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: stretch; }\\n .bbg-preview-wrap { position: relative; min-width: 0; }\\n .bbg-preview { position: relative; width: 100%; aspect-ratio: 4/3; border-radius: 8px; overflow: hidden;\\n border: 1px solid #e5e7eb; cursor: crosshair; user-select: none; touch-action: none; transition: border-color .15s ease;\\n background-color: #f9fafb; }\\n .bbg-preview:hover { border-color: #cbd5e1; }\\n .bbg-preview.is-dragging { border-color: #3b82f6; cursor: grabbing; }\\n .bbg-preview-wrap.is-empty .bbg-preview { cursor: default; background-image: linear-gradient(45deg, #f1f5f9 25%, transparent 25%), linear-gradient(-45deg, #f1f5f9 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #f1f5f9 75%), linear-gradient(-45deg, transparent 75%, #f1f5f9 75%); background-size: 12px 12px; background-position: 0 0, 0 6px, 6px -6px, -6px 0; }\\n .bbg-empty-hint { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #94a3b8; pointer-events: none; }\\n .bbg-focus-dot { position: absolute; width: 16px; height: 16px; border-radius: 50%; background: #fff; border: 3px solid #3b82f6;\\n transform: translate(-50%, -50%); box-shadow: 0 2px 6px rgba(0,0,0,.25); pointer-events: none; transition: left .02s linear, top .02s linear; }\\n .bbg-grid { position: absolute; inset: 0; pointer-events: none; }\\n .bbg-grid span { position: absolute; background: rgba(255,255,255,.5); }\\n .bbg-grid span:nth-child(1) { left: 33.333%; top: 0; width: 1px; height: 100%; }\\n .bbg-grid span:nth-child(2) { left: 66.666%; top: 0; width: 1px; height: 100%; }\\n .bbg-grid span:nth-child(3) { top: 33.333%; left: 0; height: 1px; width: 100%; }\\n .bbg-grid span:nth-child(4) { top: 66.666%; left: 0; height: 1px; width: 100%; }\\n\\n /* Side column: info on top, actions on bottom */\\n .bbg-image-side { display: flex; flex-direction: column; justify-content: space-between; gap: 8px; min-width: 0; }\\n\\n /* Image info \\u2014 inline, no background panel; stacks filename + meta */\\n .bbg-image-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }\\n .bbg-image-filename { color: #111827; font-weight: 600; font-size: 12px; line-height: 1.3;\\n display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-all; }\\n .bbg-image-filename.is-muted { color: #6b7280; font-weight: 500; }\\n .bbg-image-filename.is-error { color: #dc2626; }\\n .bbg-image-meta { color: #6b7280; font-family: ui-monospace, SFMono-Regular, Monaco, monospace; font-size: 10.5px; line-height: 1.3;\\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n\\n /* Image actions \\u2014 icon-only square buttons (labels would crowd the 50%\\n right column; aria-label + title tooltips carry the text). */\\n .bbg-image-actions { display: flex; gap: 6px; }\\n .bbg-action-btn { flex: 1; display: inline-flex; align-items: center; justify-content: center;\\n height: 32px; border: 1px solid #e5e7eb; background: #fff; border-radius: 6px;\\n color: #374151; cursor: pointer; transition: all .15s ease; }\\n .bbg-action-btn:hover:not(:disabled) { border-color: #cbd5e1; background: #f9fafb; color: #111827; }\\n .bbg-action-btn:disabled, .bbg-action-btn.is-disabled { opacity: .45; cursor: not-allowed; }\\n .bbg-action-btn--danger:hover:not(:disabled) { color: #dc2626; border-color: #fecaca; background: #fef2f2; }\\n\\n /* URL row */\\n .bbg-url-row { overflow: hidden; transition: max-height .18s ease, margin-top .18s ease, opacity .18s ease; }\\n .bbg-url-row.is-hidden { max-height: 0; margin-top: 0; opacity: 0; }\\n .bbg-url-row.is-open { max-height: 60px; margin-top: 8px; opacity: 1; }\\n .bbg-url-input { width: 100%; padding: 7px 10px; border: 1px solid #e5e7eb; border-radius: 6px; font-size: 12px;\\n background: #fff; color: #111827; transition: border-color .15s ease; }\\n .bbg-url-input:focus { outline: 0; border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,.1); }\\n\\n /* Chips */\\n .bbg-chips { display: flex; flex-wrap: wrap; gap: 5px; }\\n .bbg-chip { padding: 6px 10px; border: 1px solid #e5e7eb; background: #fff; border-radius: 5px; font-size: 11px; font-weight: 500;\\n color: #374151; cursor: pointer; transition: all .15s ease; white-space: nowrap; line-height: 1.2; }\\n .bbg-chip:hover { border-color: #cbd5e1; background: #f9fafb; }\\n .bbg-chip.is-active { background: #111827; border-color: #111827; color: #fff; }\\n .bbg-chip--icon { display: inline-flex; align-items: center; gap: 5px; }\\n .bbg-chip--icon svg { opacity: .7; }\\n .bbg-chip.is-active svg { opacity: 1; }\\n\\n /* Rows (slider + numeric input) */\\n .bbg-row { display: grid; grid-template-columns: 70px 1fr 72px; align-items: center; gap: 8px; padding: 5px 0; }\\n .bbg-row.is-muted { opacity: .4; pointer-events: none; }\\n .bbg-row-label { font-size: 11px; color: #4b5563; font-weight: 500; }\\n .bbg-slider-wrap { position: relative; padding: 0 2px; }\\n .bbg-slider { width: 100%; height: 4px; border-radius: 2px; appearance: none; -webkit-appearance: none; cursor: pointer;\\n background: linear-gradient(to right, #111827 0%, #111827 var(--pct, 0%), #e5e7eb var(--pct, 0%), #e5e7eb 100%); }\\n .bbg-slider::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%;\\n background: #fff; border: 2px solid #111827; cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,.15); transition: transform .1s ease; }\\n .bbg-slider::-webkit-slider-thumb:hover { transform: scale(1.15); }\\n .bbg-slider::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: #fff; border: 2px solid #111827;\\n cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,.15); }\\n .bbg-value-wrap { display: flex; align-items: center; gap: 2px; padding: 4px 6px; border: 1px solid #e5e7eb; border-radius: 5px;\\n background: #fff; transition: border-color .15s ease; }\\n .bbg-value-wrap:focus-within { border-color: #3b82f6; }\\n .bbg-value-input { width: 100%; border: 0; outline: 0; background: transparent; font-size: 11px; color: #111827; padding: 0;\\n text-align: right; font-variant-numeric: tabular-nums; }\\n .bbg-value-input::-webkit-inner-spin-button, .bbg-value-input::-webkit-outer-spin-button { appearance: none; -webkit-appearance: none; margin: 0; }\\n .bbg-value-input--mini { width: 40px; }\\n .bbg-unit { font-size: 10px; color: #9ca3af; user-select: none; }\\n\\n /* Select */\\n .bbg-select { width: 100%; padding: 6px 10px; border: 1px solid #e5e7eb; border-radius: 5px; font-size: 11px; background: #fff;\\n color: #111827; cursor: pointer; appearance: none; -webkit-appearance: none;\\n background-image: url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236b7280' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E\\\");\\n background-repeat: no-repeat; background-position: right 10px center; padding-right: 26px; }\\n .bbg-select:focus { outline: 0; border-color: #3b82f6; }\\n\\n /* Toggle */\\n .bbg-toggle { position: relative; display: inline-block; width: 32px; height: 18px; cursor: pointer; flex-shrink: 0; }\\n .bbg-toggle-input { opacity: 0; width: 0; height: 0; position: absolute; }\\n .bbg-toggle-slider { position: absolute; inset: 0; background: #e5e7eb; border-radius: 10px; transition: background .15s ease; }\\n .bbg-toggle-slider::before { content: ''; position: absolute; width: 14px; height: 14px; left: 2px; top: 2px;\\n background: #fff; border-radius: 50%; transition: transform .15s ease; box-shadow: 0 1px 3px rgba(0,0,0,.2); }\\n .bbg-toggle-input:checked + .bbg-toggle-slider { background: #111827; }\\n .bbg-toggle-input:checked + .bbg-toggle-slider::before { transform: translateX(14px); }\\n\\n /* Gradient */\\n .bbg-gradient-preview { width: 100%; aspect-ratio: 8/1; min-height: 32px; border-radius: 6px; margin-bottom: 10px;\\n border: 1px solid #e5e7eb; }\\n .bbg-gradient-stops { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }\\n .bbg-gradient-stop { display: flex; flex-direction: column; gap: 4px; }\\n .bbg-stop-label { font-size: 10px; color: #6b7280; text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }\\n .bbg-stop-row { display: flex; align-items: center; gap: 6px; }\\n .bbg-swatch-wrap { position: relative; width: 28px; height: 28px; border-radius: 5px; border: 1px solid #e5e7eb; overflow: hidden;\\n cursor: pointer; flex-shrink: 0; }\\n .bbg-swatch-input { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; padding: 0; border: 0; }\\n .bbg-swatch { position: absolute; inset: 0; }\\n .bbg-hex-input { flex: 1; min-width: 0; padding: 5px 8px; border: 1px solid #e5e7eb; border-radius: 5px; font-size: 11px;\\n font-family: ui-monospace, SFMono-Regular, Monaco, monospace; background: #fff; color: #111827;\\n text-transform: lowercase; transition: border-color .15s ease; }\\n .bbg-hex-input:focus { outline: 0; border-color: #3b82f6; }\\n .bbg-hex-input.is-invalid { border-color: #dc2626; background: #fef2f2; }\\n\\n .bbg-gradient-presets { margin-top: 12px; }\\n .bbg-preset-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 4px; }\\n .bbg-preset-chip { aspect-ratio: 1; border: 1px solid #e5e7eb; border-radius: 5px; cursor: pointer; padding: 0;\\n transition: transform .1s ease, border-color .15s ease; }\\n .bbg-preset-chip:hover { transform: scale(1.08); border-color: #cbd5e1; }\\n\\n /* Effects */\\n .bbg-info { display: flex; align-items: flex-start; gap: 6px; padding: 8px 10px; background: #fffbeb; border: 1px solid #fef3c7;\\n border-radius: 6px; margin-bottom: 10px; color: #92400e; font-size: 10px; line-height: 1.4; }\\n .bbg-info-icon { flex-shrink: 0; margin-top: 1px; display: inline-flex; }\\n .bbg-active-pill { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;\\n padding: 2px 6px; background: #dcfce7; color: #166534; border-radius: 3px; }\\n\\n .bbg-actions { display: flex; justify-content: flex-end; margin-top: 8px; }\\n .bbg-text-btn { background: transparent; border: 0; color: #6b7280; font-size: 11px; cursor: pointer; padding: 4px 6px;\\n border-radius: 4px; transition: all .15s ease; }\\n .bbg-text-btn:hover { color: #111827; background: #f3f4f6; }\\n\\n /* Footer */\\n .bbg-footer { padding: 10px 16px; border-top: 1px solid #f1f5f9; display: flex; justify-content: flex-end; }\\n .bbg-reset-all { display: inline-flex; align-items: center; gap: 4px; padding: 5px 10px; background: transparent;\\n border: 1px solid #e5e7eb; border-radius: 5px; font-size: 11px; color: #6b7280; cursor: pointer; transition: all .15s ease; }\\n .bbg-reset-all:hover { color: #dc2626; border-color: #fecaca; background: #fef2f2; }\\n\\n /* Dark theme inherits via iframe body; use data-theme if host provides it */\\n :host-context([data-theme=\\\"dark\\\"]) .bbg-title,\\n [data-theme=\\\"dark\\\"] .bbg-root .bbg-title { color: #e5e7eb; }\\n \";\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BackgroundControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BackgroundControl.js?");
/***/ }),
/***/ "./src/includes/BaseControl.js":
/*!*************************************!*\
!*** ./src/includes/BaseControl.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * BaseControl — base class for sidebar Controls (Phase 1.8 — SA I14).\n *\n * Historically BuilderJS controls were plain classes with no shared base —\n * each author invented its own lifecycle. That was fine at low volume but\n * broke down once dual-view controls (overlay + sidebar editing the same\n * state) needed to subscribe to element state changes. Subscriptions leak\n * unless every Control reliably tears them down when the sidebar rebuilds.\n *\n * BaseControl introduces a single `destroy()` lifecycle hook.\n * `Builder.renderElementControls` calls `destroy()` on every outgoing control\n * before building the new sidebar, so any disposer stashed via\n * `this._disposers.push(fn)` runs automatically.\n *\n * Not every Control must extend BaseControl — plain (stateless) controls\n * don't need a destroy hook, and Builder.renderElementControls guards the\n * destroy call with `typeof ctrl.destroy === 'function'`. But EVERY Control\n * that subscribes to element state (via addSyncListener) MUST extend\n * BaseControl OR implement destroy() themselves.\n *\n * See docs/core/OVERLAY.md §14 · docs/core/CONTROL_DEFINITION.md · docs/archived/OVERLAY_HARDENING_PLAN.md Phase 1.8.\n */\nvar BaseControl = /*#__PURE__*/function () {\n function BaseControl() {\n _classCallCheck(this, BaseControl);\n // List of dispose fns to run on destroy — sync-listener removers,\n // DOM listener removers, observer disconnect, etc.\n this._disposers = [];\n this._destroyed = false;\n\n /**\n * Back-reference to the owning Builder. Set by\n * Builder.renderElementControls when this control is emitted by\n * an element's getControls(). NOT guaranteed inside the\n * constructor — defer host-dependent setup to afterRender() or\n * to event handlers. See BUILDER.md \"Host Injection\" lesson.\n */\n this.host = null;\n }\n\n /** Stash a dispose fn — will be called in destroy().\n * Returns the fn for caller convenience (so chained registration works). */\n return _createClass(BaseControl, [{\n key: \"addDisposer\",\n value: function addDisposer(fn) {\n if (typeof fn !== 'function') return fn;\n this._disposers.push(fn);\n return fn;\n }\n\n /** Control teardown — called by Builder.renderElementControls when the\n * sidebar rebuilds OR by explicit ownership code. Idempotent. */\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this._destroyed) return;\n this._destroyed = true;\n var list = this._disposers || [];\n this._disposers = [];\n var _iterator = _createForOfIteratorHelper(list),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var fn = _step.value;\n try {\n fn();\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(\"[bjs:control] \".concat(this.constructor.name, \".destroy disposer threw:\"), err);\n }\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n }\n\n /** Convenience — subscribe to element state-change notifications + auto\n * dispose on destroy. Shortcut for the 3-line pattern most controls use. */\n }, {\n key: \"bindSyncListener\",\n value: function bindSyncListener(element, name, fn) {\n if (!element || typeof element.addSyncListener !== 'function') return;\n this.addDisposer(element.addSyncListener(name, fn));\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BaseControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BaseControl.js?");
/***/ }),
/***/ "./src/includes/BaseElement.js":
/*!*************************************!*\
!*** ./src/includes/BaseElement.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BuilderjsPopup.js */ \"./src/includes/BuilderjsPopup.js\");\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\n/* harmony import */ var _ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ui/holedBoxClipPath.js */ \"./src/includes/ui/holedBoxClipPath.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n\n\nvar BaseElement = /*#__PURE__*/function () {\n function BaseElement() {\n _classCallCheck(this, BaseElement);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n\n /**\n * Back-reference to the owning Builder. Set by Builder._adopt() AFTER\n * parse, BEFORE render. Available in render(), afterMount(),\n * getControls(), event handlers.\n *\n * NOT guaranteed inside constructor or static parse() — code that\n * runs in those phases must defer to render()/afterMount() if it\n * needs host. See Lesson \"Host Injection\" in BUILDER.md.\n */\n this.host = null;\n this.formats = {\n background_color: null,\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n padding_top: 0,\n padding_right: 0,\n padding_bottom: 0,\n padding_left: 0,\n // size settings\n width: '560',\n height: '315'\n };\n // Canvas overlays — live BaseOverlay instances mounted via getOverlays().\n // Default `getOverlays()` returns [] so zero runtime work for every\n // element that doesn't opt in. See docs/core/OVERLAY.md + docs/archived/OVERLAY_PLAN.md.\n this.overlays = [];\n\n // Dual-view sync listeners (Phase 1.8 — SA invariant I13).\n // A Map<name, fn> so subscriptions are addressable by name (helpful for\n // debug logging) and so the same Control registering twice stomps\n // itself instead of double-firing. `_inSyncCascade` is a re-entrancy\n // lock: if a listener triggers element.render() (accident or bad code),\n // the nested notify chain is short-circuited and logged.\n // See docs/core/OVERLAY.md §13 and docs/archived/OVERLAY_HARDENING_PLAN.md Phase 1.8.\n this._syncListeners = new Map();\n this._inSyncCascade = false;\n\n // TEXT_INLINE_PLAN W0.2b — inline-edit registry. Subclass calls\n // `this.registerInlineEdit('text')` (or whatever property name)\n // in its constructor; BaseElement.afterRender() auto-wires the\n // contenteditable + marker + input listener on every render.\n this._inlineEditRegistry = new Map();\n }\n\n /* ─── Dual-View Sync Observer (Phase 1.8 — SA I13) ─────────────────────\n *\n * Usage — Control side:\n * constructor(label, value, callback) {\n * this._disposeSync = value.element.addSyncListener(\n * 'MyControl',\n * () => this.syncFromExternal()\n * );\n * }\n * destroy() {\n * if (this._disposeSync) this._disposeSync();\n * super.destroy();\n * }\n *\n * Usage — Element side:\n * render() {\n * // ... build DOM ...\n * this.notifySyncListeners(); // call LAST\n * return this.domNode;\n * }\n *\n * Invariants:\n * I13a. syncFn MUST be idempotent — render() may fire for reasons\n * unrelated to the state the Control cares about.\n * I13b. syncFn MUST NOT call element.render() (guarded anyway by the\n * re-entrancy lock, but the warning makes the mistake visible).\n * I13c. Disposer MUST be called on Control destroy — Builder.\n * renderElementControls auto-calls destroy() on outgoing controls\n * (SA I14). Forgetting leads to subscriptions that outlive the\n * Control instance → phantom DOM writes into orphaned panels.\n */\n\n /** Register a sync listener. Returns a disposer fn — call in Control destroy. */\n return _createClass(BaseElement, [{\n key: \"addSyncListener\",\n value: function addSyncListener(name, fn) {\n var _this = this;\n if (typeof fn !== 'function') throw new Error('addSyncListener: fn must be a function');\n this._syncListeners.set(name, fn);\n return function () {\n return _this.removeSyncListener(name);\n };\n }\n }, {\n key: \"removeSyncListener\",\n value: function removeSyncListener(name) {\n this._syncListeners[\"delete\"](name);\n }\n\n /** Debug helper — wrap a state object in a Proxy that WARNS when the\n * property is replaced (e.g. `element.crop = {...}` instead of\n * `Object.assign(element.crop, {...})`). Only active when\n * `window.__bjsDebug === true`; no-op in production.\n *\n * Usage in element constructor:\n * this.crop = this._debugStateObject('crop', { enabled: false, ... });\n *\n * Result in debug mode: setting `element.crop = {...}` directly fires\n * a loud console.warn pointing at the stack trace — catches reference\n * violations (SA I13 R1) at dev time instead of in production. */\n }, {\n key: \"_debugStateObject\",\n value: function _debugStateObject(fieldName, obj) {\n var _this2 = this;\n if (typeof window === 'undefined' || window.__bjsDebug !== true) return obj;\n // Intentionally hands back the raw object in prod. In debug, wrap a\n // setter trap on THIS that warns when the field is replaced.\n var klass = this.getClassName();\n var _wrap = function wrap() {\n Object.defineProperty(_this2, fieldName, {\n configurable: true,\n get: function get() {\n return obj;\n },\n set: function set(next) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].warn(\"state:replace\", \"\".concat(klass, \".\").concat(fieldName, \" was reassigned (should be mutated in place \") + \"via Object.assign \\u2014 SA I13 R1). Re-wrapping the new object.\", new Error().stack);\n obj = next;\n _wrap();\n }\n });\n };\n _wrap();\n return obj;\n }\n\n /** Fire every registered listener. Elements that opt into dual-view call\n * this at the END of their render(). Re-entrancy is guarded: if a listener\n * re-calls render() (which would re-enter this fn), the nested cascade is\n * skipped + logged. */\n }, {\n key: \"notifySyncListeners\",\n value: function notifySyncListeners() {\n if (!this._syncListeners || this._syncListeners.size === 0) return;\n if (this._inSyncCascade) {\n // Phase 1.9: use BJS.warn so the re-entrancy warning is on in all\n // environments (not gated by __bjsDebug). Re-entrancy is always a\n // bug worth surfacing, even in production.\n _BJS_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].warn(\"sync:reentrant\", \"\".concat(this.getClassName(), \" \\u2014 a sync listener called element.render(). \") + \"Skipping nested cascade. See docs/core/OVERLAY.md \\xA713 invariant I13b.\");\n return;\n }\n this._inSyncCascade = true;\n try {\n var _iterator = _createForOfIteratorHelper(this._syncListeners),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var _step$value = _slicedToArray(_step.value, 2),\n name = _step$value[0],\n fn = _step$value[1];\n try {\n fn(this);\n } catch (err) {\n // Phase 1.9 (SA I15) — listener throw is isolated; the\n // loop continues so other listeners still fire.\n _BJS_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].error(\"sync:listener \\\"\".concat(name, \"\\\" on \").concat(this.getClassName()), err);\n }\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n } finally {\n this._inSyncCascade = false;\n }\n }\n /* ───────────────────────────────────────────────────────────────────── */\n }, {\n key: \"getClassName\",\n value: function getClassName() {\n return this.constructor.name;\n }\n }, {\n key: \"getName\",\n value: function getName() {\n return this.getClassName();\n }\n\n /* ─── Render lifecycle (TEXT_INLINE_PLAN W0.2a — Template Method H1) ───\n *\n * BaseElement owns the outer render() lifecycle. Subclasses override\n * `_doRender()` (and optionally `afterRender()`) — they do NOT override\n * `render()` directly except for legitimate pre/post wrap scenarios\n * (e.g. PricingCardElement strips stale attrs before calling super.render()).\n *\n * Lifecycle:\n * render()\n * → _initDomNode() // idempotent scaffold (<div builder-element=\"...\">)\n * → _doRender() // subclass populates innerHTML / appends children\n * → afterRender() // base hook (W0.2b will wire inline-edit here)\n * → notifySyncListeners() // dual-view sync (auto-fires; subclass no longer calls)\n * → return this.domNode\n *\n * Why H1 Template Method (not super.render() / not monkey-patch):\n * — Single owner of lifecycle = single change point for future cross-cuts.\n * — Subclass override surface is the smallest possible (`_doRender`).\n * — Auto-fired notifySyncListeners prevents the 2024-style drift where\n * element-specific render() bodies forgot to call it.\n *\n * See docs/plans/TEXT_INLINE_PLAN.md §3 W0.2a + §10 decision #13.\n */\n }, {\n key: \"_initDomNode\",\n value: function _initDomNode() {\n if (this.domNode) return;\n this.domNode = document.createElement('div');\n this.domNode.setAttribute('builder-element', this.getClassName());\n }\n }, {\n key: \"render\",\n value: function render() {\n this._initDomNode();\n this._doRender();\n this.afterRender();\n this.notifySyncListeners();\n return this.domNode;\n }\n\n /** Subclass MUST override — populate this.domNode (innerHTML, children).\n * Default no-op + dev warning if a subclass forgot to migrate from the\n * pre-W0.2a `render()` pattern. Failure is visible (T6). */\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // eslint-disable-next-line no-console\n console.warn(\"[lifecycle] \".concat(this.getClassName(), \" did not override _doRender(). \") + \"Pre-W0.2a elements defined render() directly \\u2014 migrate the body to \" + \"_doRender(). See docs/core/ELEMENT_DEFINITION.md (render lifecycle).\");\n }\n\n /** Hook fired after _doRender() and before notifySyncListeners(). Wires\n * the inline-edit framework (W0.2b). Subclass overrides MUST call\n * super.afterRender() if they add their own logic. */\n }, {\n key: \"afterRender\",\n value: function afterRender() {\n this._wireInlineEdit();\n }\n /* ───────────────────────────────────────────────────────────────────── */\n\n /* ─── Inline-edit framework (TEXT_INLINE_PLAN W0.2b) ───────────────────\n *\n * Subclass opt-in: call `this.registerInlineEdit('text')` in the\n * constructor (AFTER `super()` AND AFTER `this.text = text` so Guard C's\n * `in this` check sees the property). On every render() the base will:\n *\n * 1. Scan `this.domNode` for `[inline-edit=\"<param>\"]` nodes (template-\n * authored).\n * 2. Cross-validate three sources of truth — registry ↔ template attr ↔\n * this[param] property — and throw with an actionable message on any\n * mismatch (Guard A / B / C). Failure is visible (HARD RULE T6).\n * 3. Wire `contenteditable=\"true\"`, stamp the\n * `data-bjs-inline-text=\"<this.id>\"` marker (consumed by W0.3 +\n * every W1-W6 selection-aware overlay), and add an `input` listener\n * that mirrors `node.innerHTML` back to `this[param]` and re-renders\n * sidebar controls.\n */\n\n /** Register a property name as inline-editable. Validates input + dedupes.\n * See `_wireInlineEdit()` for the lifecycle that consumes the registry. */\n }, {\n key: \"registerInlineEdit\",\n value: function registerInlineEdit(param) {\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n if (typeof param !== 'string' || param.length === 0) {\n throw new Error(\"\".concat(this.getClassName(), \".registerInlineEdit(param): \") + \"param must be a non-empty string. Got: \".concat(_typeof(param), \" \").concat(JSON.stringify(param)));\n }\n this._inlineEditRegistry.set(param, opts);\n }\n\n /** Backward-compat computed getter — some callers still read\n * `this.inlineEditParams` (CheckoutSimpleElement.inlineEditableAttributes()).\n * Returns the live keys of `_inlineEditRegistry`. Prefer `_inlineEditRegistry`\n * in new code. */\n }, {\n key: \"inlineEditParams\",\n get: function get() {\n return Array.from(this._inlineEditRegistry.keys());\n }\n\n /** Auto-fired from `afterRender()`. Iterates the registry, runs the 3-guard\n * validation, and wires the editable surfaces. No-op when registry is empty\n * (CheckoutElement / CheckoutSimpleElement / non-text elements). */\n }, {\n key: \"_wireInlineEdit\",\n value: function _wireInlineEdit() {\n var _this3 = this;\n if (!this._inlineEditRegistry || this._inlineEditRegistry.size === 0) return;\n if (!this.domNode) return;\n\n // Guard A — template attrs that have no matching registry entry.\n // Detects \"template says inline-edit='foo' but element never registered foo\".\n var templateNodes = this.domNode.querySelectorAll('[inline-edit]');\n var _iterator2 = _createForOfIteratorHelper(templateNodes),\n _step2;\n try {\n for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n var node = _step2.value;\n var attr = node.getAttribute('inline-edit');\n if (!this._inlineEditRegistry.has(attr)) {\n throw new Error(\"\".concat(this.getClassName(), \": template has [inline-edit=\\\"\").concat(attr, \"\\\"] \") + \"but the element never called registerInlineEdit(\\\"\".concat(attr, \"\\\"). \") + \"Fix: either remove the inline-edit attribute from the template, \" + \"or add 'this.registerInlineEdit(\\\"\".concat(attr, \"\\\")' to the constructor.\"));\n }\n }\n } catch (err) {\n _iterator2.e(err);\n } finally {\n _iterator2.f();\n }\n var _iterator3 = _createForOfIteratorHelper(this._inlineEditRegistry),\n _step3;\n try {\n var _loop = function _loop() {\n var _step3$value = _slicedToArray(_step3.value, 1),\n param = _step3$value[0];\n var node = _this3.domNode.querySelector(\"[inline-edit=\\\"\".concat(param, \"\\\"]\"));\n\n // Guard B — registry entry without a matching template node.\n if (!node) {\n throw new Error(\"\".concat(_this3.getClassName(), \": registerInlineEdit(\\\"\").concat(param, \"\\\") was called \") + \"but the template has no [inline-edit=\\\"\".concat(param, \"\\\"] node. \") + \"Fix: either add 'inline-edit=\\\"\".concat(param, \"\\\"' to the template, \") + \"or remove the registerInlineEdit(\\\"\".concat(param, \"\\\") call.\"));\n }\n\n // Guard C — registry entry whose property doesn't exist or is a method.\n // Methods can't be edited inline (innerHTML would clobber the function).\n if (!(param in _this3) || typeof _this3[param] === 'function') {\n throw new Error(\"\".concat(_this3.getClassName(), \": registerInlineEdit(\\\"\").concat(param, \"\\\") was called \") + \"but this.\".concat(param, \" does not exist or is a method. \") + \"Fix: ensure the constructor sets 'this.\".concat(param, \" = \\u2026' BEFORE \") + \"the registerInlineEdit call (Guard C requires the property to exist).\");\n }\n\n // Wire — contenteditable + marker + input listener.\n node.setAttribute('contenteditable', 'true');\n // W0.3 + every selection-aware overlay reads this marker to scope\n // selectionchange + intercept events to text-editing surfaces only.\n node.setAttribute('data-bjs-inline-text', _this3.id);\n node.addEventListener('input', function () {\n var _this3$host;\n // INLINE-EDIT INVARIANT (HARD RULE T11 — 2026-05-20):\n // - The inline-edit host (`<p>` / `<h*>`) MUST only contain\n // INLINE descendants (`<span>` / `<strong>` / `<em>` /\n // `<a>` / `<br>` / …). NO `<div>` / `<p>` / `<h*>` /\n // `<ul>` / etc. inside.\n // - HTML5 fragment parsing silently auto-closes the host\n // when it encounters a block-level child, so a `<div>`\n // left in `this.text` round-trips through the parser as\n // a SIBLING of the host on the next `innerHTML =` —\n // stripping the host's inline `style` from the visible\n // content. Customer-visible symptom: paragraph loses\n // font-weight + text-align after an unrelated\n // structural mutation (delete/add block).\n //\n // - Chrome's contenteditable default-paragraph-separator\n // is `'div'` — every Enter inserts a `<div>` block\n // child by default. Firefox/Safari behave similarly.\n // `Builder._setupIframe` calls\n // `iframeDoc.execCommand('defaultParagraphSeparator',\n // false, 'br')` to flip this to `<br>` (Chrome/FF), but\n // Safari ignores that flag — defence-in-depth requires\n // this DOM-level normalize too.\n //\n // Strategy: clone the host, run `InlineSanitizer.normalize`\n // (which unwraps every block-level descendant + canonicalises\n // `<b>→<strong>` + collapses empty spans), then capture the\n // CLONE's innerHTML into `this.text`. The LIVE host is NOT\n // mutated — touching the live DOM mid-keystroke would\n // disrupt the user's caret/range. The live state stays\n // visually intact (with `<div>` if Chrome inserted one);\n // the next `_doRender()` writes the sanitised text back,\n // which is when the user would see a visual hop if the\n // host had block children. In practice the host's\n // applyFormatStyles fast-path is used during edits and full\n // `_doRender` only fires from `parse()`/cascade re-renders\n // — by then `this.text` is already inline-clean.\n var captured;\n try {\n var clone = node.cloneNode(true);\n _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"].normalize(clone);\n captured = clone.innerHTML;\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].error('BaseElement:input-normalize', err);\n captured = node.innerHTML;\n }\n _this3[param] = captured;\n if (typeof ((_this3$host = _this3.host) === null || _this3$host === void 0 ? void 0 : _this3$host.renderElementControls) === 'function') {\n _this3.host.renderElementControls(_this3);\n }\n });\n // TEXT_INLINE_PLAN W2.2 / HARD RULE T9 — intercept native paste\n // (⌘V / Ctrl+V / right-click Paste) and route the clipboard\n // payload through `InlineSanitizer.sanitize({ mode })` BEFORE\n // the browser's default paste mutates the DOM. Without this,\n // Office / Google Docs / Outlook paste lands `mso-*` attrs +\n // block tags + `<font>` legacy markup directly inside the\n // inline-text host — violating T9 whitelist and breaking\n // round-trip invariants.\n //\n // ClipboardEvent.clipboardData is always accessible on a\n // NATIVE paste event (no permission prompt, no secure-context\n // requirement) — unlike the async `navigator.clipboard.read()`\n // API the W2.2 More menu's Paste items use. That makes ⌘V the\n // reliable paste path for users in restricted environments\n // (HTTP iframes, focus-sensitive contexts, unprivileged tabs).\n node.addEventListener('paste', function (e) {\n var cd = e.clipboardData || node.ownerDocument.defaultView && node.ownerDocument.defaultView.clipboardData;\n if (!cd) return; // allow default for environments without clipboardData (legacy IE etc.)\n var html = typeof cd.getData === 'function' ? cd.getData('text/html') : '';\n var text = typeof cd.getData === 'function' ? cd.getData('text/plain') : '';\n if (!html && !text) return; // files / images / empty — let default handle\n e.preventDefault();\n var mode = typeof _this3.getOutputMode === 'function' && _this3.getOutputMode() === 'email-safe' ? 'email-safe' : 'page';\n var toInsert;\n if (html) {\n toInsert = _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sanitize(html, {\n mode: mode\n });\n } else {\n // Plain text → escape HTML specials + convert newlines to <br>.\n toInsert = String(text).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''').replace(/\\r?\\n/g, '<br>');\n }\n if (!toInsert) return;\n try {\n node.ownerDocument.execCommand('insertHTML', false, toInsert);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].error('BaseElement:paste', err);\n }\n });\n };\n for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n _loop();\n }\n } catch (err) {\n _iterator3.e(err);\n } finally {\n _iterator3.f();\n }\n }\n /* ───────────────────────────────────────────────────────────────────── */\n }, {\n key: \"isHoverable\",\n value: function isHoverable() {\n return true;\n }\n }, {\n key: \"isDroppable\",\n value: function isDroppable() {\n return false;\n }\n }, {\n key: \"canDropInside\",\n value: function canDropInside() {\n return false;\n }\n }, {\n key: \"canDropBefore\",\n value: function canDropBefore() {\n return false;\n }\n }, {\n key: \"canDropAfter\",\n value: function canDropAfter() {\n return false;\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n return [\n // CheckboxControl\n new CheckboxControl(\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.optimized_mobile'),\n // descriptoin,\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.optimized_mobile_desc'),\n // value\n true,\n // callback — placeholder (overridden by element subclasses)\n {\n setValue: function setValue(value) {\n _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].alert({\n title: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.optimized_mobile'),\n message: String(value),\n kind: 'info'\n });\n }\n }),\n // CheckboxControl\n new CheckboxControl(\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.compat_mode'),\n // descriptoin,\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.compat_mode_desc'),\n // value\n true,\n // callback — placeholder (overridden by element subclasses)\n {\n setValue: function setValue(value) {\n _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].alert({\n title: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.compat_mode'),\n message: String(value),\n kind: 'info'\n });\n }\n })];\n }\n\n /* ─── Skeletons (TEXT_INLINE_PLAN W0.2c — A2 pure design) ─────────────\n *\n * Three centralizing helpers. Subclasses use `super.X()` to extend.\n *\n * W0.2c design decision (§7 discovery): chose A2 pure for renderTemplate —\n * reads `this.template` implicitly (element identity ↔ template = 1:1\n * invariant), returns html string with NO side effect (subclass writes\n * innerHTML explicitly). Single signature, single responsibility. The\n * pre-W0.2c 2-arg form `renderTemplate(template, options)` is REMOVED —\n * no caller passed a template name other than `this.template` (audited\n * 28/28 sites). Per-render template swap is impossible by design — if\n * needed, set `this.template = newName` then call render(). Forces\n * explicit identity change, blocks accidental render mismatch.\n */\n\n /** Required template-var allowlist. Subclasses override\n * `this.requiredTemplateKeys = ['url', 'text']` in the constructor.\n * `renderTemplate(vars)` throws if any required key is missing from\n * the merged vars (HARD RULE T6 — failure visible). */\n }, {\n key: \"requiredTemplateKeys\",\n get: function get() {\n var _this$_requiredTempla;\n return (_this$_requiredTempla = this._requiredTemplateKeys) !== null && _this$_requiredTempla !== void 0 ? _this$_requiredTempla : [];\n },\n set: function set(value) {\n this._requiredTemplateKeys = value;\n }\n\n /** Pure: resolve `this.template` against vars + return html. Auto-merges\n * defaults (`formatter`, `text`) when defined on the instance. NO\n * side effect — caller writes `this.domNode.innerHTML = …` explicitly.\n *\n * Three layers of validation (HARD RULE T6 — failure visible):\n * Guard T — `this.template` must be a non-empty string (else throw\n * with element class name in message).\n * Guard V — every key in `this.requiredTemplateKeys` must be present\n * in the merged vars passed to the engine.\n * Design-W — preserved pre-W0.2c warning when the template html body\n * doesn't reference a declared required key.\n */\n }, {\n key: \"renderTemplate\",\n value: function renderTemplate() {\n var _this4 = this;\n var vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Guard T — element identity ↔ template invariant. Catches the\n // \"constructor forgot to set this.template\" bug at the FIRST render\n // with an element-class-specific message (vs. the generic\n // `Template \"undefined\" not found` from builder.getTemplate).\n if (typeof this.template !== 'string' || this.template.length === 0) {\n throw new Error(\"\".concat(this.getClassName(), \".renderTemplate: this.template is missing or \") + \"not a string (got: \".concat(_typeof(this.template), \" \").concat(JSON.stringify(this.template), \"). \") + \"Set this.template = '<TemplateName>' in the constructor BEFORE render() \" + \"runs. Element identity \\u2194 template is a 1:1 invariant.\");\n }\n var merged = {};\n if (this.formatter !== undefined) merged.formatter = this.formatter;\n if (this.text !== undefined) merged.text = this.text;\n Object.assign(merged, vars);\n\n // Guard V — every required key must be present in the merged vars\n // passed to the template engine.\n var required = this.requiredTemplateKeys || [];\n var _iterator4 = _createForOfIteratorHelper(required),\n _step4;\n try {\n for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {\n var key = _step4.value;\n if (!(key in merged)) {\n throw new Error(\"\".concat(this.getClassName(), \".renderTemplate: requiredTemplateKey \\\"\").concat(key, \"\\\" \") + \"missing from vars. Either pass { \".concat(key, \": \\u2026 } or remove \\\"\").concat(key, \"\\\" from \") + \"requiredTemplateKeys.\");\n }\n }\n\n // Design-W — preserved pre-W0.2c warning. Catches templates that\n // declare a required key but don't actually reference it (theme\n // author drift).\n } catch (err) {\n _iterator4.e(err);\n } finally {\n _iterator4.f();\n }\n var html = this.host.getTemplate(this.template);\n this.host.validateKeysUsage(html, required, function (unusedKeys) {\n // eslint-disable-next-line no-console\n console.log(\"*****DESIGN ERROR: [\".concat(_this4.getClassName(), \"] Template \") + \"\\\"\".concat(_this4.template, \"\\\" does not use the following required keys: \") + \"\".concat(unusedKeys.join(', ')));\n });\n return this.host.renderTemplate(this.template, merged);\n }\n\n /** Baseline serialization. Subclasses extend via:\n * getData() {\n * return { ...super.getData(), text: this.text, ... };\n * }\n * `formats` is included only if the element has a formatter. */\n }, {\n key: \"getData\",\n value: function getData() {\n var data = {\n name: this.getClassName(),\n template: this.template\n };\n if (this.formatter && typeof this.formatter.getFormats === 'function') {\n data.formats = this.formatter.getFormats();\n }\n return data;\n }\n\n /** Static helper for `static parse(data)` bodies. Pulls `data.formats`\n * into the formatter (when both exist). Returns the instance for chaining:\n * static parse(data) {\n * return this.parseFormats(new this(data.template, data.text), data);\n * }\n */\n }, {\n key: \"duplicate\",\n value: /* ───────────────────────────────────────────────────────────────────── */\n\n function duplicate() {\n var cloned = ElementFactory.createElement(this.getData());\n // Host injection — `cloned` came from a fresh `.parse()` and has\n // not yet been adopted. `this.host._adopt(cloned)` walks the new\n // subtree before insert so its overlays + nested children also\n // pick up the back-reference.\n if (this.host && typeof this.host._adopt === 'function') {\n this.host._adopt(cloned);\n }\n this.container.insertElementAfter(this, cloned);\n\n // @todo: dependency\n this.host.selectElement(cloned);\n\n // PLAN_UNDO_REDO — structural mutation, explicit commit.\n // HistoryManager silences commits during its own apply via _applying.\n // `getName()` returns the human-readable display name (subclass\n // override like ImageElement.getName() → \"Image\") — that's what\n // surfaces in the history dropdown label.\n if (this.host.history) {\n this.host.history.commit('history.structure_duplicate', {\n change: 'structure:duplicate',\n elementType: this.getName(),\n source: 'action-bar'\n });\n }\n }\n }, {\n key: \"fadeOut\",\n value: function fadeOut() {\n var _this$host;\n var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 300;\n var callback = arguments.length > 1 ? arguments[1] : undefined;\n var element = this.domNode;\n\n // Defensive — element may not be in the DOM yet (called before render\n // completes, or after the element has been removed). Skip animation\n // and fire callback immediately so caller flow continues.\n if (!element) {\n if (typeof callback === 'function') callback();\n return;\n }\n\n // PLAN_UNDO_REDO — skip mount/unmount animation during history apply.\n // Re-playing 300ms fade-out across every removed element on undo would\n // freeze the UI. Jump straight to final state.\n if ((_this$host = this.host) !== null && _this$host !== void 0 && (_this$host = _this$host.history) !== null && _this$host !== void 0 && _this$host._applying) {\n if (typeof callback === 'function') callback();\n return;\n }\n\n // Get computed height to allow transition from fixed height to 0\n var computedStyle = getComputedStyle(element);\n var height = element.offsetHeight;\n element.style.height = height + 'px';\n element.style.overflow = 'hidden'; // Prevent content overflow during height transition\n\n // Set up the transition\n element.style.transition = \"opacity \".concat(duration, \"ms, transform \").concat(duration, \"ms, height \").concat(duration, \"ms\");\n element.style.opacity = '1';\n element.style.transform = 'translateX(0)';\n var _handleTransitionEnd = function handleTransitionEnd(event) {\n // Wait for all transitions to complete\n if (event.propertyName !== 'height') return;\n element.removeEventListener('transitionend', _handleTransitionEnd);\n element.style.display = 'none';\n if (typeof callback === 'function') {\n callback();\n }\n };\n element.addEventListener('transitionend', _handleTransitionEnd);\n\n // Trigger animation\n requestAnimationFrame(function () {\n void element.offsetWidth; // Force reflow\n element.style.opacity = '0';\n element.style.transform = 'translateX(100px)';\n element.style.height = '0px';\n });\n }\n }, {\n key: \"fadeIn\",\n value: function fadeIn() {\n var _this$host2;\n var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 300;\n var callback = arguments.length > 1 ? arguments[1] : undefined;\n var element = this.domNode;\n\n // Defensive — element may not be mounted yet. Skip animation and fire\n // callback so the caller flow continues without crashing.\n if (!element) {\n if (typeof callback === 'function') callback();\n return;\n }\n\n // PLAN_UNDO_REDO — skip mount animation during history apply. Re-playing\n // every block's 300ms fade-in on undo/redo looks like broken jank.\n if ((_this$host2 = this.host) !== null && _this$host2 !== void 0 && (_this$host2 = _this$host2.history) !== null && _this$host2 !== void 0 && _this$host2._applying) {\n if (typeof callback === 'function') callback();\n return;\n }\n\n // Remove any lingering transitionend listeners\n element.removeEventListener('transitionend', element._fadeInTransitionEnd);\n\n // Reset display and initial state\n element.style.display = '';\n element.style.overflow = 'hidden';\n element.style.opacity = '0';\n element.style.transform = 'translateX(100px)';\n element.style.height = '0px';\n\n // Force reflow to apply initial styles\n void element.offsetWidth;\n\n // Measure full height to transition to\n var targetHeight = element.scrollHeight;\n\n // Apply transition styles\n element.style.transition = \"opacity \".concat(duration, \"ms ease, transform \").concat(duration, \"ms ease, height \").concat(duration, \"ms ease\");\n\n // Define the transition end handler\n var _handleTransitionEnd2 = function handleTransitionEnd(event) {\n if (event.propertyName !== 'height') return;\n element.removeEventListener('transitionend', _handleTransitionEnd2);\n element.style.overflow = ''; // Reset overflow\n element.style.height = ''; // Let height be auto after transition\n\n if (typeof callback === 'function') {\n callback();\n }\n };\n\n // Attach and store the handler (to avoid duplicates)\n element._fadeInTransitionEnd = _handleTransitionEnd2;\n element.addEventListener('transitionend', _handleTransitionEnd2);\n\n // Animate to visible state\n requestAnimationFrame(function () {\n element.style.opacity = '1';\n element.style.transform = 'translateX(0)';\n element.style.height = targetHeight + 'px';\n });\n }\n }, {\n key: \"remove\",\n value: function remove() {\n var _this5 = this;\n if (this.host.getSelectedElement() === this) {\n this.host.unselect();\n }\n\n // Capture display name BEFORE fadeOut — subclass override like\n // ImageElement.getName() → \"Image\" (not \"ImageElement\"). Stays\n // valid after removal but we snapshot for clarity.\n var elementType = this.getName();\n this.fadeOut(300, function () {\n // remove alement from all\n _this5.host.uiManager.removeDraggableItem(_this5);\n _this5.host.uiManager.removeElement(_this5);\n _this5.host.uiManager.dragOveringElements = [];\n _this5.host.uiManager.hoveringElements = [];\n\n // remove all effects\n _this5.removeHoverHightlight();\n _this5.removeSelectedHighlight();\n _this5.removeDropHighlight();\n _this5.removeContainerHightlight();\n _this5.removeContainerDropHightlight();\n\n // Tear down any overlays still mounted on this element (all triggers).\n // Overlays register window.document scroll/resize listeners through\n // matchingDomNode — without this call they'd keep firing against a\n // removed element. See docs/core/OVERLAY.md §3 + §4.I5.\n _this5.unmountOverlays('*');\n if (_this5.getDragAnchor && typeof _this5.getDragAnchor === 'function' && _this5.getDragAnchor()) {\n _this5.getDragAnchor().remove();\n }\n\n // remove from container\n _this5.container.removeElement(_this5);\n\n // PLAN_UNDO_REDO — structural mutation is now final (after fadeOut\n // completes + container.render()). Explicit commit so undo restores\n // the element. Silenced by HistoryManager._applying if this remove\n // is itself a redo step.\n if (_this5.host.history) {\n _this5.host.history.commit('history.structure_remove', {\n change: 'structure:remove',\n elementUid: _this5.id,\n elementType: elementType,\n source: 'action-bar'\n });\n }\n\n // CD-3 (AIBuilder Wave 4) — emit element:removed at the\n // structure-mutation chokepoint, NOT through HistoryManager (which\n // dedupes identical-data commits). Layers tree (Wave 14) +\n // collaborative editing (Wave 85) need every remove regardless of\n // history dedupe.\n if (_this5.host.events && _this5.id != null) {\n var _window$Builder$EVENT, _window$Builder;\n _this5.host.events.emit((_window$Builder$EVENT = (_window$Builder = window.Builder) === null || _window$Builder === void 0 || (_window$Builder = _window$Builder.EVENTS) === null || _window$Builder === void 0 ? void 0 : _window$Builder.ELEMENT_REMOVED) !== null && _window$Builder$EVENT !== void 0 ? _window$Builder$EVENT : 'element:removed', {\n elementUid: _this5.id,\n elementType: elementType\n });\n }\n });\n }\n\n // ─── Canvas Overlay hooks (Phase 1.1) ───────────────────────────────\n //\n // See docs/core/OVERLAY.md for spec, docs/archived/OVERLAY_PLAN.md §3.2 for phase scope.\n //\n // Default `getOverlays()` returns [] — every element that doesn't opt in\n // executes zero new work. `mount/unmountOverlays` are guarded by that\n // default, so Builder.selectElement / UIManager.mouseover paths short-\n // circuit with `if (getOverlays().length)` or produce empty for-loops.\n //\n // Subclasses override getOverlays() to return an array of BaseOverlay\n // subclass instances. See ImageElement/GridElement/CellElement/BlockElement\n // in later phases for examples.\n\n /** Return canvas overlay instances for this element.\n * Override in subclasses — default is [] (additive-only safety). */\n }, {\n key: \"getOverlays\",\n value: function getOverlays() {\n return [];\n }\n\n /**\n * Return this element's child elements as a flat array.\n *\n * Used by Builder._adopt() to recurse the element tree post-parse and\n * assign `host` on every Element + its overlays. Override in container\n * elements (Page/Block/Grid/Cell) to return their child arrays.\n *\n * Default: leaf — no children. See Lesson \"Host Injection\" in\n * BUILDER.md.\n */\n }, {\n key: \"getChildren\",\n value: function getChildren() {\n return [];\n }\n\n /** Mount overlays whose getTrigger() === trigger. Called by Builder\n * (select) and UIManager (hover) — do not call manually.\n *\n * Idempotent: if an overlay of this trigger is already mounted, this is\n * a no-op. UIManager.mouseover fires repeatedly while cursor moves inside\n * the same element — without idempotence, this.overlays would grow\n * unboundedly per hover session. */\n }, {\n key: \"mountOverlays\",\n value: function mountOverlays(trigger) {\n var _this6 = this;\n // Idempotence: already have live overlays of this trigger → skip.\n if (this.overlays.some(function (ov) {\n return ov.getTrigger() === trigger && ov.mounted;\n })) {\n return;\n }\n this.getOverlays().forEach(function (overlay) {\n if (overlay.getTrigger() === trigger) {\n // Host injection — getOverlays() constructed a fresh\n // overlay; assign host BEFORE mount() so afterMount()\n // can read host.options / host.events. Inherits from\n // this element's host (set by Builder._adopt()).\n overlay.host = _this6.host;\n\n // Edit-mode filter — when trigger is 'edit', skip overlays whose\n // declared edit mode doesn't match this.editMode. Overlays that\n // omit getEditMode() (or return null) are mode-agnostic and\n // mount on every edit-trigger fire (back-compat with overlays\n // pre-dating the multi-mode design).\n if (trigger === 'edit' && typeof overlay.getEditMode === 'function' && overlay.getEditMode() !== null && overlay.getEditMode() !== _this6.editMode) {\n return;\n }\n // Sanity: trigger 'hover' on non-hoverable element silently wastes\n // a mount because UIManager.mouseover bails at isHoverable check.\n // Log a warning so developers catch this at dev time. See §4.I7.\n if (trigger === 'hover' && typeof _this6.isHoverable === 'function' && !_this6.isHoverable()) {\n // eslint-disable-next-line no-console\n console.warn(\"[overlay] \".concat(_this6.getClassName(), \" declared a 'hover' trigger overlay \") + \"but isHoverable()=false \\u2014 UIManager.mouseover will never mount it. \" + \"Attach the affordance to the parent container's overlay instead. \" + \"See docs/core/OVERLAY.md \\xA77.3 + \\xA74.I7.\");\n }\n overlay.mount();\n _this6.overlays.push(overlay);\n }\n });\n }\n\n /** Unmount (and destroy) overlays matching trigger ('*' = all). */\n }, {\n key: \"unmountOverlays\",\n value: function unmountOverlays() {\n var trigger = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '*';\n this.overlays = this.overlays.filter(function (overlay) {\n if (trigger === '*' || overlay.getTrigger() === trigger) {\n overlay.destroy();\n return false; // remove from list\n }\n return true; // keep\n });\n }\n\n /** Enter a named edit mode — mounts 'edit'-trigger overlays whose\n * `getEditMode()` matches `modeName` (or whose `getEditMode()` is\n * absent / null, meaning \"any mode\"). Without the mode filter, every\n * edit-trigger overlay mounted on every enterEditMode call — a single\n * element with both a Crop popup and a Resize popup would mount BOTH\n * on `enterEditMode('crop')`, overlapping the modal mask. */\n }, {\n key: \"enterEditMode\",\n value: function enterEditMode(modeName) {\n if (this.editMode === modeName) return; // idempotent (§12 OVERLAY.md)\n // Tear down any currently-active edit overlay before swapping mode\n // so back-to-back enterEditMode('crop') → enterEditMode('resize')\n // doesn't leave the crop popup mounted underneath.\n if (this.editMode) this.unmountOverlays('edit');\n this.editMode = modeName;\n this.mountOverlays('edit');\n }\n\n /** Exit edit mode — unmounts 'edit' overlays + one-shot sidebar sync.\n * Single renderElementControls is OK here (boundary transition, not\n * a hot-path loop — see §7 OVERLAY.md rule 1 exception). */\n }, {\n key: \"exitEditMode\",\n value: function exitEditMode() {\n var _this$host3, _this$host3$getSelect;\n this.unmountOverlays('edit');\n this.editMode = null;\n if (((_this$host3 = this.host) === null || _this$host3 === void 0 || (_this$host3$getSelect = _this$host3.getSelectedElement) === null || _this$host3$getSelect === void 0 ? void 0 : _this$host3$getSelect.call(_this$host3)) === this) {\n // Only re-render the sidebar if this element is actually selected\n // — otherwise we'd thrash an unrelated panel.\n this.host.renderElementControls(this);\n }\n }\n }, {\n key: \"transferMediaAbsUrl\",\n value: function transferMediaAbsUrl(url) {\n // Null-tolerant: parse-only elements (created via `ElementClass.parse(json)`\n // outside a Builder tree, e.g. legacy-JSON migration tests) never get\n // adopted, so `this.host` is null. Return the URL unchanged in that case\n // — without a host there's no themeMediaUrl to prepend anyway. Adopted\n // elements (the production path through Builder._adopt) route through\n // host.transferMediaAbsUrl as before.\n if (!this.host) return url;\n return this.host.transferMediaAbsUrl(url);\n }\n\n /* Matching Position & Size of domNode and the box */\n }, {\n key: \"matchingDomNode\",\n value: function matchingDomNode(box) {\n var _this7 = this;\n var padding = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var setPosSize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n var afterPosSize = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n //\n if (!box) {\n return;\n }\n\n // Canvas-clip helper — clips the overlay paint area to the host\n // Builder's `mainContainer` rect so hover / selection / drop\n // highlights never bleed past the canvas edge into surrounding\n // chrome (sidebars, header, footer, adjacent Builder instances).\n // Runs AFTER setPosSize so b.getBoundingClientRect() reflects the\n // freshly-applied inline top/left/width/height. Opt-out via the\n // `.bjs-ovl-no-clip` class — used by `.actions-box` so the pill\n // toolbar can still float above the canvas top edge.\n // See BUILDER.md \"Canvas-clip contract\" + OVERLAY.md §24.\n var _applyCanvasClip = function _applyCanvasClip() {\n // Prefer the walk-up-resolved clip container (handles the\n // common case where `mainContainer` scrolls along with the\n // iframe inside a higher-up overflow:auto viewport — see\n // Builder._resolveClipContainer). Falls back to mainContainer\n // when the resolver returned `mainContainer` itself or when\n // host is missing (parse-only elements).\n var clip = _this7.host && (_this7.host._resolvedClipContainer || _this7.host.mainContainer) || null;\n if (!clip || box.classList.contains('bjs-ovl-no-clip')) {\n if (box.style.clipPath) box.style.clipPath = '';\n return;\n }\n var c = clip.getBoundingClientRect();\n var b = box.getBoundingClientRect();\n\n // Express the clip region as the CANVAS rect in box-relative\n // coordinates, via `polygon()`. Two reasons we cannot use the\n // simpler `inset(t r b l)` form:\n //\n // 1. `inset()` values clamp to >= 0 — they always cut INWARD\n // from the box's own border-box. So `inset(0 0 0 0)` clips\n // ::before / ::after that intentionally paints OUTSIDE the\n // box (e.g. `.drop-after-box::before` uses `bottom: -10px`,\n // `.drop-before-box::before` uses `top: -10px` to draw a\n // dashed rounded pill that STRADDLES the seam between two\n // blocks). Half of the pill lives outside the box rect by\n // design; the legacy inset form silently cut it off, so the\n // drop indicator rendered as a half-pill instead of a full\n // one (reported 2026-05-14: \"drop after/before highlight\n // bị che mất 1 nửa\").\n //\n // 2. The previous fix tried to early-out by skipping clip-path\n // when t=r=bo=l=0, but as soon as ANY edge of the box even\n // slightly overflowed the canvas (subpixel drift on\n // scroll/resize, or the box hugging a canvas edge), the\n // inset returned and re-clipped all four box edges — so\n // the pseudo cut-off reappeared whenever the user had\n // scrolled the canvas in the slightest.\n //\n // `polygon()` accepts negative coordinates, so the clip region\n // can extend OUTSIDE the box's border-box on the sides that are\n // still inside the canvas. Pseudos paint freely up to the\n // canvas edge; only the parts that genuinely overflow the\n // canvas get cut. This is the canvas-edge protection that the\n // helper was always supposed to provide; the inset form was a\n // box-edge approximation that happened to be wrong for any\n // overlay with outside-the-box pseudos.\n //\n // No regression for overlays whose pseudos live INSIDE the box\n // (`.selected-box::before { inset: 0 }`, `.hovering-box::before`,\n // etc.) — their paint area is contained, so widening the clip\n // beyond the box is a no-op for them. Box-shadows that already\n // extended past the box (`var(--bjs-selection-shadow)`) are now\n // visible up to the canvas edge instead of being truncated at\n // the box's border — a strict improvement.\n var leftPx = c.left - b.left;\n var topPx = c.top - b.top;\n var rightPx = c.right - b.left;\n var bottomPx = c.bottom - b.top;\n box.style.clipPath = \"polygon(\".concat(leftPx, \"px \").concat(topPx, \"px, \").concat(rightPx, \"px \").concat(topPx, \"px, \") + \"\".concat(rightPx, \"px \").concat(bottomPx, \"px, \").concat(leftPx, \"px \").concat(bottomPx, \"px)\");\n };\n if (!setPosSize) {\n setPosSize = function setPosSize() {\n // Get the bounding rect of the domNode inside the iframe\n var domRect = _this7.domNode.getBoundingClientRect();\n\n // Get the iframe element that contains the domNode\n var iframe = _this7.domNode.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe.getBoundingClientRect();\n\n // Calculate absolute position of domNode relative to main window\n var absoluteTop = iframeRect.top + domRect.top;\n var absoluteLeft = iframeRect.left + domRect.left;\n\n // Set the hoveringBox's position and size\n Object.assign(box.style, {\n position: 'fixed',\n top: \"\".concat(absoluteTop - padding, \"px\"),\n left: \"\".concat(absoluteLeft - padding, \"px\"),\n width: \"\".concat(domRect.width + padding * 2, \"px\"),\n height: \"\".concat(domRect.height + padding * 2, \"px\")\n });\n if (afterPosSize) {\n afterPosSize();\n }\n _applyCanvasClip();\n };\n } else {\n // Caller supplied a custom positioner (e.g. .actions-box uses\n // ToolbarPositioner; container-highlight 4-box system uses an\n // afterPosSize-style sub-layout). Wrap so canvas-clip still\n // fires AFTER their positioning runs — single source of truth\n // for the clip pass, regardless of who computes top/left.\n var _userSetPosSize = setPosSize;\n setPosSize = function setPosSize() {\n _userSetPosSize();\n _applyCanvasClip();\n };\n }\n setPosSize();\n\n //\n if (!box.events) {\n // === IFRAME SCROLL & RESIZE ===\n var iframeWindow = this.domNode.ownerDocument.defaultView;\n var iframeDocument = this.domNode.ownerDocument;\n\n // Named handlers so __disconnectObservers can actually remove them.\n // Pre-Phase-1.1 these were anonymous arrow functions → no\n // removeEventListener path → every box leaked 4 window listeners.\n // See docs/archived/OVERLAY_PLAN.md §4.I8 for the full story.\n var onIframeScroll = function onIframeScroll() {\n setPosSize();\n };\n var onIframeResize = function onIframeResize() {\n setPosSize();\n };\n var onParentScroll = function onParentScroll() {\n setPosSize();\n };\n var onParentResize = function onParentResize() {\n setPosSize();\n };\n iframeWindow.addEventListener('scroll', onIframeScroll, true);\n iframeWindow.addEventListener('resize', onIframeResize);\n\n // Optional: also watch for DOM mutations (e.g., added/removed elements)\n var mutationObserver = new iframeWindow.MutationObserver(function () {\n setPosSize();\n });\n mutationObserver.observe(iframeDocument.body, {\n childList: true,\n subtree: true,\n attributes: true\n });\n\n // Async layout changes (e.g. <video>/<img> natural size arriving\n // with loaded bytes, or CSS-driven content reflow) don't produce\n // a DOM mutation — only a layout change. ResizeObserver catches\n // both the element's own box resize and subtree reflow, so the\n // selection/hover overlay stays glued to the domNode even when\n // nothing in the DOM changed. Reported 2026-04-17 (VideoElement\n // empty-state/error-overlay height change was invisible to the\n // MutationObserver).\n var resizeObserver = null;\n if (typeof iframeWindow.ResizeObserver === 'function') {\n resizeObserver = new iframeWindow.ResizeObserver(function () {\n setPosSize();\n });\n resizeObserver.observe(this.domNode);\n }\n\n // Outer Document\n window.document.addEventListener('scroll', onParentScroll, true);\n window.document.addEventListener('resize', onParentResize);\n\n // Canvas-clip reflow hook — register `setPosSize` with the\n // Builder's mainContainer-level reflow set so a pure\n // mainContainer resize (sidebar collapse, chrome variant\n // swap, parent-page layout shift that doesn't change the\n // iframe element's children's rects) still re-ticks every\n // mounted overlay's clip pass. Single ResizeObserver per\n // Builder, scattered hooks. See Builder._reflowHooks +\n // _mainContainerResizeObserver.\n var reflowHooks = this.host && this.host._reflowHooks;\n if (reflowHooks) {\n reflowHooks.add(setPosSize);\n }\n box.events = true;\n // Expose teardowns so remove*Highlight() callers (and future\n // element-specific cleanup paths) can release observers without\n // leaking iframe-scoped closures when the element is removed.\n box.__disconnectObservers = function () {\n if (mutationObserver) mutationObserver.disconnect();\n if (resizeObserver) resizeObserver.disconnect();\n // Phase 1.1 leak fix (§4.I8): remove the 4 window-scoped\n // scroll/resize listeners this invocation of matchingDomNode\n // added. Pre-fix, these accumulated forever.\n try {\n iframeWindow.removeEventListener('scroll', onIframeScroll, true);\n } catch (_) {}\n try {\n iframeWindow.removeEventListener('resize', onIframeResize);\n } catch (_) {}\n try {\n window.document.removeEventListener('scroll', onParentScroll, true);\n } catch (_) {}\n try {\n window.document.removeEventListener('resize', onParentResize);\n } catch (_) {}\n // Canvas-clip reflow hook — release the per-overlay\n // setPosSize from the Builder-level set so a removed\n // overlay can't keep firing on mainContainer resize.\n if (reflowHooks) {\n try {\n reflowHooks[\"delete\"](setPosSize);\n } catch (_) {}\n }\n };\n }\n }\n }, {\n key: \"setFormat\",\n value: function setFormat(format, value) {\n this.formats[format] = value;\n }\n }, {\n key: \"getFormat\",\n value: function getFormat(format) {\n var _this$formats$format;\n var dValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n return (_this$formats$format = this.formats[format]) !== null && _this$formats$format !== void 0 ? _this$formats$format : dValue;\n }\n\n /* HOVERING EFFECTS */\n }, {\n key: \"addHoverHightlight\",\n value: function addHoverHightlight() {\n var _this$host4,\n _this8 = this;\n // PLAN_EFFECT W2.1 — the currently-selected element already\n // shows a selection outline via `.selected-box`; painting a\n // hover outline on top creates double-outline visual noise\n // (user feedback 2026-04-19 \"tránh messup\"). Predicate is\n // defensive: covers both the direct UIManager call path AND\n // any future caller that forgets to check selection state.\n if (typeof ((_this$host4 = this.host) === null || _this$host4 === void 0 ? void 0 : _this$host4.getSelectedElement) === 'function' && this.host.getSelectedElement() === this) {\n // Also tear down any lingering hover overlay from a prior\n // mousemove frame — the selection just landed and the\n // hover should be gone instantly, not after the 50 ms\n // debounce tail.\n this.removeHoverHightlight();\n return;\n }\n if (!this.hoveringBox) {\n var _this$host5;\n this.hoveringBox = document.createElement('div');\n this.hoveringBox.classList.add('hovering-box');\n\n // Element-type chip (W2.2 — hidden by default; gated on\n // `body.bjs-hover-type-badge-on`).\n var labelHtml = \"<div class=\\\"hovering-label\\\">\".concat(this.getName(), \"</div>\");\n\n // PLAN_EFFECT W2.3 — Inspect-mode children (hidden by default;\n // gated on `body.bjs-inspect-active` AND `body.bjs-inspect-\n // mode-on` together via CSS — both must be true to render).\n // Geometry is recomputed by `_layoutHoverInspect()` below on\n // every reflow via the same `__layoutHook` channel\n // matchingDomNode exposes.\n //\n // Layout per-side:\n // .bjs-hover-inspect-content — content rect (inside padding)\n // .bjs-hover-inspect-pad-{top|right|bottom|left} — 4 strips\n // .bjs-hover-inspect-dim — \"W × H\" chip on the content rect\n var inspectHtml = \"\\n <div class=\\\"bjs-hover-inspect-content\\\"></div>\\n <div class=\\\"bjs-hover-inspect-pad bjs-hover-inspect-pad-top\\\"></div>\\n <div class=\\\"bjs-hover-inspect-pad bjs-hover-inspect-pad-right\\\"></div>\\n <div class=\\\"bjs-hover-inspect-pad bjs-hover-inspect-pad-bottom\\\"></div>\\n <div class=\\\"bjs-hover-inspect-pad bjs-hover-inspect-pad-left\\\"></div>\\n <div class=\\\"bjs-hover-inspect-dim\\\"></div>\\n \";\n this.hoveringBox.innerHTML = labelHtml + inspectHtml;\n\n // PLAN_EFFECT W2.3 — if Alt is currently held when this hover\n // mounts, paint inspect-on from frame ZERO. Otherwise the\n // user would see one quiet-hover frame before the global\n // listener catches up. State lives on `host._inspectAltDown`\n // (NOT body class) — see HARD RULE C revised.\n if ((_this$host5 = this.host) !== null && _this$host5 !== void 0 && _this$host5._inspectAltDown) {\n this.hoveringBox.classList.add('bjs-inspect-active');\n }\n document.body.appendChild(this.hoveringBox);\n }\n\n // Re-position on every reflow. The 4th `afterPosSize` arg runs\n // AFTER the box has been positioned + sized, so we can safely\n // read width/height for the inspect-overlay layout. The hook\n // runs even when inspect mode is OFF (cost is one\n // getComputedStyle per reflow); CSS hides the children when\n // the inspect body classes aren't present, so the no-op cost\n // is negligible.\n this.matchingDomNode(this.hoveringBox, 0, null, function () {\n _this8._layoutHoverInspect();\n });\n }\n\n /**\n * PLAN_EFFECT W2.3 — Inspect-mode child layout.\n *\n * Reads computed padding from the hovered element + sizes the 4\n * `.bjs-hover-inspect-pad-*` strips + `.bjs-hover-inspect-content`\n * rect + `.bjs-hover-inspect-dim` chip accordingly. Called from\n * the `matchingDomNode` layout hook on every reflow.\n *\n * Why getComputedStyle and not formatter? Hover overlay paints on\n * EVERY hoverable element, not just elements with our padding-\n * format contract. Computed style works uniformly across every\n * element, including text nodes inside containers we don't own.\n */\n }, {\n key: \"_layoutHoverInspect\",\n value: function _layoutHoverInspect() {\n var _this9 = this;\n if (!this.hoveringBox || !this.domNode) return;\n var dom = this.domNode;\n var cs = dom.ownerDocument.defaultView.getComputedStyle(dom);\n var pt = parseFloat(cs.paddingTop) || 0;\n var pr = parseFloat(cs.paddingRight) || 0;\n var pb = parseFloat(cs.paddingBottom) || 0;\n var pl = parseFloat(cs.paddingLeft) || 0;\n\n // Use the hover-box's own rect (it already matches the element\n // via matchingDomNode) instead of dom.getBoundingClientRect()\n // — avoids the iframe → viewport translation since hover-box\n // is already in viewport coords.\n var W = parseFloat(this.hoveringBox.style.width) || this.hoveringBox.offsetWidth;\n var H = parseFloat(this.hoveringBox.style.height) || this.hoveringBox.offsetHeight;\n var contentW = Math.max(0, W - pl - pr);\n var contentH = Math.max(0, H - pt - pb);\n var set = function set(cls, style) {\n var el = _this9.hoveringBox.querySelector('.' + cls);\n if (el) Object.assign(el.style, style);\n };\n set('bjs-hover-inspect-content', {\n top: pt + 'px',\n left: pl + 'px',\n width: contentW + 'px',\n height: contentH + 'px'\n });\n set('bjs-hover-inspect-pad-top', {\n top: '0',\n left: '0',\n width: '100%',\n height: pt + 'px'\n });\n set('bjs-hover-inspect-pad-right', {\n top: pt + 'px',\n right: '0',\n width: pr + 'px',\n height: contentH + 'px'\n });\n set('bjs-hover-inspect-pad-bottom', {\n bottom: '0',\n left: '0',\n width: '100%',\n height: pb + 'px'\n });\n set('bjs-hover-inspect-pad-left', {\n top: pt + 'px',\n left: '0',\n width: pl + 'px',\n height: contentH + 'px'\n });\n var dim = this.hoveringBox.querySelector('.bjs-hover-inspect-dim');\n if (dim) {\n dim.textContent = \"\".concat(Math.round(W), \" \\xD7 \").concat(Math.round(H));\n }\n }\n }, {\n key: \"removeHoverHightlight\",\n value: function removeHoverHightlight() {\n if (this.hoveringBox) {\n if (typeof this.hoveringBox.__disconnectObservers === 'function') {\n this.hoveringBox.__disconnectObservers();\n }\n this.hoveringBox.remove();\n }\n this.hoveringBox = null;\n }\n\n /* SELECTED EFFECTS */\n }, {\n key: \"addSelectedHighlight\",\n value: function addSelectedHighlight() {\n var _this10 = this;\n // render selected outbound\n if (!this.selectedBox) {\n this.selectedBox = document.createElement('div');\n this.selectedBox.classList.add('selected-box');\n\n // Append it to the body\n document.body.appendChild(this.selectedBox);\n\n //\n this.matchingDomNode(this.selectedBox, 5);\n }\n\n // Render actions\n if (!this.actionsBox) {\n this.actionsBox = document.createElement('div');\n this.actionsBox.classList.add('actions-box');\n this.actionsBox.classList.add('d-flex');\n this.actionsBox.classList.add('align-items-center');\n // Opt out of canvas-clip — the toolbar pill MUST escape the\n // canvas top edge (its preferred-side=\"above\" places it\n // 9 px above the selection outline; clipping would chop the\n // pill off when the selected element sits at canvas top).\n // See OVERLAY.md §24 Canvas-clip contract.\n this.actionsBox.classList.add('bjs-ovl-no-clip');\n // Append it to the body\n document.body.appendChild(this.actionsBox);\n // \n this.matchingDomNode(this.actionsBox, 5, function () {\n if (!_this10.actionsBox) {\n return;\n }\n\n // Viewport-space element rect — same math as every other\n // overlay, see OVERLAY.md §4 I2 for the single-source\n // rule. `absoluteTop` / `absoluteLeft` are passed unchanged\n // to the positioner below.\n var domRect = _this10.domNode.getBoundingClientRect();\n var iframe = _this10.domNode.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe.getBoundingClientRect();\n var absoluteTop = iframeRect.top + domRect.top;\n var absoluteLeft = iframeRect.left + domRect.left;\n\n // PLAN_EFFECT W1.2 (final) — the `.actions-box` is now a\n // SINGLE unified pill docked to the element's left edge.\n // Name section + actions section live inside one pill\n // chrome with an internal vertical divider (see CSS).\n // JS owns only: top / left positioning (via\n // ToolbarPositioner) + diagnostic data-attrs (`data-side`,\n // `data-did-flip`, `data-did-clamp`) so CSS can tint the\n // pill when the positioner picked the non-preferred side.\n // Width + height flow from CSS (intrinsic `max-content`);\n // the 240 / 30 values below feed the positioner only for\n // horizontal-clamp + flip math.\n var toolbar = {\n width: 240,\n height: 36\n };\n // 9 px gap = tight visible air-gap between pill and the\n // `.selected-box` outline+halo (halo ~3 px outward). Reduced\n // from 14 → 9 after user feedback 2026-04-19 — pulls the\n // pill 5 px closer to the element on BOTH `above` (pill\n // shifts DOWN) and `below` (pill shifts UP) branches.\n var gap = 9;\n\n // -1 px horizontal inset so the pill's left edge lines up\n // with the selection outline's visible left edge — the\n // `.selected-box` uses `outline-offset: -1px`, so its\n // visual outer edge sits at `element.left - ~1 px`.\n // Without this nudge the pill shows as slightly indented\n // from the outline (user feedback 2026-04-19).\n var pos = _this10.host.toolbarPositioner.compute({\n elementRect: {\n top: absoluteTop,\n left: absoluteLeft - 1,\n width: domRect.width,\n height: domRect.height\n },\n toolbar: toolbar,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight\n },\n gap: gap,\n preferredSide: 'above'\n });\n _this10.actionsBox.dataset.side = pos.side;\n _this10.actionsBox.dataset.didFlip = String(pos.didFlip);\n _this10.actionsBox.dataset.didClamp = String(pos.didClamp);\n Object.assign(_this10.actionsBox.style, {\n position: 'fixed',\n top: \"\".concat(pos.top, \"px\"),\n left: \"\".concat(pos.left, \"px\")\n // width / height intentionally absent — let CSS drive\n // intrinsic sizing so the pill fits its own contents.\n });\n });\n\n // Label\n this.actionsBoxLabel = document.createElement('h6');\n this.actionsBoxLabel.classList.add('ms-2');\n this.actionsBoxLabel.classList.add('m-0');\n this.actionsBoxLabel.classList.add('text-light');\n this.actionsBoxLabel.innerHTML = '<span class=\"d-flex align-items-center\"><span class=\"material-symbols-rounded me-2\">apps</span>' + this.getName() + '</span>';\n this.actionsBox.appendChild(this.actionsBoxLabel);\n this.actionsBoxInner = document.createElement('div');\n this.actionsBoxInner.classList.add('actions-box-inner');\n this.actionsBoxInner.classList.add('btn-group');\n this.actionsBoxInner.classList.add('border');\n this.actionsBoxInner.classList.add('ms-auto');\n this.actionsBoxInner.classList.add('me-2');\n this.actionsBoxInner = document.createElement('div');\n this.actionsBoxInner.classList.add('actions-box-inner');\n this.actionsBoxInner.classList.add('btn-group');\n // this.actionsBoxInner.classList.add('border');\n this.actionsBoxInner.classList.add('ms-auto');\n // Append it to the body\n this.actionsBox.appendChild(this.actionsBoxInner);\n this.getActions().forEach(function (action) {\n var actionButton = document.createElement('button');\n actionButton.setAttribute('class', 'element-action-item btn btn-light p-1 d-flex align-items-center');\n actionButton.setAttribute('data-tooltip', action.label);\n actionButton.setAttribute('aria-label', action.label);\n actionButton.innerHTML = \"\\n <span class=\\\"material-symbols-rounded fs-5\\\">\" + action.icon + \"</span>\\n \";\n _this10.actionsBoxInner.appendChild(actionButton);\n\n // events\n actionButton.addEventListener('click', function () {\n action.run();\n });\n });\n\n // PLAN_EFFECT W1.4 — focus-dim toggle inside every pill so the\n // feature is always one click from the selected element, not\n // hidden behind a keyboard shortcut only. Click flips state,\n // button `is-active` class mirrors the current state. Uses the\n // shared `contrast` Material icon.\n this._appendFocusDimToggle(this.actionsBoxInner);\n }\n }\n\n /** Helper shared by BaseElement + ImageElement (via super) — appends a\n * focus-dim toggle button into the given actions-box-inner container.\n * Icon swaps between `light_mode` (sun — focus-dim OFF, page bright)\n * and `dark_mode` (moon — focus-dim ON, page dimmed). No active-state\n * fill; icon change alone communicates state, which reads cleaner\n * than a filled chip (user feedback 2026-04-19 \"button thô quá\"). */\n }, {\n key: \"_appendFocusDimToggle\",\n value: function _appendFocusDimToggle(container) {\n var _this11 = this;\n if (!container) return;\n var btn = document.createElement('button');\n btn.setAttribute('class', 'element-action-item btn btn-light p-1 d-flex align-items-center bjs-focus-dim-toggle');\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded fs-5';\n btn.appendChild(icon);\n var sync = function sync() {\n var _this11$host;\n var on = typeof ((_this11$host = _this11.host) === null || _this11$host === void 0 ? void 0 : _this11$host.isFocusDim) === 'function' && _this11.host.isFocusDim();\n icon.textContent = on ? 'dark_mode' : 'light_mode';\n var _tipText = (on ? 'Focus mode: ON' : 'Focus mode: OFF') + ' (⌘/Ctrl+.)';\n btn.setAttribute('data-tooltip', _tipText);\n btn.setAttribute('aria-label', _tipText);\n btn.setAttribute('aria-pressed', on ? 'true' : 'false');\n };\n sync();\n btn.addEventListener('click', function (e) {\n var _this11$host2;\n e.stopPropagation();\n if (typeof ((_this11$host2 = _this11.host) === null || _this11$host2 === void 0 ? void 0 : _this11$host2.toggleFocusDim) === 'function') {\n _this11.host.toggleFocusDim();\n sync();\n }\n });\n container.appendChild(btn);\n }\n }, {\n key: \"removeSelectedHighlight\",\n value: function removeSelectedHighlight() {\n // remove selected outbound\n if (this.selectedBox) {\n if (typeof this.selectedBox.__disconnectObservers === 'function') {\n this.selectedBox.__disconnectObservers();\n }\n this.selectedBox.remove();\n }\n this.selectedBox = null;\n\n // remove selected actions\n if (this.actionsBox) {\n if (typeof this.actionsBox.__disconnectObservers === 'function') {\n this.actionsBox.__disconnectObservers();\n }\n this.actionsBox.remove();\n }\n this.actionsBox = null;\n }\n }, {\n key: \"getActions\",\n value: function getActions() {\n var _this12 = this;\n var actions = [{\n icon: 'content_copy',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('actions.copy'),\n run: function run() {\n _this12.duplicate();\n }\n }, {\n icon: 'delete',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('actions.remove'),\n run: function run() {\n _this12.remove(); // @todo dependency\n }\n }];\n if (this.container) {\n actions.unshift({\n icon: 'arrow_circle_up',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('actions.select_parent'),\n run: function run() {\n _this12.host.selectElement(_this12.container); // @todo dependency\n }\n });\n }\n actions.push({\n icon: 'remove_selection',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('actions.unselect'),\n run: function run() {\n _this12.host.unselect();\n }\n });\n return actions;\n }\n\n /* DROP INSIDE EFFECTS */\n }, {\n key: \"addDropBeforeHighlight\",\n value: function addDropBeforeHighlight() {\n // remove other effects\n this.removeDropHighlight();\n if (!this.dropBeforeBox) {\n this.dropBeforeBox = document.createElement('div');\n this.dropBeforeBox.classList.add('drop-before-box');\n\n // Append it to the body\n document.body.appendChild(this.dropBeforeBox);\n }\n this.matchingDomNode(this.dropBeforeBox);\n }\n }, {\n key: \"addDropAfterHighlight\",\n value: function addDropAfterHighlight() {\n // remove other effects\n this.removeDropHighlight();\n if (!this.dropAfterBox) {\n this.dropAfterBox = document.createElement('div');\n this.dropAfterBox.classList.add('drop-after-box');\n\n // Append it to the body\n document.body.appendChild(this.dropAfterBox);\n }\n this.matchingDomNode(this.dropAfterBox);\n }\n }, {\n key: \"addDropInsideHighlight\",\n value: function addDropInsideHighlight() {\n // remove other effects\n this.removeDropHighlight();\n if (!this.dropInsideBox) {\n this.dropInsideBox = document.createElement('div');\n this.dropInsideBox.classList.add('drop-inside-box');\n\n // Append it to the body\n document.body.appendChild(this.dropInsideBox);\n }\n this.matchingDomNode(this.dropInsideBox);\n }\n }, {\n key: \"removeDropHighlight\",\n value: function removeDropHighlight() {\n // remove drop inside\n if (this.dropInsideBox) {\n if (typeof this.dropInsideBox.__disconnectObservers === 'function') {\n this.dropInsideBox.__disconnectObservers();\n }\n this.dropInsideBox.remove();\n }\n this.dropInsideBox = null;\n\n // remove drop before\n if (this.dropBeforeBox) {\n if (typeof this.dropBeforeBox.__disconnectObservers === 'function') {\n this.dropBeforeBox.__disconnectObservers();\n }\n this.dropBeforeBox.remove();\n }\n this.dropBeforeBox = null;\n\n // remove drop after\n if (this.dropAfterBox) {\n if (typeof this.dropAfterBox.__disconnectObservers === 'function') {\n this.dropAfterBox.__disconnectObservers();\n }\n this.dropAfterBox.remove();\n }\n this.dropAfterBox = null;\n }\n }, {\n key: \"addContainerHightlight\",\n value: function addContainerHightlight(element) {\n var _this13 = this;\n // Skip the hover container-highlight when THIS container is already\n // part of the current selection — either THIS is the selected\n // element (redundant with its own selection outline — user feedback\n // 2026-04-19 image 2) or THIS is the parent of the selected child\n // (selection already communicates \"active\"; adding hover chrome on\n // top reads as noise). Bailing out early avoids spawning boxes\n // we'll immediately remove.\n var _selectedForGuard = this.host.getSelectedElement();\n if (_selectedForGuard && (_selectedForGuard === this || _selectedForGuard.container === this)) {\n this.removeContainerHightlight();\n return;\n }\n if (!this.containerBox) {\n this.containerBox = document.createElement('div');\n this.containerBox.classList.add('container-box');\n\n // //\n // this.containerBox.innerHTML = `\n // <div class=\"container-label\">`+this.getClassName()+`</div>\n // `;\n\n // Append it to the body\n document.body.appendChild(this.containerBox);\n }\n this.matchingDomNode(this.containerBox);\n if (!this.containerHighlightBox) {\n this.containerHighlightBox = document.createElement('div');\n this.containerHighlightBox.classList.add('container-selected-highlight-box');\n // Mount the full-rect hatch layer via the holed-box primitive\n // (.bjs-holed-box.--hatch + inline clip-path). Single gradient,\n // single origin — stripes flow continuously across every seam.\n // Helper `holedBoxClipPath` handles the winding-trick polygon;\n // see src/includes/ui/holedBoxClipPath.js + docs/plans/HOLED_BOX.md.\n this.containerHighlightBox.innerHTML = \"\\n <div class=\\\"bjs-holed-box bjs-holed-box--hatch\\\" data-role=\\\"hatch\\\"></div>\\n <div class=\\\"inside-box container-selected-highlight-box-1\\\"></div>\\n <div class=\\\"inside-box container-selected-highlight-box-2\\\"></div>\\n <div class=\\\"inside-box container-selected-highlight-box-3\\\"></div>\\n <div class=\\\"inside-box container-selected-highlight-box-4\\\"></div>\\n \";\n\n // Append it to the body\n document.body.appendChild(this.containerHighlightBox);\n }\n this.matchingDomNode(this.containerHighlightBox, 0, null, function () {\n if (!_this13.containerHighlightBox) {\n return;\n }\n\n // Use iframe-relative rects from the same coordinate space to avoid\n // cross-document subpixel rounding differences between browsers.\n // Both domNodes live inside the same iframe, so their getBoundingClientRect\n // values are directly comparable without converting through iframeRect.\n var childRect = element.domNode.getBoundingClientRect();\n var containerDomRect = _this13.domNode.getBoundingClientRect();\n\n // Padding areas between the container and child element.\n // Math.max(0, ...) guards against negative values from subpixel rounding —\n // a negative width/height is invalid CSS and browsers silently ignore it,\n // causing the CSS class default (width:100%) to take effect instead.\n var topPadding = Math.max(0, childRect.top - containerDomRect.top);\n var rightPadding = Math.max(0, containerDomRect.right - childRect.right);\n var bottomPadding = Math.max(0, containerDomRect.bottom - childRect.bottom);\n var leftPadding = Math.max(0, childRect.left - containerDomRect.left);\n var childWidth = childRect.width;\n var containerWidth = containerDomRect.width;\n var containerHeight = containerDomRect.height;\n\n // Box 1 — top strip, top-left corner at (leftPadding, 0)\n var box1 = _this13.containerHighlightBox.querySelector('.container-selected-highlight-box-1');\n box1.style.height = topPadding + 'px';\n box1.style.left = leftPadding + 'px';\n box1.style.width = childWidth + 'px';\n\n // Box 2 — right strip, top-left corner at (containerWidth - rightPadding, 0)\n var box2 = _this13.containerHighlightBox.querySelector('.container-selected-highlight-box-2');\n box2.style.width = rightPadding + 'px';\n\n // Box 3 — bottom strip, top-left corner at (leftPadding, containerHeight - bottomPadding)\n var box3 = _this13.containerHighlightBox.querySelector('.container-selected-highlight-box-3');\n box3.style.height = bottomPadding + 'px';\n box3.style.left = leftPadding + 'px';\n box3.style.width = childWidth + 'px';\n\n // Box 4 — left strip, top-left corner at (0, 0)\n var box4 = _this13.containerHighlightBox.querySelector('.container-selected-highlight-box-4');\n box4.style.width = leftPadding + 'px';\n\n // Holed-box hatch frame — carve the child rect out of a full\n // container hatch via clip-path. Helper handles the winding\n // trick; see src/includes/ui/holedBoxClipPath.js.\n var hatch = _this13.containerHighlightBox.querySelector('[data-role=\"hatch\"]');\n if (hatch) {\n hatch.style.clipPath = (0,_ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"])({\n width: containerWidth,\n height: containerHeight\n }, {\n left: leftPadding,\n top: topPadding,\n right: containerWidth - rightPadding,\n bottom: containerHeight - bottomPadding\n });\n }\n });\n }\n }, {\n key: \"removeContainerHightlight\",\n value: function removeContainerHightlight() {\n if (this.containerBox) {\n if (typeof this.containerBox.__disconnectObservers === 'function') {\n this.containerBox.__disconnectObservers();\n }\n this.containerBox.remove();\n }\n this.containerBox = null;\n if (this.containerHighlightBox) {\n if (typeof this.containerHighlightBox.__disconnectObservers === 'function') {\n this.containerHighlightBox.__disconnectObservers();\n }\n this.containerHighlightBox.remove();\n }\n this.containerHighlightBox = null;\n }\n }, {\n key: \"addContainerSelectedHightlight\",\n value: function addContainerSelectedHightlight(element) {\n var _this14 = this;\n this.removeContainerHightlight();\n if (!this.containerSelectedBox) {\n this.containerSelectedBox = document.createElement('div');\n this.containerSelectedBox.classList.add('container-selected-highlight-box');\n this.containerSelectedBox.innerHTML = \"\\n <div class=\\\"bjs-holed-box bjs-holed-box--hatch\\\" data-role=\\\"hatch\\\"></div>\\n <div class=\\\"inside-box container-selected-highlight-box-1\\\"></div>\\n <div class=\\\"inside-box container-selected-highlight-box-2\\\"></div>\\n <div class=\\\"inside-box container-selected-highlight-box-3\\\"></div>\\n <div class=\\\"inside-box container-selected-highlight-box-4\\\"></div>\\n \";\n\n // //\n // this.containerBox.innerHTML = `\n // <div class=\"container-label\">`+this.getClassName()+`</div>\n // `;\n\n // Append it to the body\n document.body.appendChild(this.containerSelectedBox);\n }\n this.matchingDomNode(this.containerSelectedBox, 0, null, function () {\n if (!_this14.containerSelectedBox) {\n return;\n }\n\n // Same iframe-relative rect approach as addContainerHightlight —\n // avoids cross-document subpixel rounding that breaks Chrome.\n var childRect = element.domNode.getBoundingClientRect();\n var containerDomRect = _this14.domNode.getBoundingClientRect();\n var topPadding = Math.max(0, childRect.top - containerDomRect.top);\n var rightPadding = Math.max(0, containerDomRect.right - childRect.right);\n var bottomPadding = Math.max(0, containerDomRect.bottom - childRect.bottom);\n var leftPadding = Math.max(0, childRect.left - containerDomRect.left);\n var childWidth = childRect.width;\n var containerWidth = containerDomRect.width;\n var containerHeight = containerDomRect.height;\n\n // Box 1 — top strip, top-left corner at (leftPadding, 0)\n var box1 = _this14.containerSelectedBox.querySelector('.container-selected-highlight-box-1');\n box1.style.height = topPadding + 'px';\n box1.style.left = leftPadding + 'px';\n box1.style.width = childWidth + 'px';\n\n // Box 2 — right strip, top-left corner at (containerWidth - rightPadding, 0)\n var box2 = _this14.containerSelectedBox.querySelector('.container-selected-highlight-box-2');\n box2.style.width = rightPadding + 'px';\n\n // Box 3 — bottom strip, top-left corner at (leftPadding, containerHeight - bottomPadding)\n var box3 = _this14.containerSelectedBox.querySelector('.container-selected-highlight-box-3');\n box3.style.height = bottomPadding + 'px';\n box3.style.left = leftPadding + 'px';\n box3.style.width = childWidth + 'px';\n\n // Box 4 — left strip, top-left corner at (0, 0)\n var box4 = _this14.containerSelectedBox.querySelector('.container-selected-highlight-box-4');\n box4.style.width = leftPadding + 'px';\n\n // Holed-box hatch frame — see addContainerHightlight for the\n // full rationale. Single gradient + clip-path = no seam jog.\n var hatch = _this14.containerSelectedBox.querySelector('[data-role=\"hatch\"]');\n if (hatch) {\n hatch.style.clipPath = (0,_ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"])({\n width: containerWidth,\n height: containerHeight\n }, {\n left: leftPadding,\n top: topPadding,\n right: containerWidth - rightPadding,\n bottom: containerHeight - bottomPadding\n });\n }\n });\n }\n }, {\n key: \"removeContainerSelectedHightlight\",\n value: function removeContainerSelectedHightlight() {\n if (this.containerSelectedBox) {\n if (typeof this.containerSelectedBox.__disconnectObservers === 'function') {\n this.containerSelectedBox.__disconnectObservers();\n }\n this.containerSelectedBox.remove();\n }\n this.containerSelectedBox = null;\n }\n }, {\n key: \"addContainerDropHightlight\",\n value: function addContainerDropHightlight() {\n if (!this.containerDropBox) {\n this.containerDropBox = document.createElement('div');\n this.containerDropBox.classList.add('container-drop-box');\n\n // //\n // this.containerDropBox.innerHTML = `\n // <div class=\"container-label\">`+this.getClassName()+`</div>\n // `;\n\n // Append it to the body\n document.body.appendChild(this.containerDropBox);\n }\n this.matchingDomNode(this.containerDropBox);\n }\n }, {\n key: \"removeContainerDropHightlight\",\n value: function removeContainerDropHightlight() {\n if (this.containerDropBox) {\n if (typeof this.containerDropBox.__disconnectObservers === 'function') {\n this.containerDropBox.__disconnectObservers();\n }\n this.containerDropBox.remove();\n }\n this.containerDropBox = null;\n }\n }, {\n key: \"checkIfThePositionIsBefore\",\n value: function checkIfThePositionIsBefore(clientX, clientY) {\n var hoveredBlock = this.domNode;\n var hoveredBlockRect = hoveredBlock.getBoundingClientRect();\n return clientY < hoveredBlockRect.top + hoveredBlockRect.height / 2;\n }\n\n // W0.2b — legacy `applyInlineEdit()` method removed. The new framework\n // (`registerInlineEdit` + auto-fired `_wireInlineEdit` from `afterRender`)\n // replaces both the legacy method AND the per-element wire blocks. See\n // docs/core/ELEMENT_DEFINITION.md → \"Inline editing — registerInlineEdit\"\n // and BUILDER.md Lesson 49.\n }], [{\n key: \"parseFormats\",\n value: function parseFormats(instance, data) {\n if (instance && instance.formatter && data && data.formats && typeof instance.formatter.parseFormats === 'function') {\n instance.formatter.parseFormats(data.formats);\n }\n return instance;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BaseElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BaseElement.js?");
/***/ }),
/***/ "./src/includes/BaseOverlay.js":
/*!*************************************!*\
!*** ./src/includes/BaseOverlay.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/*\n * BaseOverlay — base class for canvas overlays.\n *\n * See docs/core/OVERLAY.md for full design spec.\n * See docs/archived/OVERLAY_PLAN.md for phased implementation + SA invariants.\n *\n * Overlays are the on-canvas sibling of Controls:\n * Controls edit the element from the sidebar (getControls()).\n * Overlays edit the element from the canvas (getOverlays()).\n *\n * Subclasses MUST:\n * - override render() to build this.domNode\n * - optionally override getTrigger() ('select' | 'hover' | 'always' | 'edit')\n * - optionally override position() — but always delegate to\n * this.element.matchingDomNode() for iframe-aware positioning\n *\n * Subclasses MUST NOT:\n * - appendChild to the iframe document (overlays live in parent document.body)\n * - call builder.renderElementControls() in pointer/keystroke handlers (NO-FLICKER)\n * - duplicate iframe math (use matchingDomNode)\n *\n * Phase 1.9 (SA I15) — Error isolation: mount + destroy wrap render() /\n * beforeDestroy() in try/catch so a bug in one overlay can't kill element\n * lifecycle. A failed mount leaves mounted=false + domNode=null so the\n * element is still selectable. Errors route to BJS.error with the overlay\n * class name as tag.\n */\n\nvar BaseOverlay = /*#__PURE__*/function () {\n function BaseOverlay(element) {\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, BaseOverlay);\n this.element = element; // owning Element\n this.opts = opts; // subclass-specific config\n this.domNode = null; // floating box; created by render(), appended by mount()\n this.mounted = false;\n\n /**\n * Back-reference to the owning Builder. Set by Builder._adopt()\n * which walks element.overlays after parse. Available in\n * afterMount(), event handlers, beforeDestroy(). NOT guaranteed\n * inside the overlay constructor — defer host-dependent setup\n * to afterMount(). See BUILDER.md \"Host Injection\" lesson.\n */\n this.host = null;\n }\n\n // ─── Subclasses override ─────────────────────────────────────\n\n /** Declare when this overlay should be mounted. */\n return _createClass(BaseOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'select';\n } // 'select' | 'hover' | 'always' | 'edit'\n\n /** Build this.domNode and bind DOM/pointer events.\n * Do NOT append to document here — mount() does that. */\n }, {\n key: \"render\",\n value: function render() {\n throw new Error('BaseOverlay.render() is abstract — subclass must build this.domNode');\n }\n\n /** Called after this.domNode is appended and first positioned. Safe to\n * do size-dependent init here (child layout, scroll-to, focus). */\n }, {\n key: \"afterMount\",\n value: function afterMount() {}\n\n /** Called right before this.domNode is removed. Use to flush pending\n * state, clear timers, release resources, remove document-level listeners. */\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {}\n\n // ─── Framework-provided (usually not overridden) ────────────\n }, {\n key: \"mount\",\n value: function mount() {\n if (this.mounted) return;\n var tag = \"overlay:\".concat(this.constructor.name, \":mount\");\n try {\n if (!this.domNode) this.render();\n if (!this.domNode) throw new Error('render() returned without assigning this.domNode');\n // Namespace marker so UIManager's parent-doc hover-clear exemption\n // (§4.I6) can identify overlay nodes and skip the clear.\n this.domNode.classList.add('bjs-ovl');\n // Always append to parent document (never iframe). This is what\n // makes iframe-boundary pointer capture work (§4.I10).\n document.body.appendChild(this.domNode);\n this.position();\n this.mounted = true;\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log(tag, this.element && this.element.id);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error(tag, err);\n // Roll back partial state so the element stays selectable.\n if (this.domNode && this.domNode.parentNode) {\n try {\n this.domNode.parentNode.removeChild(this.domNode);\n } catch (_) {/* no-op */}\n }\n this.domNode = null;\n this.mounted = false;\n return;\n }\n // afterMount is a separate try so a broken afterMount doesn't unmount\n // a successfully-rendered overlay.\n try {\n this.afterMount();\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error(\"overlay:\".concat(this.constructor.name, \":afterMount\"), err);\n }\n }\n\n /** Default position: full-element box with zero padding.\n * Override to anchor to a sub-region — but always delegate to\n * this.element.matchingDomNode() (§4.I8 centralised positioning). */\n }, {\n key: \"position\",\n value: function position() {\n this.element.matchingDomNode(this.domNode, 0);\n }\n }, {\n key: \"show\",\n value: function show() {\n if (this.domNode) this.domNode.style.display = '';\n }\n }, {\n key: \"hide\",\n value: function hide() {\n if (this.domNode) this.domNode.style.display = 'none';\n }\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (!this.domNode) return;\n var tag = \"overlay:\".concat(this.constructor.name, \":destroy\");\n // beforeDestroy is caught so a broken hook can't leave observers\n // attached — the unmount path below still runs.\n try {\n this.beforeDestroy();\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error(\"\".concat(tag, \":beforeDestroy\"), err);\n }\n try {\n // Release observers attached by matchingDomNode (MutationObserver +\n // ResizeObserver + window.document + iframeWindow scroll/resize).\n if (typeof this.domNode.__disconnectObservers === 'function') {\n this.domNode.__disconnectObservers();\n }\n this.domNode.remove();\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log(tag, this.element && this.element.id);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error(tag, err);\n } finally {\n this.domNode = null;\n this.mounted = false;\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BaseOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BaseOverlay.js?");
/***/ }),
/***/ "./src/includes/BaseWidget.js":
/*!************************************!*\
!*** ./src/includes/BaseWidget.js ***!
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar BaseWidget = /*#__PURE__*/function () {\n function BaseWidget() {\n _classCallCheck(this, BaseWidget);\n this.domNode = null;\n\n // new Block for this widget\n this.block = new BlockElement('Block');\n }\n return _createClass(BaseWidget, [{\n key: \"render\",\n value: function render() {\n var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'icon';\n if (!this.domNode) {\n // Default UI box\n var widgetDiv = document.createElement('div');\n this.domNode = widgetDiv;\n } else {\n this.domNode.innerHTML = '';\n }\n\n //\n if (type === 'icon') {\n this.domNode.setAttribute('widget-class', this.constructor.name);\n this.domNode.className = 'widget-item';\n var iconDiv = document.createElement('div');\n iconDiv.innerHTML = '<span class=\"material-symbols-rounded widget-icon\">' + this.getIcon() + '</span>';\n iconDiv.className = 'widget-icon-box';\n this.domNode.appendChild(iconDiv);\n var labelDiv = document.createElement('div');\n labelDiv.className = 'widget-label';\n labelDiv.textContent = this.getName();\n this.domNode.appendChild(labelDiv);\n } else if (type === 'image') {\n this.domNode.setAttribute('widget-class', this.constructor.name);\n this.domNode.className = 'widget-item widget-item-image';\n var imageDiv = document.createElement('div');\n var imgSrc = this.getImageUrl();\n imageDiv.innerHTML = '<img src=\"' + imgSrc + '\" alt=\"' + this.getName() + '\" class=\"widget-image-box\"/>';\n this.domNode.appendChild(imageDiv);\n\n // const labelDiv = document.createElement('div');\n // labelDiv.className = 'widget-label';\n // labelDiv.textContent = this.getName();\n // this.domNode.appendChild(labelDiv);\n }\n return this.domNode;\n }\n }, {\n key: \"getImageUrl\",\n value: function getImageUrl() {\n return null;\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'extension';\n }\n }, {\n key: \"addDragAnchor\",\n value: function addDragAnchor() {}\n }, {\n key: \"getDragAnchor\",\n value: function getDragAnchor() {\n this.domNode.setAttribute('draggable', 'true');\n return this.domNode;\n }\n }, {\n key: \"hideDragAnchor\",\n value: function hideDragAnchor() {\n // do nothing\n }\n }, {\n key: \"showDragAnchor\",\n value: function showDragAnchor() {\n // do nothing\n }\n }, {\n key: \"removeAfterDrop\",\n value: function removeAfterDrop() {\n return false;\n }\n }, {\n key: \"canDropOn\",\n value: function canDropOn(element) {\n if (!element.isDroppable()) return false;\n\n // Grid-inside-Cell restriction.\n //\n // Widgets carry a wrapping Block (this.block) whose .elements[] holds\n // the widget's actual content. When a widget contains a GridElement\n // (ImageTextLeftWidget, ImageTextRightWidget, ImageTextDoubleWidget,\n // GridWidget, TextLeftWidget/TextDoubleWidget, PricingCardsWidget,\n // CheckoutWidget, RSSWidget, MenuWidget, …) it cannot legally land\n // INSIDE a Cell — nested Grids inside Cells are blocked by the\n // schema (CellElement.isDroppable=true is for child-Block targets;\n // Block-with-Grid sibling of an inner Block inside a Cell would\n // still be a Grid nested inside a Cell once the wrapping Block\n // gets adopted). Without this guard, UIManager.getTopDragOveringElement\n // picks the INNERMOST droppable (the inner Block inside the Cell)\n // and shows the drop indicator at HALF canvas width — the user\n // reads that as \"the indicator is half-clipped\" because they\n // expected the indicator at the OUTER 2-col block (full canvas\n // width) where the drop would actually make sense.\n //\n // Pre-fix this method read `this.getElements()` which doesn't exist\n // on BaseWidget — `getElements` is a BlockElement method. The check\n // silently returned an empty array and the restriction never fired\n // (2026-05-14: \"drop after/before highlight bị che mất 1 nửa\").\n // Fix: walk `this.block.elements` (the widget's actual content) and\n // also recurse one level into nested Grids to cover widgets whose\n // Grid lives at a deeper depth.\n if (this._widgetContainsGrid() && this._targetIsInsideCell(element)) {\n return false;\n }\n return true;\n }\n\n /** True when the widget's wrapping block (or any direct child of it)\n * is/contains a GridElement. Recursion intentionally shallow — every\n * shipped widget either has the Grid at depth 1 or doesn't have one\n * at all; deep recursion would mis-fire on Grid-rich page samples\n * reused inside other widgets and we have no such case today. */\n }, {\n key: \"_widgetContainsGrid\",\n value: function _widgetContainsGrid() {\n if (!this.block || !Array.isArray(this.block.elements)) return false;\n return this.block.elements.some(function (el) {\n return el && typeof el.getClassName === 'function' && el.getClassName() === 'GridElement';\n });\n }\n\n /** True when `target` is a CellElement (or a descendant whose\n * container chain reaches a Cell within 3 hops — covers the\n * Block-inside-Cell case the original commented intent referred to). */\n }, {\n key: \"_targetIsInsideCell\",\n value: function _targetIsInsideCell(target) {\n var node = target;\n for (var depth = 0; node && depth < 4; depth++) {\n if (typeof node.getClassName === 'function' && node.getClassName() === 'CellElement') return true;\n node = node.container;\n }\n return false;\n }\n }, {\n key: \"renderBlock\",\n value: function renderBlock() {\n // Clone a new block\n var block = BlockElement.parse(this.block.getData());\n return block;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BaseWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BaseWidget.js?");
/***/ }),
/***/ "./src/includes/BlockElement.js":
/*!**************************************!*\
!*** ./src/includes/BlockElement.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _overlays_BlockDragAnchorOverlay_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./overlays/BlockDragAnchorOverlay.js */ \"./src/includes/overlays/BlockDragAnchorOverlay.js\");\n/* harmony import */ var _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./overlays/PaddingVisualizerOverlay.js */ \"./src/includes/overlays/PaddingVisualizerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\nvar BlockElement = /*#__PURE__*/function (_BaseElement) {\n function BlockElement(template) {\n var _this;\n _classCallCheck(this, BlockElement);\n _this = _callSuper(this, BlockElement); // Call the parent class constructor\n _this.container = null;\n _this.elements = [];\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['elements'];\n\n // Formatter\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]({\n // background\n background_color: null,\n background_image: null,\n background_position: null,\n background_size: null,\n background_repeat: null,\n background_blend_mode: null,\n opacity: null,\n filter: null,\n // border\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_width: null,\n border_left_style: null,\n border_left_color: null,\n // border radius\n border_radius: null,\n // padding\n padding_top: null,\n padding_right: null,\n padding_bottom: null,\n padding_left: null\n\n // NOTE: margin intentionally removed 2026-04-17.\n // BlockElement is a container; margin between blocks was\n // confusing next to the padding control (users routinely\n // picked the wrong one). External block spacing is now\n // always the parent's responsibility — use the Page's\n // `block_gap` between siblings, or the Cell's padding.\n // Existing sample JSON with margin_* keys loads cleanly\n // (Formatter.parseFormats skips unknown keys); a migration\n // script (scripts/migrate-block-margin-to-padding.cjs)\n // converts margin_* → padding_* on the same block so the\n // visual stays intact after re-save.\n });\n _this.template = template;\n return _this;\n }\n _inherits(BlockElement, _BaseElement);\n return _createClass(BlockElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.block');\n }\n }, {\n key: \"isDroppable\",\n value: function isDroppable() {\n return true;\n }\n }, {\n key: \"canDropAfter\",\n value: function canDropAfter() {\n return this.isDroppable();\n }\n }, {\n key: \"canDropBefore\",\n value: function canDropBefore() {\n return this.isDroppable();\n }\n\n /**\n * Cheap in-place style patch — PLAN_EFFECT W3.1 + SA I5.\n *\n * BlockElement.template.html wraps children in a single styled div:\n * <div style=\"<%- formatter.toStyleStringAll() %>\"> ... </div>\n *\n * applyFormatStyles() updates only that wrapper's inline `style`\n * attribute. Child element DOM + UIManager registrations are left\n * intact. Any observer anchored to the Block (e.g. the\n * PaddingVisualizerOverlay's ResizeObserver via matchingDomNode)\n * sees a normal layout change and re-positions — no teardown /\n * remount cycle, so no flicker on the canvas.\n *\n * Use this for every formatter-only mutation (padding, margin,\n * background, border) from a Control callback. Fall back to\n * render() only when the mutation actually changes child structure\n * (add/remove elements, template swap).\n */\n }, {\n key: \"applyFormatStyles\",\n value: function applyFormatStyles() {\n if (!this.domNode) {\n this.render();\n return;\n }\n var inner = this.domNode.firstElementChild;\n if (!inner) {\n this.render();\n return;\n }\n inner.setAttribute('style', this.formatter.toStyleStringAll());\n }\n\n /**\n * PLAN_EFFECT W3.7 — cascade-aware padding read.\n *\n * Returns the EFFECTIVE padding for a side:\n * - This block's own formatter value if it's a non-null number.\n * - Otherwise, walk up to the page and read\n * `page.block_padding_${side}` (the Page's \"Block default\n * padding\" setting, cascaded to every block without an\n * explicit padding). Matches the CSS cascade the Page template\n * already applies at render time.\n * - Zero as a last resort.\n *\n * Used by the PaddingVisualizerOverlay via `opts.readSide` so the\n * on-canvas visualisation reflects what users SEE in the browser,\n * not just what's stored in their own formatter. Without this, a\n * block with no explicit padding would draw zero-width regions on\n * canvas while the rendered page actually shows e.g. 20px from the\n * page's default.\n */\n }, {\n key: \"getEffectivePadding\",\n value: function getEffectivePadding(side) {\n var own = this.formatter.getFormat(\"padding_\".concat(side));\n if (own !== null && own !== undefined && own !== '') {\n var n = Number(own);\n if (!Number.isNaN(n)) return n;\n }\n\n // Walk up the container chain to find the PageElement.\n var ctx = this.container;\n while (ctx) {\n if (ctx.getClassName && ctx.getClassName() === 'PageElement') {\n var v = ctx[\"block_padding_\".concat(side)];\n var _n = Number(v);\n return Number.isNaN(_n) ? 0 : _n;\n }\n ctx = ctx.container;\n }\n return 0;\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n var _this2 = this;\n // formatter auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n elements: this.elements.map(function (element) {\n return '<div element-anchor=\"' + element.id + '\">' + element.id + '</div>';\n }).join('')\n });\n\n // render elements inside\n this.elements.forEach(function (element) {\n var anchor = _this2.domNode.querySelector('[element-anchor=\"' + element.id + '\"]');\n\n // render block\n var domNode = element.render();\n\n // Dome append child\n anchor.parentNode.insertBefore(domNode, anchor);\n\n //\n anchor.remove();\n\n //\n _this2.host.uiManager.addElement(element);\n });\n }\n }, {\n key: \"append\",\n value: function append(element) {\n // private\n // set element container\n element.container = this;\n // Host injection — adopt the new element + its subtree.\n // No-op when this block isn't yet adopted (host null) — the\n // outer `_adopt(block)` from the insertion site will recurse and\n // reach the appended element through getChildren().\n if (this.host && typeof this.host._adopt === 'function') {\n this.host._adopt(element);\n }\n this.elements.push(element);\n }\n }, {\n key: \"appendElements\",\n value: function appendElements(elements) {\n var _this3 = this;\n elements.forEach(function (element) {\n _this3.append(element);\n });\n }\n }, {\n key: \"getElements\",\n value: function getElements() {\n // Return the elements\n return this.elements;\n }\n\n /** Host-injection recursion hook — returns this block's elements so\n * Builder._adopt() can walk down the tree. See BUILDER.md \"Host\n * Injection\" lesson. */\n }, {\n key: \"getChildren\",\n value: function getChildren() {\n return this.elements || [];\n }\n }, {\n key: \"renderBlock\",\n value: function renderBlock() {\n // Clone a new block\n var block = this.constructor.parse(this.getData());\n return block;\n }\n\n /**\n * Surgical remove — BUILDER.md Lesson 21 + customer fix 2026-05-20.\n *\n * Pre-fix this called `this.render()`, which wipes block innerHTML and\n * re-renders EVERY sibling element from scratch. Each child's\n * `_doRender()` then assigned `this.domNode.innerHTML = …`, round-\n * tripping `this.text` through the HTML5 fragment parser. With\n * customer content that contained `<div>` block children (Chrome's\n * default-paragraph-separator behaviour) this DROPPED their inline\n * `font-weight` / `text-align` / `font-family` because the parser\n * silently auto-closed the host `<p>` at the first `<div>`. Even\n * after `defaultParagraphSeparator = 'br'` + `InlineSanitizer.normalize`\n * defence-in-depth (see BaseElement._wireInlineEdit input listener)\n * the cascade re-render is wasteful — every untouched sibling pays\n * the cost of `innerHTML =` and the host blade's MutationObserver\n * pushes one history entry per mutation in the cascade.\n *\n * Surgical path: drop the element from the array, detach its\n * domNode, cascade up if the block went empty. Sibling DOM is\n * untouched — contenteditable cursors, sidebar control closures,\n * overlay anchors, UIManager registrations all survive byte-perfect.\n */\n }, {\n key: \"removeElement\",\n value: function removeElement(element) {\n var idx = this.elements.indexOf(element);\n if (idx === -1) return;\n this.elements.splice(idx, 1);\n if (element.domNode && element.domNode.parentNode) {\n element.domNode.remove();\n }\n\n // Cascade up: if this block is now empty, remove it too. Same\n // contract as the pre-fix path — `this.remove()` initiates a\n // fadeOut → container.removeElement on the parent (PageElement)\n // → another surgical pass.\n if (!this.elements.length) {\n this.remove();\n }\n }\n }, {\n key: \"insertElementAfter\",\n value: function insertElementAfter(element, newElement) {\n // set element container\n newElement.container = this;\n // Host injection — adopt before insert (in case caller hasn't).\n if (this.host && typeof this.host._adopt === 'function') {\n this.host._adopt(newElement);\n }\n var idx = this.elements.indexOf(element);\n if (idx === -1) return;\n this.elements.splice(idx + 1, 0, newElement);\n\n // Surgical DOM insert — render the NEW element only, splice into\n // the right position. Siblings' DOM stays untouched (see\n // `removeElement` rationale above).\n var renderedDom = newElement.render();\n var anchor = element.domNode;\n if (anchor && anchor.parentNode) {\n anchor.parentNode.insertBefore(renderedDom, anchor.nextSibling);\n } else if (this.domNode) {\n // Fallback — anchor missing for some reason; append at end so\n // the new element is at least mounted.\n this.domNode.firstElementChild ? this.domNode.firstElementChild.appendChild(renderedDom) : this.domNode.appendChild(renderedDom);\n }\n if (this.host && this.host.uiManager) {\n this.host.uiManager.addElement(newElement);\n }\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(BlockElement, \"getData\", this, 3)([])), {}, {\n elements: this.elements.map(function (element) {\n return element.getData();\n })\n });\n }\n }, {\n key: \"getContainerStyleControls\",\n value: function getContainerStyleControls() {\n var _this4 = this;\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var paddingLabel = options.paddingLabel || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.block_padding');\n return [new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n color: this.formatter.getFormat('background_color', '#ffffff'),\n image: this.formatter.getFormat('background_image', ''),\n position: this.formatter.getFormat('background_position', 'center'),\n size: this.formatter.getFormat('background_size', '100'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat'),\n blendMode: this.formatter.getFormat('background_blend_mode', 'normal'),\n opacity: Math.round((parseFloat(this.formatter.getFormat('opacity', 1)) || 1) * 100),\n filter: this.formatter.getFormat('filter', '')\n }, {\n setBackground: function setBackground(values) {\n _this4.formatter.setFormat('background_color', values.color);\n _this4.formatter.setFormat('background_image', values.image);\n _this4.formatter.setFormat('background_position', values.position);\n _this4.formatter.setFormat('background_size', typeof values.size === 'number' ? values.size : values.size);\n _this4.formatter.setFormat('background_repeat', values.repeat);\n _this4.formatter.setFormat('background_blend_mode', values.blendMode === 'normal' ? null : values.blendMode);\n _this4.formatter.setFormat('opacity', values.opacity === 1 ? null : values.opacity);\n _this4.formatter.setFormat('filter', values.filter || null);\n _this4.render();\n }\n }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style'),\n border_top_width: this.formatter.getFormat('border_top_width'),\n border_top_color: this.formatter.getFormat('border_top_color'),\n border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n border_left_style: this.formatter.getFormat('border_left_style'),\n border_left_width: this.formatter.getFormat('border_left_width'),\n border_left_color: this.formatter.getFormat('border_left_color'),\n border_right_style: this.formatter.getFormat('border_right_style'),\n border_right_width: this.formatter.getFormat('border_right_width'),\n border_right_color: this.formatter.getFormat('border_right_color')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this4.formatter.setFormat('border_top_style', border_top_style);\n _this4.formatter.setFormat('border_top_width', border_top_width);\n _this4.formatter.setFormat('border_top_color', border_top_color);\n _this4.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this4.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this4.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this4.formatter.setFormat('border_left_style', border_left_style);\n _this4.formatter.setFormat('border_left_width', border_left_width);\n _this4.formatter.setFormat('border_left_color', border_left_color);\n _this4.formatter.setFormat('border_right_style', border_right_style);\n _this4.formatter.setFormat('border_right_width', border_right_width);\n _this4.formatter.setFormat('border_right_color', border_right_color);\n _this4.render();\n }\n }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n setRadius: function setRadius(v) {\n _this4.formatter.setFormat('border_radius', v);\n // PLAN_EFFECT W3.1 — cheap in-place style patch instead\n // of full render(). Overlays keep their anchors; no\n // flicker.\n _this4.applyFormatStyles();\n }\n }), new _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](paddingLabel, {\n top: this.formatter.getFormat('padding_top'),\n right: this.formatter.getFormat('padding_right'),\n bottom: this.formatter.getFormat('padding_bottom'),\n left: this.formatter.getFormat('padding_left')\n }, {\n setValues: function setValues(values) {\n _this4.formatter.setFormat('padding_top', values.top);\n _this4.formatter.setFormat('padding_right', values.right);\n _this4.formatter.setFormat('padding_bottom', values.bottom);\n _this4.formatter.setFormat('padding_left', values.left);\n _this4.applyFormatStyles();\n }\n },\n // Host-injection — control reads bus + pinSet off\n // `this.host` directly. No prop-drilling needed.\n {\n elementUid: this.id\n })\n // Margin control removed 2026-04-17 — see formatter comment.\n ];\n }\n\n /**\n * W3.8b — deprecated. PageElement.getControls() already provides the\n * Block Padding control under its `block_padding` namespace (see\n * PageElement.js ~line 467). Keeping this method as a no-op so existing\n * `...this.getPageSettingsControls()` callers stay byte-compatible;\n * remove in a future tidy pass.\n */\n }, {\n key: \"getPageSettingsControls\",\n value: function getPageSettingsControls() {\n return [];\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n return [].concat(_toConsumableArray(this.getContainerStyleControls()), _toConsumableArray(this.getPageSettingsControls()));\n }\n }, {\n key: \"getOverlays\",\n value:\n /**\n * Canvas overlays (Phase 1.6 — replaces hand-rolled createDragAnchor).\n *\n * Trigger 'hover' — BlockDragAnchorOverlay mounts via\n * UIManager.mouseover → mountOverlays('hover'), unmounts via the\n * 50 ms debounce flush in UIManager.mouseout (SA invariant I1 —\n * debounce stays load-bearing for iframe-boundary idle-hover).\n *\n * The overlay owns its own `dragstart` handler (via NativeDragHandleOverlay)\n * and hands off to `uiManager.dragStart(block)` in its onDragStart hook.\n * `UIManager.addDraggableItem` detects this via `usesOverlayDragAnchor()`\n * and skips the legacy anchor-wiring path. Widgets continue to use the\n * legacy path (their domNode itself is the draggable).\n *\n * ⚠️ BLOCK-IN-CELL RULE (preserved from legacy — user report 2026-04-18):\n * Only TOP-LEVEL page blocks are draggable. A block nested inside a\n * CellElement has no drag anchor because moving it out of the cell\n * would break the containing grid's layout semantics (widgets are the\n * only things that can enter cells; once a block is in a cell it stays\n * there). The legacy rule was enforced implicitly by only registering\n * top-level blocks via `PageElement.render → addDraggableItem`. The\n * overlay path — where `getOverlays()` is called on every hover — must\n * enforce this explicitly OR else hovering an inner block mounts an\n * anchor that has no valid drop target anywhere.\n *\n * See docs/core/OVERLAY.md §7.4 + docs/archived/OVERLAY_PLAN.md §3.7 + §5 D54.\n */\n function getOverlays() {\n var _this5 = this;\n var overlays = [];\n\n // Drag anchor — trigger 'hover' — top-level blocks only (inner\n // blocks can't be dragged out of their cell).\n if (!this._isInsideCell()) {\n overlays.push(new _overlays_BlockDragAnchorOverlay_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](this));\n }\n\n // PLAN_EFFECT W3.1 — padding visualiser — trigger 'select'.\n // Always emit; the overlay self-disposes in afterMount() when\n // host's usePaddingVisualizer flag is off. Why: getOverlays()\n // runs during parse — `this.host` is null then, so a flag\n // check here would always skip. The flag gate moved to\n // PaddingVisualizerOverlay (commit 4 + 6 of host-injection\n // refactor).\n //\n // W3.7 — `opts.readSide` pipes the cascade-aware effective\n // padding into the overlay. If the block's own formatter is\n // null, the overlay still draws the inherited page.block_padding\n // value — matching what the user sees rendered on canvas.\n overlays.push(new _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](this, {\n readSide: function readSide(side) {\n return _this5.getEffectivePadding(side);\n }\n }));\n return overlays;\n }\n\n /**\n * Capability flag consumed by `UIManager.addDraggableItem`. When true,\n * UIManager skips calling `addDragAnchor()` / binding a shared dragstart\n * handler — the BlockDragAnchorOverlay wires its own dragstart on\n * every mount (trigger 'hover'). Keeps widgets on the legacy path by\n * leaving the default `BaseElement` behavior (method missing → falsy).\n * Also falls back to legacy-path-skipped for inner blocks (see §D54).\n */\n }, {\n key: \"usesOverlayDragAnchor\",\n value: function usesOverlayDragAnchor() {\n return !this._isInsideCell();\n }\n\n /**\n * True if this block's direct container is a CellElement. Legacy rule:\n * only top-level page blocks are draggable; blocks inside cells are\n * fixed-in-place. Preserves the implicit legacy invariant explicitly\n * now that `getOverlays()` is authoritative for anchor visibility.\n */\n }, {\n key: \"_isInsideCell\",\n value: function _isInsideCell() {\n return !!(this.container && typeof this.container.getClassName === 'function' && this.container.getClassName() === 'CellElement');\n }\n }, {\n key: \"canDropOn\",\n value: function canDropOn(element) {\n // Existing blocks cannot be dragged into cells — only widgets can.\n // PricingCardElement (2026-04-18) is a CellElement subclass serving as\n // a pricing-card container; same rule applies. FormContainerCell is\n // deliberately left out: it also extends CellElement but has always\n // accepted block drags (form-area append UX); do not tighten that.\n var cellTypes = ['CellElement', 'PricingCardElement'];\n if (cellTypes.includes(element.getClassName())) {\n return false;\n }\n if (element.container && cellTypes.includes(element.container.getClassName())) {\n return false;\n }\n return element.isDroppable();\n }\n }, {\n key: \"removeAfterDrop\",\n value: function removeAfterDrop() {\n return true;\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var e = new this(data.template);\n var elems = Array.isArray(data.elements) ? data.elements : [];\n e.appendElements(elems.map(function (item) {\n return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(item);\n }));\n return this.parseFormats(e, data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BlockElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BlockElement.js?");
/***/ }),
/***/ "./src/includes/BorderControl.js":
/*!***************************************!*\
!*** ./src/includes/BorderControl.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * BorderControl — per-side border editor (style / width / color).\n *\n * Phase 3 refactor (2026-04-19) —\n * Replaces the Phase-2.12b composite with a showcase-aligned\n * pro-grade editor: mode segmented (All / Split), quick presets\n * (None / Thin / Medium / Thick), icon-based style picker with\n * real stroke previews, canonical `.bjs-number-step` + `.bjs-number-\n * value` + `.bjs-color-input` (swatch + hex) primitives, and a\n * live 72px preview tile that mirrors the current values.\n *\n * Root-cause of the visible-broken stepper: the old render wrote\n * `.bjs-number-input-btn` / `.bjs-number-input-value` (non-canonical\n * class names that have no CSS). The canonical primitives in\n * builder.css are `.bjs-number-step` and `.bjs-number-value`. Using\n * them inherits all the hover / focus / disabled / dark-mode styling\n * for free.\n *\n * Backward-compat (non-negotiable, do not break):\n * - Data contract: reads/writes the same 12 flat keys\n * `border_{top|right|bottom|left}_{style|width|color}`.\n * - Callback shape: still invokes `callback.setBorder(top_style,\n * top_width, top_color, bottom_style, bottom_width, bottom_color,\n * left_style, left_width, left_color, right_style, right_width,\n * right_color)` with the same 12-arg signature + positional order\n * the 13 existing consumers (Block / Button / Image / TextInput /\n * HTML / Video / Youtube / Alert / Label / SubmitButton / RSS /\n * Cell / Table) rely on.\n * - All `[data-role=\"…\"]` hooks used by e2e specs are preserved\n * (header, body, all-sides, per-side, style, width, color, minus,\n * plus). New roles added for the new affordances (mode-all,\n * mode-split, preset, copy-to-all, reset, preview-tile, color-hex,\n * color-preview).\n *\n * New opt-in contract (`opts` arg, ignored by legacy callers):\n * - `opts.onChange({ top, right, bottom, left })` — preferred, object-\n * shaped patch (each side = `{ style, width, color }`).\n * - `opts.showPreview` (default true).\n * - `opts.namespace` — lets a single element host two independent\n * BorderControl instances that don't cross-talk (e.g. inner border\n * vs outer border).\n *\n * No-flicker rule (BUILDER.md Lesson 19):\n * `_emitValues()` / `_syncUI()` / `_syncPreview()` NEVER re-`innerHTML`\n * the control during pointer/keystroke events — they only mutate\n * `input.value`, toggle `aria-checked` / `hidden` / `is-active`, and\n * set inline `style` on the preview tile in-place. Mode switch\n * (All ↔ Split) is the single permitted rebuild and still only\n * toggles `hidden` between two pre-rendered containers — no DOM\n * churn.\n */\n\nvar SIDES = ['top', 'right', 'bottom', 'left'];\n\n// Visible style choices in the icon segmented. Five CSS styles that\n// render reliably in modern email clients + modern browsers. Legacy\n// CSS styles (groove / ridge / inset / outset / hidden) are read +\n// preserved from data but not exposed in the icon picker — follow-up\n// epic can surface them via a `More styles` overflow if demand exists.\nvar STYLE_CHOICES = ['solid', 'dashed', 'dotted', 'double', 'none'];\n\n// SVG stroke previews for each style — 20×14 viewBox, currentColor\n// so the icon inherits the segmented button's text color (flips to\n// white when active). Kept inline so the control has no external\n// asset dependency.\nvar STYLE_PREVIEW_SVG = {\n solid: '<svg width=\"22\" height=\"14\" viewBox=\"0 0 22 14\" aria-hidden=\"true\"><line x1=\"2\" y1=\"7\" x2=\"20\" y2=\"7\" stroke=\"currentColor\" stroke-width=\"2\"/></svg>',\n dashed: '<svg width=\"22\" height=\"14\" viewBox=\"0 0 22 14\" aria-hidden=\"true\"><line x1=\"2\" y1=\"7\" x2=\"20\" y2=\"7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"4 2.5\"/></svg>',\n dotted: '<svg width=\"22\" height=\"14\" viewBox=\"0 0 22 14\" aria-hidden=\"true\"><line x1=\"2\" y1=\"7\" x2=\"20\" y2=\"7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-dasharray=\"0.5 3\"/></svg>',\n \"double\": '<svg width=\"22\" height=\"14\" viewBox=\"0 0 22 14\" aria-hidden=\"true\"><line x1=\"2\" y1=\"5\" x2=\"20\" y2=\"5\" stroke=\"currentColor\" stroke-width=\"1.5\"/><line x1=\"2\" y1=\"9\" x2=\"20\" y2=\"9\" stroke=\"currentColor\" stroke-width=\"1.5\"/></svg>',\n none: '<svg width=\"22\" height=\"14\" viewBox=\"0 0 22 14\" aria-hidden=\"true\"><line x1=\"3\" y1=\"11\" x2=\"19\" y2=\"3\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.7\"/></svg>'\n};\n\n// Preset widths. Chosen to cover the common range — None, hairline,\n// default, hero. `style: null` means \"don't change\", only the width\n// (and color if unset) gets applied.\nvar PRESETS = {\n none: {\n style: 'none',\n width: 0,\n applyColor: false\n },\n thin: {\n style: 'solid',\n width: 1,\n applyColor: false\n },\n medium: {\n style: 'solid',\n width: 2,\n applyColor: false\n },\n thick: {\n style: 'solid',\n width: 4,\n applyColor: false\n }\n};\nvar HEX_FULL = /^#[0-9a-f]{6}$/i;\nvar HEX_SHORT = /^#[0-9a-f]{3}$/i;\nfunction normaliseHex(value) {\n if (!value) return '';\n var v = String(value).trim().toLowerCase();\n if (HEX_FULL.test(v)) return v;\n if (HEX_SHORT.test(v)) {\n return '#' + v.slice(1).split('').map(function (c) {\n return c + c;\n }).join('');\n }\n var withHash = v.startsWith('#') ? v : '#' + v;\n if (HEX_FULL.test(withHash)) return withHash;\n if (HEX_SHORT.test(withHash)) {\n return '#' + withHash.slice(1).split('').map(function (c) {\n return c + c;\n }).join('');\n }\n return null; // invalid\n}\nvar BorderControl = /*#__PURE__*/function () {\n /**\n * @param {string} label Title for the section header.\n * @param {object} values { border_{top|right|bottom|left}_{style|width|color}: … }\n * @param {object} callback { setBorder(…12 args): Function } — legacy.\n * @param {object} [opts] { onChange, showPreview, namespace }\n */\n function BorderControl(label, values, callback) {\n var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n _classCallCheck(this, BorderControl);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.values = values || {};\n this.callback = callback;\n this.opts = opts || {};\n this.showPreview = this.opts.showPreview !== false;\n this.namespace = this.opts.namespace || 'border';\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-border-control');\n this.domNode.setAttribute('data-namespace', this.namespace);\n this.isCollapsed = false;\n this.showPerSide = !this._allSidesSame();\n this.focusedSide = null; // used for preview highlight + preset targeting in Split\n\n this.render();\n }\n\n /** True when every side has the same style/width/color — drives the\n * auto-select between All (uniform) and Split modes on first mount\n * so the author sees their actual data immediately. */\n return _createClass(BorderControl, [{\n key: \"_allSidesSame\",\n value: function _allSidesSame() {\n var v = this.values;\n var first = {\n style: v[\"border_\".concat(SIDES[0], \"_style\")] || 'none',\n width: parseInt(v[\"border_\".concat(SIDES[0], \"_width\")], 10) || 0,\n color: (v[\"border_\".concat(SIDES[0], \"_color\")] || '#000000').toLowerCase()\n };\n return SIDES.every(function (s) {\n var style = v[\"border_\".concat(s, \"_style\")] || 'none';\n var width = parseInt(v[\"border_\".concat(s, \"_width\")], 10) || 0;\n var color = (v[\"border_\".concat(s, \"_color\")] || '#000000').toLowerCase();\n return style === first.style && width === first.width && color === first.color;\n });\n }\n }, {\n key: \"_readSide\",\n value: function _readSide(side) {\n var v = this.values;\n return {\n style: v[\"border_\".concat(side, \"_style\")] || 'solid',\n width: parseInt(v[\"border_\".concat(side, \"_width\")], 10) || 0,\n color: v[\"border_\".concat(side, \"_color\")] || '#000000'\n };\n }\n }, {\n key: \"render\",\n value: function render() {\n var rowsAll = this._renderUniformBody();\n var rowsSplit = this._renderSplitBody();\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-section-header bjs-border-control-header\\\" data-role=\\\"header\\\" role=\\\"button\\\" tabindex=\\\"0\\\" aria-expanded=\\\"\".concat(!this.isCollapsed, \"\\\">\\n <div class=\\\"bjs-border-control-header-text\\\">\\n <span class=\\\"bjs-section-header-title\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.title'), \"</span>\\n <span class=\\\"bjs-section-header-desc\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.description'), \"</span>\\n </div>\\n <div class=\\\"bjs-border-control-header-actions\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-border-control-reset\\\" data-role=\\\"reset\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.reset', 'Reset borders'), \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.reset', 'Reset borders'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">restart_alt</span>\\n </button>\\n <span class=\\\"material-symbols-rounded bjs-section-header-caret\\\" aria-hidden=\\\"true\\\">keyboard_arrow_down</span>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-border-control-body\\\" data-role=\\\"body\\\" \").concat(this.isCollapsed ? 'hidden' : '', \">\\n <div class=\\\"bjs-border-control-mode-row\\\">\\n <span class=\\\"bjs-border-control-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.mode_label', 'Mode'), \"</span>\\n <div class=\\\"bjs-segmented bjs-border-mode-seg\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.mode_label', 'Mode'), \"\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-segmented-btn \").concat(!this.showPerSide ? 'is-active' : '', \"\\\" data-role=\\\"mode-all\\\" role=\\\"radio\\\" aria-checked=\\\"\").concat(!this.showPerSide, \"\\\" tabindex=\\\"\").concat(!this.showPerSide ? '0' : '-1', \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">border_outer</span>\\n <span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.mode_all', 'All'), \"</span>\\n </button>\\n <button type=\\\"button\\\" class=\\\"bjs-segmented-btn \").concat(this.showPerSide ? 'is-active' : '', \"\\\" data-role=\\\"mode-split\\\" role=\\\"radio\\\" aria-checked=\\\"\").concat(this.showPerSide, \"\\\" tabindex=\\\"\").concat(this.showPerSide ? '0' : '-1', \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">border_all</span>\\n <span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.mode_split', 'Split'), \"</span>\\n </button>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-border-control-preset-row\\\">\\n <span class=\\\"bjs-border-control-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_label', 'Preset'), \"</span>\\n <div class=\\\"bjs-segmented bjs-border-preset-seg\\\" role=\\\"group\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_label', 'Preset'), \"\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\\\" data-role=\\\"preset\\\" data-preset=\\\"none\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_none', 'None'), \"</button>\\n <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\\\" data-role=\\\"preset\\\" data-preset=\\\"thin\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_thin', 'Thin'), \"</button>\\n <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\\\" data-role=\\\"preset\\\" data-preset=\\\"medium\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_medium', 'Medium'), \"</button>\\n <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\\\" data-role=\\\"preset\\\" data-preset=\\\"thick\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_thick', 'Thick'), \"</button>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-border-control-rows bjs-border-control-rows--uniform\\\" data-role=\\\"all-sides\\\" \").concat(this.showPerSide ? 'hidden' : '', \">\\n \").concat(rowsAll, \"\\n </div>\\n\\n <div class=\\\"bjs-border-control-rows bjs-border-control-rows--split\\\" data-role=\\\"per-side\\\" \").concat(this.showPerSide ? '' : 'hidden', \">\\n \").concat(rowsSplit, \"\\n </div>\\n </div>\\n \");\n this._bindEvents();\n this._syncUI();\n }\n }, {\n key: \"_renderUniformBody\",\n value: function _renderUniformBody() {\n var state = this._readSide('top'); // authoritative when sides are in sync\n return \"\\n <div class=\\\"bjs-border-control-uniform-body\\\">\\n <div class=\\\"bjs-border-control-row\\\" data-side=\\\"all\\\">\\n <span class=\\\"bjs-border-control-side-label\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.all_sides', 'All sides'), \"</span>\\n \").concat(this._renderRowInputs('all', state, {\n compact: false,\n withCopy: false\n }), \"\\n </div>\\n \").concat(this.showPreview ? this._renderPreview('uniform') : '', \"\\n </div>\\n \");\n }\n }, {\n key: \"_renderSplitBody\",\n value: function _renderSplitBody() {\n var _this = this;\n var rows = SIDES.map(function (side) {\n return \"\\n <div class=\\\"bjs-border-control-row bjs-border-control-row--compact\\\" data-side=\\\"\".concat(side, \"\\\">\\n <div class=\\\"bjs-border-control-side-column\\\">\\n <span class=\\\"bjs-border-control-side-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.' + side, side.charAt(0).toUpperCase() + side.slice(1)), \"</span>\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-border-copy-btn\\\" data-role=\\\"copy-to-all\\\"\\n data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.copy_to_all', 'Copy this side to all sides'), \"\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.copy_to_all', 'Copy this side to all sides'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">content_copy</span>\\n </button>\\n </div>\\n \").concat(_this._renderRowInputs(side, _this._readSide(side), {\n compact: true,\n withCopy: false\n }), \"\\n </div>\\n \");\n }).join('');\n return \"\\n <div class=\\\"bjs-border-control-split-body\\\">\\n <div class=\\\"bjs-border-control-split-rows\\\">\\n \".concat(rows, \"\\n </div>\\n \").concat(this.showPreview ? this._renderPreview('split') : '', \"\\n </div>\\n \");\n }\n }, {\n key: \"_renderRowInputs\",\n value: function _renderRowInputs(side, state, _ref) {\n var compact = _ref.compact,\n withCopy = _ref.withCopy;\n var styleBtns = STYLE_CHOICES.map(function (s) {\n return \"\\n <button type=\\\"button\\\"\\n class=\\\"bjs-segmented-btn bjs-border-style-btn \".concat(state.style === s ? 'is-active' : '', \"\\\"\\n data-role=\\\"style\\\" data-style=\\\"\").concat(s, \"\\\"\\n role=\\\"radio\\\" aria-checked=\\\"\").concat(state.style === s, \"\\\"\\n data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.style_' + s, s), \"\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.style_' + s, s), \"\\\"\\n tabindex=\\\"\").concat(state.style === s ? '0' : '-1', \"\\\">\\n \").concat(STYLE_PREVIEW_SVG[s], \"\\n </button>\\n \");\n }).join('');\n var copyBtn = withCopy ? \"\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-border-copy-btn\\\" data-role=\\\"copy-to-all\\\"\\n data-tooltip=\\\"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.copy_to_all', 'Copy this side to all sides'), \"\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.copy_to_all', 'Copy this side to all sides'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">content_copy</span>\\n </button>\\n \") : '';\n return \"\\n <div class=\\\"bjs-border-control-inputs \".concat(compact ? 'bjs-border-control-inputs--compact' : '', \"\\\">\\n <div class=\\\"bjs-segmented bjs-border-style-seg\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.style_label', 'Border style'), \"\\\">\\n \").concat(styleBtns, \"\\n </div>\\n <div class=\\\"bjs-number-input bjs-border-width-input\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-role=\\\"minus\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('number.decrement', 'Decrease'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">remove</span>\\n </button>\\n <input type=\\\"number\\\" class=\\\"bjs-number-value\\\" data-role=\\\"width\\\" value=\\\"\").concat(state.width, \"\\\" min=\\\"0\\\" max=\\\"999\\\" step=\\\"1\\\" aria-valuemin=\\\"0\\\" aria-valuemax=\\\"999\\\" aria-valuenow=\\\"\").concat(state.width, \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.width_label', 'Border width (px)'), \"\\\">\\n <span class=\\\"bjs-number-unit\\\" aria-hidden=\\\"true\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.width_unit', 'px'), \"</span>\\n <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-role=\\\"plus\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('number.increment', 'Increase'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">add</span>\\n </button>\\n </div>\\n <div class=\\\"bjs-color-input bjs-border-color-input\\\">\\n <label class=\\\"bjs-color-swatch\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.color_label', 'Border color'), \"\\\">\\n <input type=\\\"color\\\" class=\\\"bjs-color-native\\\" data-role=\\\"color\\\" value=\\\"\").concat(state.color, \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.color_label', 'Border color'), \"\\\">\\n <span class=\\\"bjs-color-preview\\\" data-role=\\\"color-preview\\\"></span>\\n </label>\\n <input type=\\\"text\\\" class=\\\"bjs-color-hex\\\" data-role=\\\"color-hex\\\" value=\\\"\").concat(state.color, \"\\\" placeholder=\\\"#000000\\\" maxlength=\\\"7\\\" autocomplete=\\\"off\\\" spellcheck=\\\"false\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.color_label', 'Border color'), \"\\\">\\n </div>\\n \").concat(copyBtn, \"\\n </div>\\n \");\n }\n }, {\n key: \"_renderPreview\",\n value: function _renderPreview(mode) {\n return \"\\n <div class=\\\"bjs-border-control-preview bjs-border-control-preview--\".concat(mode, \"\\\" data-role=\\\"preview\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"bjs-border-control-preview-tile\\\" data-role=\\\"preview-tile\\\"></div>\\n <span class=\\\"bjs-border-control-preview-caption\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preview_aria', 'Preview'), \"</span>\\n </div>\\n <span class=\\\"bjs-sr-only\\\" aria-live=\\\"polite\\\" data-role=\\\"preview-announce\\\"></span>\\n \");\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this2 = this;\n var root = this.domNode;\n var header = root.querySelector('[data-role=\"header\"]');\n var body = root.querySelector('[data-role=\"body\"]');\n\n // Header collapse — click + keyboard.\n var toggleCollapsed = function toggleCollapsed() {\n _this2.isCollapsed = !_this2.isCollapsed;\n header.setAttribute('aria-expanded', String(!_this2.isCollapsed));\n if (_this2.isCollapsed) body.setAttribute('hidden', '');else body.removeAttribute('hidden');\n };\n header.addEventListener('click', function (e) {\n // Don't collapse when the reset icon-btn inside the header is\n // clicked — it's an independent affordance.\n if (e.target.closest('[data-role=\"reset\"]')) return;\n toggleCollapsed();\n });\n header.addEventListener('keydown', function (e) {\n if (e.key === 'Enter' || e.key === ' ') {\n if (e.target.closest('[data-role=\"reset\"]')) return;\n e.preventDefault();\n toggleCollapsed();\n }\n });\n\n // Reset — clears all 4 sides.\n var resetBtn = root.querySelector('[data-role=\"reset\"]');\n if (resetBtn) {\n resetBtn.addEventListener('click', function (e) {\n e.stopPropagation();\n SIDES.forEach(function (s) {\n _this2.values[\"border_\".concat(s, \"_style\")] = 'none';\n _this2.values[\"border_\".concat(s, \"_width\")] = 0;\n _this2.values[\"border_\".concat(s, \"_color\")] = '#000000';\n });\n _this2._syncUI();\n _this2._emitValues(/*fromUI*/false);\n });\n }\n\n // Mode segmented — flip between uniform and split bodies.\n this._bindModeSegmented(root);\n\n // Preset chips.\n this._bindPresets(root);\n\n // Row-level handlers — style icons, width stepper + input, color.\n root.querySelectorAll('.bjs-border-control-row').forEach(function (row) {\n return _this2._bindRow(row);\n });\n this._syncColorPreviews();\n this._syncPreview();\n }\n }, {\n key: \"_bindModeSegmented\",\n value: function _bindModeSegmented(root) {\n var _this3 = this;\n var all = root.querySelector('[data-role=\"mode-all\"]');\n var split = root.querySelector('[data-role=\"mode-split\"]');\n var allBody = root.querySelector('[data-role=\"all-sides\"]');\n var splitBody = root.querySelector('[data-role=\"per-side\"]');\n var select = function select(toSplit) {\n _this3.showPerSide = toSplit;\n all.classList.toggle('is-active', !toSplit);\n split.classList.toggle('is-active', toSplit);\n all.setAttribute('aria-checked', String(!toSplit));\n split.setAttribute('aria-checked', String(toSplit));\n all.setAttribute('tabindex', toSplit ? '-1' : '0');\n split.setAttribute('tabindex', toSplit ? '0' : '-1');\n if (toSplit) {\n allBody.setAttribute('hidden', '');\n splitBody.removeAttribute('hidden');\n } else {\n splitBody.setAttribute('hidden', '');\n allBody.removeAttribute('hidden');\n }\n // When switching from split → all, broadcast top's values so\n // all sides converge (matches the \"All sides\" semantic).\n if (!toSplit) {\n var src = _this3._readSide('top');\n SIDES.forEach(function (s) {\n _this3.values[\"border_\".concat(s, \"_style\")] = src.style;\n _this3.values[\"border_\".concat(s, \"_width\")] = src.width;\n _this3.values[\"border_\".concat(s, \"_color\")] = src.color;\n });\n _this3._syncUI();\n _this3._emitValues(false);\n } else {\n _this3._syncUI();\n }\n };\n all.addEventListener('click', function () {\n return select(false);\n });\n split.addEventListener('click', function () {\n return select(true);\n });\n\n // Arrow-key nav inside the segmented group.\n var onKey = function onKey(btns) {\n return function (e) {\n var idx = btns.indexOf(document.activeElement);\n if (idx === -1) return;\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault();\n btns[(idx + 1) % btns.length].focus();\n btns[(idx + 1) % btns.length].click();\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault();\n btns[(idx - 1 + btns.length) % btns.length].focus();\n btns[(idx - 1 + btns.length) % btns.length].click();\n }\n };\n };\n var modeBtns = [all, split];\n [all, split].forEach(function (b) {\n return b.addEventListener('keydown', onKey(modeBtns));\n });\n }\n }, {\n key: \"_bindPresets\",\n value: function _bindPresets(root) {\n var _this4 = this;\n root.querySelectorAll('[data-role=\"preset\"]').forEach(function (btn) {\n btn.addEventListener('click', function (e) {\n var key = btn.getAttribute('data-preset');\n var preset = PRESETS[key];\n if (!preset) return;\n var targetSides = _this4.showPerSide && _this4.focusedSide ? [_this4.focusedSide] : SIDES;\n // Alt/Option held on a preset chip = apply to all sides\n // regardless of focused side. (Power-user shortcut.)\n var apply = e.altKey ? SIDES : targetSides;\n apply.forEach(function (s) {\n _this4.values[\"border_\".concat(s, \"_style\")] = preset.style;\n _this4.values[\"border_\".concat(s, \"_width\")] = preset.width;\n // Only overwrite color when it's currently the default black\n // and we're applying a non-none preset — so preset doesn't\n // clobber a user-picked color.\n });\n // Flash visual feedback on the pressed chip.\n btn.classList.add('is-flash');\n setTimeout(function () {\n return btn.classList.remove('is-flash');\n }, 220);\n _this4._syncUI();\n _this4._emitValues(false);\n });\n });\n }\n }, {\n key: \"_bindRow\",\n value: function _bindRow(row) {\n var _this5 = this;\n var side = row.getAttribute('data-side');\n\n // Style icon segmented.\n row.querySelectorAll('[data-role=\"style\"]').forEach(function (btn) {\n btn.addEventListener('click', function () {\n var value = btn.getAttribute('data-style');\n _this5._setRowStyle(row, value);\n _this5._emitValues(false);\n });\n btn.addEventListener('keydown', function (e) {\n var btns = Array.from(row.querySelectorAll('[data-role=\"style\"]'));\n var idx = btns.indexOf(document.activeElement);\n if (idx === -1) return;\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault();\n var nxt = btns[(idx + 1) % btns.length];\n nxt.focus();\n nxt.click();\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault();\n var prv = btns[(idx - 1 + btns.length) % btns.length];\n prv.focus();\n prv.click();\n }\n });\n });\n\n // Width — stepper + input + keyboard shortcuts.\n var width = row.querySelector('[data-role=\"width\"]');\n var minus = row.querySelector('[data-role=\"minus\"]');\n var plus = row.querySelector('[data-role=\"plus\"]');\n var clampWidth = function clampWidth(v) {\n return Math.max(0, Math.min(999, parseInt(v, 10) || 0));\n };\n var bumpWidth = function bumpWidth(delta) {\n width.value = clampWidth(parseInt(width.value, 10) + delta);\n width.setAttribute('aria-valuenow', width.value);\n _this5._emitValues(true);\n };\n minus.addEventListener('click', function () {\n return bumpWidth(-1);\n });\n plus.addEventListener('click', function () {\n return bumpWidth(1);\n });\n width.addEventListener('input', function () {\n width.setAttribute('aria-valuenow', width.value || '0');\n _this5._emitValues(true);\n });\n width.addEventListener('blur', function () {\n width.value = clampWidth(width.value);\n width.setAttribute('aria-valuenow', width.value);\n _this5._emitValues(true);\n });\n width.addEventListener('keydown', function (e) {\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n var step = e.shiftKey ? 10 : 1;\n bumpWidth(e.key === 'ArrowUp' ? step : -step);\n }\n });\n\n // Color — native picker + hex textbox.\n var color = row.querySelector('[data-role=\"color\"]');\n var hex = row.querySelector('[data-role=\"color-hex\"]');\n color.addEventListener('input', function () {\n hex.value = color.value.toLowerCase();\n hex.classList.remove('is-error');\n _this5._syncColorPreviews();\n _this5._emitValues(true);\n });\n hex.addEventListener('input', function () {\n var normalised = normaliseHex(hex.value);\n if (normalised) {\n hex.classList.remove('is-error');\n color.value = normalised;\n _this5._syncColorPreviews();\n _this5._emitValues(true);\n } else {\n // Keep showing the typed value; flag as error so the user\n // sees it's invalid (red border on the hex input).\n hex.classList.add('is-error');\n }\n });\n hex.addEventListener('blur', function () {\n var normalised = normaliseHex(hex.value);\n if (!normalised) {\n // Revert to the currently-stored color on blur so we never\n // persist an invalid value.\n hex.value = color.value;\n hex.classList.remove('is-error');\n } else {\n hex.value = normalised;\n }\n });\n\n // Focus tracking for preview-highlight + preset targeting.\n row.addEventListener('focusin', function () {\n _this5.focusedSide = side;\n _this5._syncPreviewHighlight();\n });\n row.addEventListener('mouseenter', function () {\n _this5.focusedSide = side;\n _this5._syncPreviewHighlight();\n });\n row.addEventListener('mouseleave', function () {\n _this5.focusedSide = null;\n _this5._syncPreviewHighlight();\n });\n\n // Copy-to-all.\n var copy = row.querySelector('[data-role=\"copy-to-all\"]');\n if (copy) {\n copy.addEventListener('click', function () {\n var src = _this5._readRowValues(row);\n SIDES.forEach(function (s) {\n _this5.values[\"border_\".concat(s, \"_style\")] = src.style;\n _this5.values[\"border_\".concat(s, \"_width\")] = src.width;\n _this5.values[\"border_\".concat(s, \"_color\")] = src.color;\n });\n copy.classList.add('is-flash');\n setTimeout(function () {\n return copy.classList.remove('is-flash');\n }, 220);\n _this5._syncUI();\n _this5._emitValues(false);\n });\n }\n }\n\n /** In-place style selection — toggles aria-checked + is-active on the\n * row's style buttons + updates tabindex for roving-focus; no innerHTML. */\n }, {\n key: \"_setRowStyle\",\n value: function _setRowStyle(row, value) {\n row.querySelectorAll('[data-role=\"style\"]').forEach(function (b) {\n var match = b.getAttribute('data-style') === value;\n b.classList.toggle('is-active', match);\n b.setAttribute('aria-checked', String(match));\n b.setAttribute('tabindex', match ? '0' : '-1');\n });\n }\n }, {\n key: \"_readRowValues\",\n value: function _readRowValues(row) {\n var styleBtn = row.querySelector('[data-role=\"style\"].is-active') || row.querySelector('[data-role=\"style\"]');\n var style = styleBtn ? styleBtn.getAttribute('data-style') : 'solid';\n var width = Math.max(0, Math.min(999, parseInt(row.querySelector('[data-role=\"width\"]').value, 10) || 0));\n var color = row.querySelector('[data-role=\"color\"]').value || '#000000';\n return {\n style: style,\n width: width,\n color: color\n };\n }\n\n /** Populate UI from this.values (mutates input.value + aria + toggle\n * .is-active; never innerHTML). Keeps focus intact. */\n }, {\n key: \"_syncUI\",\n value: function _syncUI() {\n var _this6 = this;\n var allRow = this.domNode.querySelector('[data-role=\"all-sides\"] .bjs-border-control-row');\n if (allRow) this._writeSideToRow(allRow, this._readSide('top'));\n SIDES.forEach(function (side) {\n var row = _this6.domNode.querySelector(\"[data-role=\\\"per-side\\\"] .bjs-border-control-row[data-side=\\\"\".concat(side, \"\\\"]\"));\n if (row) _this6._writeSideToRow(row, _this6._readSide(side));\n });\n this._syncColorPreviews();\n this._syncPreview();\n }\n }, {\n key: \"_writeSideToRow\",\n value: function _writeSideToRow(row, state) {\n // Style icons.\n row.querySelectorAll('[data-role=\"style\"]').forEach(function (b) {\n var match = b.getAttribute('data-style') === state.style;\n b.classList.toggle('is-active', match);\n b.setAttribute('aria-checked', String(match));\n b.setAttribute('tabindex', match ? '0' : '-1');\n });\n // Width.\n var w = row.querySelector('[data-role=\"width\"]');\n if (w) {\n w.value = state.width;\n w.setAttribute('aria-valuenow', state.width);\n }\n // Color.\n var c = row.querySelector('[data-role=\"color\"]');\n var h = row.querySelector('[data-role=\"color-hex\"]');\n if (c) c.value = state.color;\n if (h) {\n h.value = state.color;\n h.classList.remove('is-error');\n }\n }\n }, {\n key: \"_syncColorPreviews\",\n value: function _syncColorPreviews() {\n this.domNode.querySelectorAll('.bjs-border-control-row').forEach(function (row) {\n var inp = row.querySelector('[data-role=\"color\"]');\n var pre = row.querySelector('[data-role=\"color-preview\"]');\n if (inp && pre) pre.style.setProperty('--bjs-color-current', inp.value || 'transparent');\n });\n }\n\n /** Mutate inline style on the preview tile(s) — NEVER rebuild. */\n }, {\n key: \"_syncPreview\",\n value: function _syncPreview() {\n var _this7 = this;\n if (!this.showPreview) return;\n this.domNode.querySelectorAll('[data-role=\"preview-tile\"]').forEach(function (tile) {\n var sides = SIDES.map(function (s) {\n return _objectSpread({\n side: s\n }, _this7._readSide(s));\n });\n sides.forEach(function (_ref2) {\n var side = _ref2.side,\n style = _ref2.style,\n width = _ref2.width,\n color = _ref2.color;\n // `none` with 0 width collapses visually; the tile's own\n // base border (from CSS) keeps the box visible so the user\n // still sees something to edit.\n tile.style[\"border\".concat(side.charAt(0).toUpperCase() + side.slice(1))] = \"\".concat(width, \"px \").concat(style === 'none' ? 'none' : style, \" \").concat(color);\n });\n });\n var ann = this.domNode.querySelector('[data-role=\"preview-announce\"]');\n if (ann) {\n var top = this._readSide('top');\n ann.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preview_announce', \"Border: \".concat(top.style, \" \").concat(top.width, \"px \").concat(top.color));\n }\n this._syncPreviewHighlight();\n }\n }, {\n key: \"_syncPreviewHighlight\",\n value: function _syncPreviewHighlight() {\n var _this8 = this;\n var tiles = this.domNode.querySelectorAll('[data-role=\"preview-tile\"]');\n tiles.forEach(function (t) {\n return t.setAttribute('data-highlight', _this8.focusedSide || '');\n });\n }\n\n /** Read UI, update this.values, invoke legacy setBorder(…12) +\n * optional opts.onChange(patch). `fromUI=true` means the caller\n * is a live input event (keystroke/stepper) — we STILL invoke the\n * callback but skip `_syncUI()` to preserve focus. */\n }, {\n key: \"_emitValues\",\n value: function _emitValues(fromUI) {\n var _this9 = this;\n var patch = {\n top: null,\n right: null,\n bottom: null,\n left: null\n };\n if (!this.showPerSide) {\n var row = this.domNode.querySelector('[data-role=\"all-sides\"] .bjs-border-control-row');\n if (!row) return;\n var side = this._readRowValues(row);\n SIDES.forEach(function (s) {\n _this9.values[\"border_\".concat(s, \"_style\")] = side.style;\n _this9.values[\"border_\".concat(s, \"_width\")] = side.width;\n _this9.values[\"border_\".concat(s, \"_color\")] = side.color;\n patch[s] = _objectSpread({}, side);\n });\n } else {\n SIDES.forEach(function (s) {\n var row = _this9.domNode.querySelector(\"[data-role=\\\"per-side\\\"] .bjs-border-control-row[data-side=\\\"\".concat(s, \"\\\"]\"));\n if (!row) return;\n var v = _this9._readRowValues(row);\n _this9.values[\"border_\".concat(s, \"_style\")] = v.style;\n _this9.values[\"border_\".concat(s, \"_width\")] = v.width;\n _this9.values[\"border_\".concat(s, \"_color\")] = v.color;\n patch[s] = _objectSpread({}, v);\n });\n }\n this._syncPreview();\n if (this.callback && typeof this.callback.setBorder === 'function') {\n this.callback.setBorder(this.values.border_top_style, this.values.border_top_width, this.values.border_top_color, this.values.border_bottom_style, this.values.border_bottom_width, this.values.border_bottom_color, this.values.border_left_style, this.values.border_left_width, this.values.border_left_color, this.values.border_right_style, this.values.border_right_width, this.values.border_right_color);\n }\n if (this.opts && typeof this.opts.onChange === 'function') {\n this.opts.onChange(patch);\n }\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BorderControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BorderControl.js?");
/***/ }),
/***/ "./src/includes/BorderRadiusControl.js":
/*!*********************************************!*\
!*** ./src/includes/BorderRadiusControl.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar MIN = 0;\nvar MAX = 200;\nvar DEBOUNCE_MS = 100;\nvar BorderRadiusControl = /*#__PURE__*/function () {\n function BorderRadiusControl() {\n var label = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Radius';\n var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {\n setRadius: function setRadius() {}\n };\n _classCallCheck(this, BorderRadiusControl);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = this._clamp(value);\n this.callback = callback;\n this.debounceTimeout = null;\n this.domNode = document.createElement('div');\n this.render();\n }\n return _createClass(BorderRadiusControl, [{\n key: \"render\",\n value: function render() {\n var pct = (this.value - MIN) / (MAX - MIN) * 100;\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\"><span>\".concat(this.label, \"</span></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-slider\\\">\\n <input type=\\\"range\\\" class=\\\"bjs-slider-track\\\"\\n min=\\\"\").concat(MIN, \"\\\" max=\\\"\").concat(MAX, \"\\\" step=\\\"1\\\" value=\\\"\").concat(this.value, \"\\\"\\n id=\\\"\").concat(this.id, \"\\\" aria-label=\\\"\").concat(this.label, \"\\\"\\n style=\\\"--pct: \").concat(pct, \"%\\\">\\n <div class=\\\"bjs-slider-value\\\">\\n <input type=\\\"number\\\" class=\\\"bjs-number-value\\\"\\n min=\\\"\").concat(MIN, \"\\\" max=\\\"\").concat(MAX, \"\\\" step=\\\"1\\\" value=\\\"\").concat(this.value, \"\\\"\\n aria-label=\\\"\").concat(this.label, \" (px)\\\">\\n <span class=\\\"bjs-number-unit\\\">px</span>\\n </div>\\n </div>\\n </div>\\n </div>\\n \");\n this._bindEvents();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this = this;\n var rangeInput = this.domNode.querySelector('.bjs-slider-track');\n var numberInput = this.domNode.querySelector('.bjs-number-value');\n rangeInput.addEventListener('input', function () {\n _this._setValue(parseInt(rangeInput.value, 10) || 0, {\n source: 'range'\n });\n });\n numberInput.addEventListener('input', function () {\n // Allow intermediate empty string while typing — commit on blur.\n var raw = numberInput.value;\n if (raw === '') return;\n _this._setValue(parseInt(raw, 10) || 0, {\n source: 'number'\n });\n });\n numberInput.addEventListener('blur', function () {\n // Empty commits to MIN; ensures the field never stays blank.\n if (numberInput.value === '') {\n _this._setValue(MIN, {\n source: 'number'\n });\n }\n });\n }\n }, {\n key: \"_setValue\",\n value: function _setValue(raw) {\n var _this2 = this;\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n source = _ref.source;\n var clamped = this._clamp(raw);\n this.value = clamped;\n var rangeInput = this.domNode.querySelector('.bjs-slider-track');\n var numberInput = this.domNode.querySelector('.bjs-number-value');\n if (rangeInput && source !== 'range') rangeInput.value = clamped;\n if (numberInput && source !== 'number') numberInput.value = clamped;\n\n // Sync the track-fill CSS var so the filled portion matches the thumb.\n if (rangeInput) {\n var pct = (clamped - MIN) / (MAX - MIN) * 100;\n rangeInput.style.setProperty('--pct', pct + '%');\n }\n clearTimeout(this.debounceTimeout);\n this.debounceTimeout = setTimeout(function () {\n if (_this2.callback && typeof _this2.callback.setRadius === 'function') {\n _this2.callback.setRadius(_this2.value);\n }\n }, DEBOUNCE_MS);\n }\n }, {\n key: \"_clamp\",\n value: function _clamp(n) {\n var num = typeof n === 'number' ? n : parseInt(n, 10) || 0;\n return Math.max(MIN, Math.min(MAX, num));\n }\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n var clamped = this._clamp(newValue);\n if (clamped === this.value) return;\n this.value = clamped;\n var rangeInput = this.domNode.querySelector('.bjs-slider-track');\n var numberInput = this.domNode.querySelector('.bjs-number-value');\n if (rangeInput) rangeInput.value = clamped;\n if (numberInput) numberInput.value = clamped;\n if (rangeInput) {\n var pct = (clamped - MIN) / (MAX - MIN) * 100;\n rangeInput.style.setProperty('--pct', pct + '%');\n }\n if (this.callback && typeof this.callback.setRadius === 'function') {\n this.callback.setRadius(this.value);\n }\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BorderRadiusControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BorderRadiusControl.js?");
/***/ }),
/***/ "./src/includes/Builder.js":
/*!*********************************!*\
!*** ./src/includes/Builder.js ***!
\*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _PageElement_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PageElement.js */ \"./src/includes/PageElement.js\");\n/* harmony import */ var _UIManager_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./UIManager.js */ \"./src/includes/UIManager.js\");\n/* harmony import */ var _SettingsTabManager_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./SettingsTabManager.js */ \"./src/includes/SettingsTabManager.js\");\n/* harmony import */ var _BuilderJsonStructureValidator_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BuilderJsonStructureValidator.js */ \"./src/includes/BuilderJsonStructureValidator.js\");\n/* harmony import */ var _EventEmitter_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./EventEmitter.js */ \"./src/includes/EventEmitter.js\");\n/* harmony import */ var _ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ui/holedBoxClipPath.js */ \"./src/includes/ui/holedBoxClipPath.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./TextSelectionTracker.js */ \"./src/includes/TextSelectionTracker.js\");\n/* harmony import */ var _overlays_TextInlineToolbarOverlay_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./overlays/TextInlineToolbarOverlay.js */ \"./src/includes/overlays/TextInlineToolbarOverlay.js\");\n/* harmony import */ var _TextInlineKeyboardShortcuts_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./TextInlineKeyboardShortcuts.js */ \"./src/includes/TextInlineKeyboardShortcuts.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./BuilderjsPopup.js */ \"./src/includes/BuilderjsPopup.js\");\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\n/* harmony import */ var _HistoryManager_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./HistoryManager.js */ \"./src/includes/HistoryManager.js\");\n/* harmony import */ var _HistoryWidget_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./HistoryWidget.js */ \"./src/includes/HistoryWidget.js\");\n/* harmony import */ var _TooltipManager_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./TooltipManager.js */ \"./src/includes/TooltipManager.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar Builder = /*#__PURE__*/function () {\n function Builder(options) {\n var _this$options$loadAss,\n _this = this,\n _options$historyMaxSi,\n _options$historyDebou,\n _options$historyCoale,\n _options$historyAutoC;\n _classCallCheck(this, Builder);\n // Keep the raw options object around so feature flags flow through\n // without every caller having to re-pluck fields. PLAN_EFFECT flags\n // (usePaddingVisualizer, usePaddingRulers, etc.) are read off\n // `builder.options.*` by their consumers.\n //\n // PLAN_EFFECT defaults — explicit `false` from the caller still\n // wins. Default ON during dev so the demo + downstream hosts both\n // see the feature out of the box. Production callers can disable\n // by passing `{ usePaddingVisualizer: false }`.\n this.options = Object.assign({\n usePaddingVisualizer: true\n }, options || {});\n\n // W6.A.A.5 — peer-dependency auto-injection. The engine hard-depends\n // on two runtime peer-deps that dist/builder.{js,css} doesn't ship:\n //\n // 1. Material Symbols Rounded font — referenced as\n // `.material-symbols-rounded` in src/builder.css (24+ rules)\n // and Builder.js innerHTML (breadcrumb · panel-parent · widgets\n // palette · every overlay icon). Without it, glyphs render as\n // raw ligature text (\"arrow_drop_down\", \"edit\", \"code\") all\n // across the chrome.\n // 2. Bootstrap JS bundle — Builder.js + SAlert.js call\n // `new bootstrap.Modal(...)` on Change-Theme / Asset-Upload /\n // Alert flows. Without it, those clicks throw `bootstrap is\n // not defined`.\n //\n // Both are auto-injected at construction time iff missing. Idempotent\n // (skip when already present). Air-gap / China deployments opt out\n // via `new Builder({ loadAssets: false })` and self-host.\n //\n // Default: 'auto' (inject if missing). Pass `false` to skip entirely.\n // No `'force'` mode — multiple Builder instances on one page never\n // need a re-inject.\n this._ensurePeerAssets((_this$options$loadAss = this.options.loadAssets) !== null && _this$options$loadAss !== void 0 ? _this$options$loadAss : 'auto');\n\n // PLAN_EFFECT W2.3 — Alt-hold inspect runtime state. Mirrors the\n // global Alt key — set by `_inspectModeInit()` listeners, read by\n // `BaseElement.addHoverHightlight()` so a NEW hover that mounts\n // mid-Alt-hold gets the inspect class on first paint. Lives on\n // the Builder instance (NOT body class) per the \"scope to overlay,\n // not page\" rule — a sibling host page on the same domain is not\n // affected.\n this._inspectAltDown = false;\n\n // PLAN_EFFECT W3.2 — session-scoped per-element pin state. Lives\n // only on the running Builder instance, never serialized to\n // template JSON. Membership = \"keep the padding visualiser rich\n // whenever this element is selected, regardless of panel focus\".\n this._pinnedPaddingElements = new Set();\n\n // Host-injection state — promoted to explicit constructor init so\n // every Builder instance owns its own slots from t=0 (was previously\n // lazily created by ColorPickerControl / ImageControl on first use,\n // which broke multi-instance because the slots were attached via\n // bare-builder reach-in to whichever instance happened to be set\n // as the page-level global). See Lesson \"Host Injection\" in\n // BUILDER.md.\n this._activeControls = {};\n this._recentElementColors = [];\n\n // i18n initialization\n _I18n_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].init(options.translations);\n\n // Container resolution.\n //\n // `mainContainer` (canvas) is REQUIRED — every Builder mounts a canvas.\n // `widgetsContainer` and `settingsContainer` are OPTIONAL: pass `null`\n // / `undefined` (or a selector that resolves to no element) and the\n // corresponding sub-system simply does not mount. Cookbook chrome\n // presets (W6 Phase C.B) rely on this to drop sidebars without\n // forcing the buyer to ship hidden orphan `<div>`s.\n //\n // Existing 3-container callers (demo/builder.php and the W6 Phase B\n // examples) pass valid selectors and behave identically — the null is\n // strictly additive. See DISCOVERIES.md D13.A.A.1 for the design\n // rationale (W6.A.A.1, 2026-05-07).\n this.mainContainer = window.document.querySelector(options.mainContainer);\n this.settingsContainer = options.settingsContainer ? window.document.querySelector(options.settingsContainer) : null;\n this.widgetsContainer = options.widgetsContainer ? window.document.querySelector(options.widgetsContainer) : null;\n\n // Canvas-clip reflow set + observer (2026-05-09).\n //\n // Every overlay positioner registered through\n // `BaseElement.matchingDomNode` adds its `setPosSize` closure to\n // this set on first mount and removes it from `__disconnectObservers`.\n // The clip-container ResizeObserver iterates the set on every\n // resize so a pure chrome-driven layout shift (sidebar collapse,\n // chrome-variant swap, parent column reflow that doesn't change\n // iframe-internal element rects) still re-ticks every overlay's\n // clip pass + position. Single observer per Builder; per-overlay\n // hooks. Multi-Builder safe because each Builder owns its own\n // set + observer.\n //\n // ── Clip-container resolution (walk-up rule) ──────────────────\n // Buyers typically wire `mainContainer` to a div they own\n // (`#MainContainer` in demo/builder.php, `.bjs-mb__canvas` slot\n // in cookbook variants). That div often does NOT have its own\n // overflow boundary — the SCROLL viewport sits one or more\n // ancestors up (e.g. `.demo-builder__canvas` with `overflow:\n // auto` in demo/builder.php). When the viewport scrolls, the\n // iframe inside `mainContainer` slides past topnav / sticky\n // chrome — its rect (and `mainContainer`'s rect) become\n // negative-top, but the chrome stays put. Clipping to\n // `mainContainer` does NOTHING in that frame because both rects\n // share the same offset. We need to clip to the FIRST ancestor\n // whose overflow clips paint (auto / scroll / hidden) — that's\n // the actual canvas viewport.\n //\n // If no such ancestor is found, fall back to `mainContainer`\n // itself (full-page builder where there's no chrome above the\n // canvas — clip is a no-op).\n //\n // See BUILDER.md \"Canvas-clip contract\" + OVERLAY.md §24.\n this._reflowHooks = new Set();\n this._mainContainerResizeObserver = null;\n this._resolvedClipContainer = this._resolveClipContainer();\n var _clipTarget = this._resolvedClipContainer || this.mainContainer;\n if (_clipTarget && typeof ResizeObserver === 'function') {\n this._mainContainerResizeObserver = new ResizeObserver(function () {\n var _iterator = _createForOfIteratorHelper(_this._reflowHooks),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var hook = _step.value;\n try {\n hook();\n } catch (_) {/* per-overlay error must not break others */}\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n });\n this._mainContainerResizeObserver.observe(_clipTarget);\n }\n this.assetUploadHandler = options.assetUploadHandler;\n // AI Task framework — explicit URL per feature. Each consumer\n // wires their own AI endpoint; the demo wires the BuilderJS AI\n // showcase URLs by default.\n // Shape: { inlineRewriteUrl?, chatboxUrl?, pageGeneratorUrl?, enabled?, csrfToken? }\n // Per-feature enable: omit/null the URL. Per-installation disable: enabled=false.\n this.ai = options.ai || {};\n this.rssHandler = options.rssHandler || null;\n\n // themeMediaUrl — Base URL pointing to the theme's media/assets directory.\n // Set by load(). Used to resolve relative asset paths (images, fonts, etc.)\n // stored in template JSON into absolute URLs for rendering in the iframe.\n //\n // How it works:\n // 1. Template JSON stores paths RELATIVE to the theme folder:\n // \"image\": \"assets/profile_image/avatar.png\"\n // \"background\": \"assets/backgrounds/header-bg.jpg\"\n //\n // 2. At render time, transferMediaAbsUrl() prepends themeMediaUrl:\n // \"assets/profile_image/avatar.png\"\n // → \"https://app.example.com/templates/000abc/assets/profile_image/avatar.png\"\n //\n // 3. At save/export time, getHtmlWithRelativeLinks() strips themeMediaUrl\n // back out, so the saved HTML stays portable (relative paths only).\n //\n // Example values from a SaaS host:\n // - Email builder: \"https://app.example.com/p/templates/000abc\"\n // (e.g. a Template model's public URL)\n // - Form builder: \"https://app.example.com/p/templates/000def\"\n // - Demo/dev: \"themes/default\" (relative to demo page)\n //\n // Also used by BackgroundControl to convert absolute URLs back to relative\n // when saving background image values (strips themeMediaUrl prefix).\n //\n // Key rule: paths like \"assets/profile_image/photo.jpg\" are RELATIVE —\n // they live inside the template's storage folder. themeMediaUrl is the\n // root that makes them absolute for the browser.\n this.themeMediaUrl = null;\n this.themeConfigs = null;\n this.templates = {};\n\n // helpers\n this.iframe = null;\n\n // PageElement\n this.pageElement = new _PageElement_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"](this);\n\n // Initialize parameters\n this.mode = 'preview';\n this.selectedElement = null;\n\n // Initialize UI Manager\n this.uiManager = new _UIManager_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this);\n\n // Global pub/sub on every Builder instance. Started life as\n // `CanvasHighlightBus` for control↔overlay signalling (W0.1; events\n // 'region:focus' / 'region:blur'); CD-3 (AIBuilder Wave 4) generalised\n // it into `EventEmitter` so host apps can drive autosave + dirty\n // tickers off the same bus the History system already publishes on.\n // Canonical events table: docs/core/USAGE.md \"Event bus (CD-3)\".\n // `document:changed` is debounced inside the bus so a typing burst\n // collapses into ONE host-visible signal (default 120ms — ~2 frames\n // at 60Hz, coalesces typing without lagging perceptual feedback).\n // Host overrides via `new Builder({ eventDebounceMs: ... })`.\n var eventDebounceMs = typeof options.eventDebounceMs === 'number' ? options.eventDebounceMs : 120;\n this.events = new _EventEmitter_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]({\n debounce: _defineProperty({}, Builder.EVENTS.DOCUMENT_CHANGED, eventDebounceMs)\n });\n\n // PLAN_EFFECT W0.3 — pure geometry utility for smart-flipped,\n // horizontally-clamped floating toolbars. Stateless; exposing the\n // class here is inert until W1.1 wires the actionsBox positioner\n // behind `useSmartToolbarPosition`. See docs/core/OVERLAY.md \"Toolbar\n // Positioner\".\n this.toolbarPositioner = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"];\n\n // TooltipManager — singleton DOM tooltip that portals into\n // <body> so it escapes every ancestor overflow clip (sidebar,\n // popovers, canvas wrappers). Installed once on first Builder\n // construction; subsequent instances share the same manager.\n // Reads `data-tooltip` / `data-tooltip-placement` /\n // `data-tooltip-align` attrs from every button in the chrome.\n this.tooltipManager = (0,_TooltipManager_js__WEBPACK_IMPORTED_MODULE_16__.getTooltipManager)();\n\n // PLAN_EFFECT W1.4 — focus-dim mode state.\n // `bjs:focus-dim` in localStorage persists the user toggle\n // across reloads. `_focusDimInit()` is called from `load()`\n // after the iframe is ready so the stored value re-applies.\n this._focusDim = false;\n this._focusDimKeyHandler = null;\n\n // TEXT_INLINE_PLAN W0.3 — single canvas-wide selection tracker.\n // Instantiated + attached by `_textSelectionInit()` once the iframe\n // document is available. Kept as a `Builder` field so both overlays\n // and tests can reach it (`builder.textSelectionTracker.getCurrent()`).\n this.textSelectionTracker = null;\n\n // TEXT_INLINE_PLAN W1.1 — floating inline-text formatting toolbar.\n // Singleton owned by the Builder; subscribes to `text-selection:*`\n // bus events emitted by the W0.3 tracker. Mount/unmount is driven\n // by selection changes (HARD RULE T1) — never by element click.\n // Instantiated + attached in `_textInlineToolbarInit()` after the\n // tracker is live.\n this._textInlineToolbar = null;\n\n // saveUrl for save() method\n this.saveUrl = options.saveUrl || null;\n\n // ─── History (undo/redo) ──────────────────────────────────────\n // PLAN_UNDO_REDO W7.3 — HistoryManager lives on the builder\n // instance. Widget default-on (opt-out via historyUI: false).\n // Shortcuts default-on (Ctrl/⌘Z, Ctrl/⌘⇧Z). See\n // docs/plans/PLAN_UNDO_REDO.md.\n this.history = new _HistoryManager_js__WEBPACK_IMPORTED_MODULE_14__[\"default\"](this, {\n maxSize: (_options$historyMaxSi = options.historyMaxSize) !== null && _options$historyMaxSi !== void 0 ? _options$historyMaxSi : 50,\n debounceMs: (_options$historyDebou = options.historyDebounceMs) !== null && _options$historyDebou !== void 0 ? _options$historyDebou : 400,\n coalesceMs: (_options$historyCoale = options.historyCoalesceMs) !== null && _options$historyCoale !== void 0 ? _options$historyCoale : 600,\n autoCloseTxMs: (_options$historyAutoC = options.historyAutoCloseTxMs) !== null && _options$historyAutoC !== void 0 ? _options$historyAutoC : 5000\n });\n this._historyWidget = null; // instantiated after load() so\n // mainContainer has final layout\n this._historyKeyHandler = null;\n\n // central structure validator for load/parse path\n this.structureValidator = new _BuilderJsonStructureValidator_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]();\n\n // filemanager plugin\n if (options.fileManager) {\n this.fileManager = options.fileManager;\n }\n }\n\n /**\n * Adopt an element subtree: recursively sets `host` on the element,\n * its children (via getChildren()), and any overlays it has emitted\n * (`element.overlays`). Called once after a subtree is parsed,\n * before render / mount.\n *\n * Why: Host injection — every Element/Overlay/Control needs a\n * back-reference to its owning Builder for bus / flags / shared\n * state. Walking the tree post-parse keeps `static parse(data)`\n * signature unchanged (CD-1).\n *\n * Idempotent — re-adopting an already-adopted element is a no-op,\n * so it's safe to call multiple times along an insertion path.\n *\n * @param {BaseElement} element root of the subtree to adopt\n */\n /**\n * Resolve the canvas-clip surface (2026-05-09).\n *\n * Walks up from `mainContainer` until the first ancestor whose\n * computed `overflow{,X,Y}` is one of `auto / scroll / hidden`.\n * That ancestor IS the actual canvas viewport — anything painted\n * past its border-box gets clipped by the browser's own overflow\n * machinery, so it's the SAME boundary the user sees.\n *\n * Why not just use `mainContainer`? In demo/builder.php (and any\n * real-world chrome with a topnav / sticky header), `mainContainer`\n * is the iframe wrapper that scrolls along with the iframe inside\n * a higher-up scroll viewport. When the user scrolls down, the\n * iframe rect AND mainContainer rect both go negative-top in\n * unison — clipping to mainContainer is a no-op against itself in\n * that frame. The actual viewport is `.demo-builder__canvas`\n * (overflow: auto) sitting below the topnav.\n *\n * Cookbook variants where buyers wire `mainContainer` to a fully\n * self-contained card / floating panel (their own overflow:hidden)\n * find the boundary at depth 0 (mainContainer itself).\n *\n * Falls back to `mainContainer` if no scroll-clipping ancestor is\n * found (full-page builder where the viewport == document — clip\n * becomes a visual no-op which is correct for that case).\n *\n * @returns {HTMLElement|null} the resolved clip surface\n */\n return _createClass(Builder, [{\n key: \"_resolveClipContainer\",\n value: function _resolveClipContainer() {\n if (!this.mainContainer) return null;\n var el = this.mainContainer;\n while (el && el !== document.body && el !== document.documentElement) {\n var cs = window.getComputedStyle(el);\n var ov = (cs.overflow || '') + (cs.overflowX || '') + (cs.overflowY || '');\n if (/(auto|scroll|hidden)/.test(ov)) {\n return el;\n }\n el = el.parentElement;\n }\n return this.mainContainer;\n }\n }, {\n key: \"_adopt\",\n value: function _adopt(element) {\n if (!element || element.host === this) return;\n element.host = this;\n // Propagate host into the element's formatter so its\n // `background_image: url(...)` resolution can route through\n // host.transferMediaAbsUrl per-instance (was a bare-builder\n // reach-in pre-host-injection W3 batch).\n if (element.formatter && typeof element.formatter._setHost === 'function') {\n element.formatter._setHost(this);\n }\n if (Array.isArray(element.overlays)) {\n var _iterator2 = _createForOfIteratorHelper(element.overlays),\n _step2;\n try {\n for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n var o = _step2.value;\n if (o) o.host = this;\n }\n } catch (err) {\n _iterator2.e(err);\n } finally {\n _iterator2.f();\n }\n }\n var kids = typeof element.getChildren === 'function' ? element.getChildren() : [];\n var _iterator3 = _createForOfIteratorHelper(kids),\n _step3;\n try {\n for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n var k = _step3.value;\n this._adopt(k);\n }\n } catch (err) {\n _iterator3.e(err);\n } finally {\n _iterator3.f();\n }\n }\n\n /**\n * W6.A.A.5 — auto-inject the engine's peer-dep CDN tags if absent.\n *\n * Detects whether the host page already loaded Material Symbols\n * Rounded (font) + Bootstrap JS (behavior) and injects matching\n * `<link>` / `<script>` tags into `document.head` if not. Idempotent:\n * subsequent Builder instances on the same page skip both checks.\n *\n * Detection rules (kept loose to avoid false-negatives across CDN\n * mirrors / version pins / self-hosted variants):\n * - Material Symbols Rounded: any `<link>` whose `href` contains\n * `Material+Symbols+Rounded` (case-insensitive). Matches Google\n * Fonts URL + the typical self-host filename.\n * - Bootstrap JS: `window.bootstrap?.Modal` is a function. Matches\n * bundle, separate-popper-and-bootstrap, and self-hosted variants.\n *\n * Race notes:\n * - Material Symbols is purely visual; late load swaps glyphs in\n * when ready (the `display=block` fontface descriptor pins the\n * glyph slot until ready, no FOUT shimmer).\n * - Bootstrap JS load is async (~80KB over CDN, <500ms typical).\n * The engine never opens a modal during boot — only on user-\n * triggered actions like Change-Theme / Asset-Upload, by which\n * time the bundle has loaded. Users clicking within the first\n * ~500ms hit a `bootstrap is not defined` error; acceptable\n * tradeoff vs. forcing every buyer to remember the script tag.\n *\n * @param {'auto'|false} mode — 'auto' to inject if missing,\n * false to skip entirely (air-gap / self-host).\n */\n }, {\n key: \"_ensurePeerAssets\",\n value: function _ensurePeerAssets(mode) {\n if (mode === false || typeof document === 'undefined') return;\n var head = document.head;\n if (!head) return;\n\n // ── Material Symbols Rounded ──────────────────────────────────\n var hasIconFont = Array.from(head.querySelectorAll('link[rel=\"stylesheet\"]')).some(function (l) {\n return /Material\\+Symbols\\+Rounded/i.test(l.href || '');\n });\n if (!hasIconFont) {\n var link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = 'https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,[email protected],100..700,0..1,-50..200&display=block';\n link.dataset.bjsAutoinject = 'icon-font';\n head.appendChild(link);\n }\n\n // ── Bootstrap JS (modal/alert behavior) ───────────────────────\n var hasBootstrapJs = typeof window !== 'undefined' && window.bootstrap && typeof window.bootstrap.Modal === 'function';\n if (!hasBootstrapJs) {\n // Don't double-inject if a prior Builder instance already added\n // the script (still loading). Mark via data attribute.\n var alreadyInjecting = head.querySelector('script[data-bjs-autoinject=\"bootstrap-js\"]');\n if (!alreadyInjecting) {\n var script = document.createElement('script');\n script.src = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js';\n script.defer = true;\n script.dataset.bjsAutoinject = 'bootstrap-js';\n head.appendChild(script);\n }\n }\n }\n\n /**\n * Save the current page content.\n * Sends the generated HTML and JSON data to the configured saveUrl via Ajax POST.\n *\n * @returns {Promise<Object>} The JSON response from the server.\n */\n }, {\n key: \"save\",\n value: (function () {\n var _save = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var html, data, payload, response;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (this.saveUrl) {\n _context.next = 2;\n break;\n }\n throw new Error('saveUrl is not configured. Pass it in the constructor options.');\n case 2:\n html = this.getHtml();\n data = this.getData();\n payload = new URLSearchParams();\n payload.append('html', html);\n payload.append('data', JSON.stringify(data));\n _context.next = 9;\n return fetch(this.saveUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded'\n },\n body: payload.toString()\n });\n case 9:\n response = _context.sent;\n return _context.abrupt(\"return\", response.json());\n case 11:\n case \"end\":\n return _context.stop();\n }\n }, _callee, this);\n }));\n function save() {\n return _save.apply(this, arguments);\n }\n return save;\n }()\n /* ─── PLAN_EFFECT W1.4 — focus-dim mode ─────────────────────────\n *\n * Host apps toggle \"focus mode\" via these three methods. When ON,\n * the iframe body receives a `.bjs-focus-dim` class — CSS in the\n * injected debug-css helper then applies `filter: brightness(…)`\n * to all content while counter-brightening the `[data-bjs-\n * selected=\"true\"]` element so the selection pops off the dimmed\n * canvas. State persists in `localStorage` under the key\n * `bjs:focus-dim` so the user's preference survives reload.\n *\n * Keyboard shortcut `⌘/Ctrl+.` is registered at `load()` time via\n * `_focusDimInit()` and torn down automatically on any future\n * `destroy()` path (via `_focusDimKeyHandler`).\n *\n * Honors `prefers-reduced-motion` — no filter transition when the\n * user requested reduced motion.\n */\n )\n }, {\n key: \"isFocusDim\",\n value: function isFocusDim() {\n return this._focusDim === true;\n }\n }, {\n key: \"setFocusDim\",\n value: function setFocusDim(on) {\n var next = !!on;\n if (this._focusDim === next) return;\n this._focusDim = next;\n this._applyFocusDim();\n try {\n localStorage.setItem('bjs:focus-dim', next ? '1' : '0');\n } catch (_) {}\n }\n }, {\n key: \"toggleFocusDim\",\n value: function toggleFocusDim() {\n this.setFocusDim(!this._focusDim);\n }\n\n /** Apply / remove the `.bjs-focus-dim` class on the iframe body +\n * mirror the flag onto the MAIN document.body as\n * `bjs-focus-dim-active` so main-window CSS (e.g. .selected-box\n * outline rules) can react — then (un)mount the spotlight\n * panels. Idempotent; safe to call pre-iframe-mount. */\n }, {\n key: \"_applyFocusDim\",\n value: function _applyFocusDim() {\n // Mirror onto main document body so `.selected-box` (which\n // lives in main window, not iframe) can read the state. User\n // feedback 2026-04-19: square outline when dim is ON avoids\n // the 4-corner bright gaps where the square 4-panel cutout\n // meets a rounded outline.\n try {\n document.body.classList.toggle('bjs-focus-dim-active', this._focusDim);\n } catch (_) {}\n var doc = this.iframe && this.iframe.contentDocument;\n if (doc && doc.body) {\n doc.body.classList.toggle('bjs-focus-dim', this._focusDim);\n }\n\n // Mount / unmount the spotlight based on state + selection.\n if (this._focusDim && this.getSelectedElement()) {\n this._mountFocusSpotlight(this.getSelectedElement());\n } else {\n this._unmountFocusSpotlight();\n }\n }\n\n /** Mount 4 dim panels surrounding the selected element's rect\n * inside the iframe body. Each panel carries backdrop-filter:\n * blur + a dark tint; the spotlight rect itself has no panel\n * over it so it stays razor-sharp. PAD (5 px) matches\n * `.selected-box`'s matchingDomNode(5) so the bright region\n * ends precisely at the outline's visible edge. */\n }, {\n key: \"_mountFocusSpotlight\",\n value: function _mountFocusSpotlight(element) {\n var _this2 = this;\n if (!element || !element.domNode) return;\n var doc = element.domNode.ownerDocument;\n if (!doc || !doc.body) return;\n\n // Single-element holed-box — same primitive as hover / select\n // container-highlight + padding visualiser. `clip-path: polygon(...)`\n // carves the selected element's rect out of a full-viewport `--dim`\n // layer so the element stays razor-sharp while the rest of the\n // canvas is dimmed.\n //\n // NO `--blur` here. The backdrop-filter + clip-path combination\n // hits a Chrome / Safari compositing quirk where the filter\n // buffer spans the element's whole bounding box before clipping\n // — the filtered snapshot then leaks into the hole area and the\n // element appears blurred through it. The dim-only surface is\n // lighter (1 element vs 4), architecturally consistent with the\n // other 3 primitive callsites, and \"turn off the lights\" reads\n // clearly without the blur. Added note in docs/plans/HOLED_BOX.md §\n // \"backdrop-filter gotcha\" so future requests to re-add blur\n // land on the 4-panel fallback pattern instead.\n if (!this._focusSpotlightPanel) {\n var p = doc.createElement('div');\n p.className = 'bjs-holed-box bjs-holed-box--dim bjs-focus-dim-spot';\n // `.bjs-holed-box` uses `inset: 0` relative to the containing\n // block; override here to anchor to the viewport explicitly\n // via `position: fixed` so we cover the full iframe no matter\n // where the body layout puts things.\n p.style.position = 'fixed';\n p.style.top = '0';\n p.style.left = '0';\n p.style.width = '100%';\n p.style.height = '100%';\n p.style.zIndex = '999998';\n p.style.pointerEvents = 'none';\n doc.body.appendChild(p);\n this._focusSpotlightPanel = p;\n }\n var PAD = 5;\n var setPos = function setPos() {\n var p = _this2._focusSpotlightPanel;\n if (!p || !element.domNode) return;\n var r = element.domNode.getBoundingClientRect();\n var iwin = doc.defaultView;\n var vw = iwin.innerWidth;\n var vh = iwin.innerHeight;\n var t = Math.max(0, r.top - PAD);\n var l = Math.max(0, r.left - PAD);\n var w = r.width + PAD * 2;\n var h = r.height + PAD * 2;\n // Holed-box polygon: outer = viewport rect, hole = selected\n // element rect inflated by PAD to clear its outline.\n p.style.clipPath = (0,_ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"])({\n width: vw,\n height: vh\n }, {\n left: l,\n top: t,\n right: l + w,\n bottom: t + h\n });\n };\n setPos();\n\n // Tear down any prior observer set (element may have been re-\n // selected with a different domNode after an inner render).\n this._disposeFocusSpotlightObservers();\n var iwin = doc.defaultView;\n var onScroll = function onScroll() {\n return setPos();\n };\n var onResize = function onResize() {\n return setPos();\n };\n iwin.addEventListener('scroll', onScroll, true);\n iwin.addEventListener('resize', onResize);\n window.addEventListener('scroll', onScroll, true);\n window.addEventListener('resize', onResize);\n var mo = null;\n var ro = null;\n try {\n mo = new iwin.MutationObserver(function () {\n return setPos();\n });\n mo.observe(doc.body, {\n childList: true,\n subtree: true,\n attributes: true\n });\n if (typeof iwin.ResizeObserver === 'function') {\n ro = new iwin.ResizeObserver(function () {\n return setPos();\n });\n ro.observe(element.domNode);\n }\n } catch (_) {/* dead iframe — ignore */}\n this._focusSpotlightDispose = function () {\n try {\n iwin.removeEventListener('scroll', onScroll, true);\n } catch (_) {}\n try {\n iwin.removeEventListener('resize', onResize);\n } catch (_) {}\n try {\n window.removeEventListener('scroll', onScroll, true);\n } catch (_) {}\n try {\n window.removeEventListener('resize', onResize);\n } catch (_) {}\n try {\n if (mo) mo.disconnect();\n } catch (_) {}\n try {\n if (ro) ro.disconnect();\n } catch (_) {}\n };\n }\n }, {\n key: \"_unmountFocusSpotlight\",\n value: function _unmountFocusSpotlight() {\n this._disposeFocusSpotlightObservers();\n if (this._focusSpotlightPanels) {\n for (var _i = 0, _Object$values = Object.values(this._focusSpotlightPanels); _i < _Object$values.length; _i++) {\n var p = _Object$values[_i];\n try {\n p.remove();\n } catch (_) {}\n }\n this._focusSpotlightPanels = null;\n }\n // Back-compat clean-up — the brief single-holed-box iteration\n // stored on this._focusSpotlightPanel. Drop any stale instance\n // left over from a hot-reload boundary across the refactor.\n if (this._focusSpotlightPanel) {\n try {\n this._focusSpotlightPanel.remove();\n } catch (_) {}\n this._focusSpotlightPanel = null;\n }\n }\n }, {\n key: \"_disposeFocusSpotlightObservers\",\n value: function _disposeFocusSpotlightObservers() {\n if (typeof this._focusSpotlightDispose === 'function') {\n try {\n this._focusSpotlightDispose();\n } catch (_) {}\n this._focusSpotlightDispose = null;\n }\n }\n\n /** Wire up persistence + keyboard shortcut. Called once after the\n * iframe content is loaded + the first `_injectIframeHelpers()`\n * has run (so the CSS rules are already in the head). */\n }, {\n key: \"_focusDimInit\",\n value: function _focusDimInit() {\n var _this3 = this;\n // Restore persisted value, if any.\n try {\n var stored = localStorage.getItem('bjs:focus-dim');\n if (stored === '1') this._focusDim = true;\n } catch (_) {}\n this._applyFocusDim();\n\n // `⌘/Ctrl+.` toggles. Only on the OUTER document — not inside\n // the iframe — so typing `.` into an inline-edit contentedit-\n // able never steals the shortcut. Handler guards against\n // inputs / textareas / contentEditable in the outer chrome\n // too (for the settings sidebar).\n if (this._focusDimKeyHandler) {\n document.removeEventListener('keydown', this._focusDimKeyHandler, true);\n }\n this._focusDimKeyHandler = function (e) {\n var isToggle = (e.metaKey || e.ctrlKey) && e.key === '.' && !e.shiftKey && !e.altKey;\n if (!isToggle) return;\n var tgt = e.target;\n if (tgt && (tgt.tagName === 'INPUT' || tgt.tagName === 'TEXTAREA' || tgt.isContentEditable === true)) {\n return;\n }\n e.preventDefault();\n _this3.toggleFocusDim();\n };\n document.addEventListener('keydown', this._focusDimKeyHandler, true);\n }\n\n /* ─── PLAN_EFFECT W2.3 — Alt-hold \"Inspect mode\" ──────────────────\n *\n * Tracks Alt key state on BOTH the outer document and the iframe\n * document. While Alt is held + the user is NOT in a text-edit\n * context, applies `.bjs-inspect-active` to the currently mounted\n * `.hovering-box` (and stores the boolean on `this._inspectAltDown`\n * so a NEW hover that starts mid-Alt-hold paints inspect-on on\n * first frame).\n *\n * Why both documents?\n * - Outer document: covers Alt held while sidebar / topbar focused.\n * - Iframe document: covers Alt held while mouse is over the canvas\n * (most common case — without this, the iframe steals key events).\n *\n * Auto-clear on:\n * - keyup of Alt\n * - window blur (user switched apps with Alt held)\n * - text-edit context gained (focus on input / textarea /\n * contentEditable) — the class drops immediately so the user\n * never sees inspect overlays while typing.\n *\n * Why class on `.hovering-box` (not body)?\n * The Builder is a guest in the host page. Mutating `document.body`\n * pollutes a surface the host owns and may style — class collisions,\n * unrelated CSS rules tripping on it, devtools confusion. Scoping\n * the inspect state to the overlay element itself keeps every\n * Builder side-effect inside the Builder's own DOM. See HARD RULE C\n * (revised 2026-04-19) in BUILDER.md for the full rationale.\n */\n }, {\n key: \"_inspectModeInit\",\n value: function _inspectModeInit() {\n var _this4 = this;\n var isInTextEdit = function isInTextEdit() {\n var a = document.activeElement;\n if (!a) return false;\n if (a.tagName === 'INPUT' || a.tagName === 'TEXTAREA') return true;\n if (a.isContentEditable === true) return true;\n return false;\n };\n var setActive = function setActive(on) {\n _this4._inspectAltDown = !!on;\n // Apply to the currently mounted hover overlay (only one at a\n // time per UIManager). Idempotent class toggle — cheap.\n try {\n var boxes = document.querySelectorAll('.hovering-box');\n var _iterator4 = _createForOfIteratorHelper(boxes),\n _step4;\n try {\n for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {\n var b = _step4.value;\n b.classList.toggle('bjs-inspect-active', _this4._inspectAltDown);\n }\n } catch (err) {\n _iterator4.e(err);\n } finally {\n _iterator4.f();\n }\n } catch (_) {}\n };\n var onKeyDown = function onKeyDown(e) {\n if (e.key !== 'Alt' && !e.altKey) return;\n if (isInTextEdit()) return;\n setActive(true);\n };\n var onKeyUp = function onKeyUp(e) {\n // `e.key === 'Alt'` handles the explicit Alt release. Also\n // clear if any other key release happens with `e.altKey`\n // false — covers the Tab-out / Cmd-Tab edge case.\n if (e.key === 'Alt' || !e.altKey) {\n setActive(false);\n }\n };\n var onBlur = function onBlur() {\n return setActive(false);\n };\n\n // Outer document.\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('keyup', onKeyUp, true);\n window.addEventListener('blur', onBlur);\n\n // Iframe document. The iframe may not exist yet at construct\n // time — wire up after `load()` mounts it. Re-wire on every\n // PageElement.render() too, since the iframe document survives\n // but listeners are persistent (we attach to the same document\n // object the iframe mounts into).\n var wireIframe = function wireIframe() {\n var idoc = _this4.iframe && _this4.iframe.contentDocument;\n if (!idoc || idoc.__bjsInspectWired) return;\n idoc.addEventListener('keydown', onKeyDown, true);\n idoc.addEventListener('keyup', onKeyUp, true);\n idoc.__bjsInspectWired = true;\n };\n setTimeout(wireIframe, 0);\n window.addEventListener('focus', wireIframe);\n }\n\n /* ─── TEXT_INLINE_PLAN W0.3 — selection tracker bootstrap ──── */\n }, {\n key: \"_textSelectionInit\",\n value: function _textSelectionInit() {\n var idoc = this.iframe && this.iframe.contentDocument;\n if (!idoc) return;\n\n // If load() is called twice (dev hot-reload, rebind tests), tear\n // down the previous tracker first so we don't leak two listener\n // chains on the same document.\n if (this.textSelectionTracker) {\n this.textSelectionTracker.destroy();\n this.textSelectionTracker = null;\n }\n this.textSelectionTracker = new _TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"]({\n doc: idoc,\n bus: this.events\n });\n this.textSelectionTracker.attach();\n }\n\n /* ─── TEXT_INLINE_PLAN W1.1 — inline toolbar bootstrap ────────── */\n }, {\n key: \"_textInlineToolbarInit\",\n value: function _textInlineToolbarInit() {\n // Tear down + rebuild on hot reload so we don't leak two\n // subscribers on the same bus.\n if (this._textInlineToolbar) {\n this._textInlineToolbar.destroy();\n this._textInlineToolbar = null;\n }\n this._textInlineToolbar = new _overlays_TextInlineToolbarOverlay_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](this);\n this._textInlineToolbar.attach();\n }\n\n /* ─── TEXT_INLINE_PLAN W6.3 — keyboard shortcut bootstrap ──── */\n }, {\n key: \"_textInlineShortcutsInit\",\n value: function _textInlineShortcutsInit() {\n // Tear down + rebuild on hot reload; same iframe-attach pattern\n // as TextSelectionTracker / TextInlineToolbarOverlay so a second\n // `load()` call doesn't leak listener pairs on the same document.\n if (this._textInlineShortcuts) {\n this._textInlineShortcuts.destroy();\n this._textInlineShortcuts = null;\n }\n this._textInlineShortcuts = new _TextInlineKeyboardShortcuts_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](this);\n this._textInlineShortcuts.attach();\n }\n\n /* ─── PLAN_UNDO_REDO W7.3 — History bootstrap ───────────────── */\n }, {\n key: \"_historyInit\",\n value: function _historyInit() {\n var _this5 = this;\n if (this.options.historyEnabled === false) return;\n\n // 1. Baseline snapshot — one entry for the freshly loaded state.\n this.history.pushBaseline();\n\n // 2. Bind iframe + settings debounce fallback. Small delay so\n // the iframe document is definitely attached + listeners on\n // the document survive subsequent re-renders (PageElement\n // only replaces <head>, not the document itself).\n setTimeout(function () {\n return _this5.history.bindDebounceFallback();\n }, 0);\n\n // 2a. Subscribe to region:focus / region:blur so debounce commits\n // can attach \"which property was focused\" context. Currently\n // only PaddingMarginControl emits these, but any future control\n // that opts in gets the benefit for free.\n this.history.bindRegionFocusTracking();\n\n // 3. Mount floating widget (opt-out: historyUI: false).\n if (this.options.historyUI !== false) {\n this._historyWidget = new _HistoryWidget_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](this, {\n position: this.options.historyUIPosition || 'bottom-left',\n minimal: !!this.options.historyUIMinimal,\n className: this.options.historyUIClassName || ''\n });\n this._historyWidget.mount();\n }\n\n // 4. Keyboard shortcuts — Ctrl/⌘Z · Ctrl/⌘⇧Z · Ctrl+Y. Wired\n // on OUTER document with capture phase, skips text-edit\n // contexts (matches _focusDimInit pattern).\n if (this.options.historyShortcuts === false) return;\n if (this._historyKeyHandler) {\n document.removeEventListener('keydown', this._historyKeyHandler, true);\n }\n this._historyKeyHandler = function (e) {\n var mod = e.metaKey || e.ctrlKey;\n if (!mod) return;\n var k = (e.key || '').toLowerCase();\n var isUndo = k === 'z' && !e.shiftKey && !e.altKey;\n var isRedo = k === 'z' && e.shiftKey && !e.altKey || k === 'y' && !e.shiftKey;\n if (!isUndo && !isRedo) return;\n\n // Skip text-edit contexts — let the browser / editor native\n // undo/redo handle it first. Page-level undo only fires\n // from the canvas / sidebar / topbar.\n var tgt = e.target;\n if (tgt && (tgt.tagName === 'INPUT' || tgt.tagName === 'TEXTAREA' || tgt.isContentEditable === true)) {\n return;\n }\n e.preventDefault();\n if (isUndo) _this5.undo();else _this5.redo();\n };\n document.addEventListener('keydown', this._historyKeyHandler, true);\n }\n\n /** Public undo shortcut. Returns a promise that resolves when apply completes. */\n }, {\n key: \"undo\",\n value: function undo() {\n return this.history.undo();\n }\n /** Public redo shortcut. Returns a promise that resolves when apply completes. */\n }, {\n key: \"redo\",\n value: function redo() {\n return this.history.redo();\n }\n }, {\n key: \"canUndo\",\n value: function canUndo() {\n return this.history.canUndo();\n }\n }, {\n key: \"canRedo\",\n value: function canRedo() {\n return this.history.canRedo();\n }\n\n /* ───────────────────────────────────────────────────────────── */\n\n /**\n * Load the builder with prepared data.\n * This is the primary entry point — all consumers (builder.php, host\n * server templates) pre-load theme templates and page data on the\n * server, then call load() directly.\n *\n * @param {Object} themeJson - Page JSON data (the content to render).\n * @param {Object} themeTemplatesJson - Pre-loaded template HTML: { \"Page\": \"<html>...\", \"Block\": \"<div>...\", ... }.\n * @param {Object} themeConfigData - Parsed theme index.json (name, pages, templates metadata).\n * @param {string} themeMediaUrl - Base URL for resolving relative asset/media paths to absolute URLs.\n * @param {Function} [callback] - Optional callback after load completes.\n */\n }, {\n key: \"load\",\n value: (function () {\n var _load = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(themeJson, themeTemplatesJson, themeConfigData, themeMediaUrl, callback) {\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n this.data = themeJson;\n this.themeMediaUrl = themeMediaUrl;\n this.themeConfigs = themeConfigData;\n\n // Store pre-loaded templates directly — zero HTTP fetches\n this.templates = themeTemplatesJson;\n\n // validate structure\n this.validateStructure(this.data);\n\n // widgets box — consumer adds widgets via builder.widgetsBox.addWidget() in callback.\n // W6.A.A.1: when `widgetsContainer` is null (no sidebar), `widgetsBox`\n // stays null too. Callers that opt out of the sidebar must not call\n // `widgetsBox.addWidget(...)` — there is no widget palette to add to.\n this.widgetsBox = this.widgetsContainer ? new WidgetsBox(this.widgetsContainer, this) : null;\n\n // init iframe\n _context2.next = 8;\n return this.initIframe();\n case 8:\n _context2.next = 10;\n return this.render();\n case 10:\n // Auto-resize iframe height to match content — must run AFTER render()\n // because render() uses iframeDoc.write() which replaces the document.\n // _setupIframeAutoResize → _injectIframeHelpers injects ALL builder-mode\n // helper CSS (autosize overrides + debug-css for cursor / scrollbar /\n // contenteditable focus-ring suppression / etc.) in one idempotent\n // pass that re-runs on every PageElement.render() head replacement.\n this._setupIframeAutoResize();\n\n // apply mode: normal or for debugging\n this.applyMode();\n\n // PLAN_EFFECT W1.4 — restore persisted focus-dim state + wire\n // keyboard shortcut. Runs AFTER _setupIframeAutoResize so the\n // iframe head already has the `.bjs-focus-dim` CSS injected.\n this._focusDimInit();\n\n // PLAN_EFFECT W2.3 — wire the global Alt-key tracker for the\n // Alt-hold inspect overlay. Always wired (no flag) — the inspect\n // chrome ships default-on, and toggling state is hot path during\n // hover. State lives on `this._inspectAltDown`; the listener\n // re-applies the `.bjs-inspect-active` class to the active\n // `.hovering-box` overlay (NOT body — see W2.3 design note in\n // BUILDER.md HARD RULE C).\n this._inspectModeInit();\n\n // TEXT_INLINE_PLAN W0.3 — attach the canvas-wide selection\n // tracker. Runs AFTER render() so `iframe.contentDocument` is the\n // final one PageElement.render() wrote to (PageElement replaces\n // <head>/<body>, not the document itself — listeners installed\n // here survive every subsequent re-render).\n this._textSelectionInit();\n\n // TEXT_INLINE_PLAN W1.1 — mount the singleton inline toolbar.\n // Subscribes to the tracker's bus events; DOM is created on\n // first selection, destroyed on clear. Must run AFTER the\n // tracker is attached so the bus exists.\n this._textInlineToolbarInit();\n\n // TEXT_INLINE_PLAN W6.3 — attach the inline-text keyboard\n // shortcut dispatcher (⌘B/I/U/⇧X/K/⇧K/⌥C/⌥V/\\/⇧L/E/R/J). Capture-\n // phase listener on the iframe document, scoped to\n // `[data-bjs-inline-text]` focus. Must run AFTER toolbar init\n // so ⌘K can route through `_textInlineToolbar._toggleLinkPopover`.\n this._textInlineShortcutsInit();\n\n // PLAN_UNDO_REDO W7.3 — bootstrap history AFTER render + UI\n // managers are live. Pushes baseline snapshot, binds iframe /\n // settings debounce fallback, mounts the floating widget, wires\n // Ctrl/⌘Z shortcuts. Guarded by `options.historyEnabled`\n // (default TRUE). See docs/plans/PLAN_UNDO_REDO.md.\n this._historyInit();\n\n // callback after initialization\n if (callback) {\n callback();\n }\n case 19:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, this);\n }));\n function load(_x, _x2, _x3, _x4, _x5) {\n return _load.apply(this, arguments);\n }\n return load;\n }())\n }, {\n key: \"getCurrentCapabilityName\",\n value: function getCurrentCapabilityName() {\n var _this$data;\n switch ((_this$data = this.data) === null || _this$data === void 0 ? void 0 : _this$data.template) {\n case 'Form':\n return 'form';\n default:\n return 'page';\n }\n }\n }, {\n key: \"hasTemplate\",\n value: function hasTemplate(templateName) {\n return this.templates[templateName];\n }\n }, {\n key: \"getTemplate\",\n value: function getTemplate(templateName) {\n if (!this.templates[templateName]) {\n // Fire-and-forget themed alert. We still throw synchronously so\n // the caller's error-handling path runs as before — the popup\n // is just a nicer visual signal for the user.\n _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].alert({\n title: _I18n_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].t('errors.template_not_found_title', 'Template not found'),\n message: _I18n_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].t('errors.template_not_found_msg', 'Template \"{name}\" could not be located in the current theme.').replace('{name}', templateName),\n kind: 'error'\n });\n throw new Error(\"Template \\\"\".concat(templateName, \"\\\" not found\"));\n }\n return this.templates[templateName];\n }\n }, {\n key: \"initIframe\",\n value: function () {\n var _initIframe = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n // Create an iframe and append it to the body\n this.iframe = document.createElement('iframe');\n this.iframe.style.width = '100%';\n this.iframe.style.border = 'none';\n this.iframe.style.backgroundColor = '#FFFFFF';\n this.iframe.classList.add('shadow');\n this.mainContainer.appendChild(this.iframe);\n\n // Access the iframe document\n this.iframeDoc = this.iframe.contentDocument || this.iframe.contentWindow.document;\n case 7:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, this);\n }));\n function initIframe() {\n return _initIframe.apply(this, arguments);\n }\n return initIframe;\n }()\n /**\n * Auto-resize: keep iframe height === actual content height (no excess,\n * no shortage). The builder canvas (iframe) never has its own scrollbar;\n * scrolling is handled by the outer wrapper.\n *\n * FEEDBACK-LOOP TRAPS — both fixed by _injectIframeHelpers():\n * (a) Page.template.html sets `min-height: 100vh` on PageElement.\n * Inside an iframe, 100vh === iframe height. With auto-resize syncing\n * iframe height → page height, ANY page padding/margin grows the\n * iframe forever (page = max(content, 100vh) + padding → iframe →\n * 100vh grows → page grows → loop).\n * (b) The empty-page placeholder in PageElement.render() previously used\n * inline `height: 100vh`. Same loop trigger when page padding > 0.\n *\n * Both are fixed by injecting a builder-helper <style> that overrides\n * min-height on PageElement and pins the placeholder to a fixed\n * min-height. Crucially, this helper must be RE-INJECTED after every\n * PageElement.render() because that path replaces iframeDoc.head.innerHTML\n * wholesale (see PageElement.render() else branch).\n */\n }, {\n key: \"_setupIframeAutoResize\",\n value: function _setupIframeAutoResize() {\n var iframe = this.iframe;\n\n /**\n * Measure actual content height by summing the natural heights of\n * body's direct children using offsetTop + offsetHeight.\n *\n * Why not scrollHeight?\n * PageElement has min-height: 100vh in template CSS. Inside an\n * iframe, 100vh = iframe height. scrollHeight reflects that,\n * creating a feedback loop. (We override min-height via\n * _injectIframeHelpers, but scrollHeight can also pick up other\n * 100vh children, so offsetTop+offsetHeight stays the safer path.)\n *\n * Why not getBoundingClientRect()?\n * rect.top is viewport-relative. If the page uses flex centering\n * (align-items: center), children shift vertically as iframe grows,\n * causing rect.top to grow → measured height grows → loop.\n *\n * offsetTop + offsetHeight are relative to the offsetParent (body),\n * independent of iframe height and flex centering.\n */\n var getContentHeight = function getContentHeight() {\n var doc = iframe.contentDocument;\n if (!doc || !doc.body) return 0;\n var maxBottom = 0;\n var children = doc.body.children;\n for (var i = 0; i < children.length; i++) {\n var child = children[i];\n // Skip script/style/hidden elements\n if (child.tagName === 'SCRIPT' || child.tagName === 'STYLE') continue;\n var bottom = child.offsetTop + child.offsetHeight;\n if (bottom > maxBottom) maxBottom = bottom;\n }\n\n // Account for body margin\n var bodyStyle = doc.defaultView.getComputedStyle(doc.body);\n var marginTop = parseFloat(bodyStyle.marginTop) || 0;\n var marginBottom = parseFloat(bodyStyle.marginBottom) || 0;\n return Math.ceil(maxBottom + marginTop + marginBottom);\n };\n var lastHeight = 0;\n var syncHeight = function syncHeight() {\n var h = getContentHeight();\n if (h > 0 && h !== lastHeight) {\n lastHeight = h;\n iframe.style.height = h + 'px';\n }\n };\n\n // Re-injection hook: PageElement.render() calls _injectIframeHelpers()\n // after every head replacement, so syncHeight always sees the\n // overridden min-height and converges immediately.\n this._injectIframeHelpers();\n\n // Iframe height = exactly content height. No artificial minHeight —\n // the empty-page placeholder (min-height: 480px, see PageElement.render)\n // gives empty pages a reasonable visual footprint without coupling to\n // viewport units.\n iframe.style.minHeight = '0';\n\n // Poll for height changes every 200ms.\n // MutationObserver cannot observe across document boundaries,\n // and injected scripts in iframes created via document.write()\n // may not execute. Polling is lightweight (compares one integer)\n // and works reliably across all browsers.\n setInterval(syncHeight, 200);\n\n // Sync on parent window resize (responsive mode switches)\n window.addEventListener('resize', syncHeight);\n\n // Initial sync\n syncHeight();\n }\n\n /**\n * Re-inject all iframe-only helper styles. Called once after the initial\n * render (from _setupIframeAutoResize) and again from PageElement.render()\n * after every head replacement.\n *\n * IDEMPOTENT: each style block is tagged with a unique data-helper-id so\n * we can detect \"already injected\" and bail. Cheap to call repeatedly.\n *\n * MUST CARRY data-control=\"builder-helper\" so getHtml() strips them on\n * export — they exist purely for the editor canvas, not the rendered email.\n */\n }, {\n key: \"_injectIframeHelpers\",\n value: function _injectIframeHelpers() {\n var doc = this.iframeDoc;\n if (!doc || !doc.head) return;\n\n // Stable across head replacement (documentElement is not replaced\n // when we do head.innerHTML = ...). Set defensively each call so\n // any code that resets it gets corrected.\n if (doc.documentElement) {\n doc.documentElement.style.overflow = 'hidden';\n }\n\n // Auto-size override. Override `min-height: 100vh` from Page.template.html\n // and pin the empty-page placeholder to a fixed min-height so neither\n // can drive the iframe-height feedback loop when the user adds page\n // padding or margins.\n if (!doc.head.querySelector('style[data-helper-id=\"autosize-overrides\"]')) {\n var style = doc.createElement('style');\n style.setAttribute('data-control', 'builder-helper');\n style.setAttribute('data-helper-id', 'autosize-overrides');\n style.textContent = \"\\n [builder-element=\\\"PageElement\\\"] { min-height: 0 !important; }\\n [data-control=\\\"page-empty-placeholder\\\"] {\\n height: auto !important;\\n min-height: 480px !important;\\n }\\n \";\n doc.head.appendChild(style);\n }\n\n // Debug / builder-mode CSS (cursor styling, scrollbar theming,\n // design-mode layout colors, inline-edit focus-ring suppression,\n // input pointer-events). Originally lived in a\n // one-shot loadDebugCss() called at init. But PageElement.render()'s\n // else branch does `head.innerHTML = doc.head.innerHTML` which WIPES\n // every style tag — including this one. Result: after any re-render\n // (add block, reorder, save), clicking into a [contenteditable]\n // inline-edit `<p>` / `<h*>` / `<a>` surfaced the browser-default\n // focus ring (blue in Chrome and Safari). The fix is to colocate\n // this CSS with the other iframe helpers so it rides the idempotent\n // re-injection path triggered by PageElement.render().\n //\n // Keep data-helper-id=\"debug-css\" stable — it's the dedupe key.\n if (!doc.head.querySelector('style[data-helper-id=\"debug-css\"]')) {\n var _style = doc.createElement('style');\n _style.setAttribute('data-control', 'builder-helper');\n _style.setAttribute('data-helper-id', 'debug-css');\n _style.textContent = this._getDebugCss();\n doc.head.appendChild(_style);\n }\n\n // Flip the contenteditable line-break separator from `<div>` (Chrome\n // / Safari default) to `<br>`. Without this, every Enter inside a\n // `<p inline-edit=\"text\">` inserts a `<div>` block child — which\n // round-trips through the HTML5 fragment parser as a SIBLING of the\n // `<p>` on the next `innerHTML =` assignment (parser auto-closes\n // `<p>` when it sees a `<div>`). Result: paragraph-level inline\n // styles (font-weight, text-align, font-family) disappear from the\n // visible content. See InlineSanitizer.BLOCK_LEVEL_TAGS + the\n // BaseElement._wireInlineEdit input listener for the DOM-level\n // defence-in-depth that handles Safari (which ignores this flag).\n //\n // Idempotent — execCommand may overwrite on repeated calls, but\n // calling repeatedly is safe + cheap. Wrapped in try/catch because\n // older Safari throws InvalidStateError when invoked outside an\n // active editing context; the DOM-level normalize catches the\n // fallout there.\n try {\n doc.execCommand('defaultParagraphSeparator', false, 'br');\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].warn('builder:defaultParagraphSeparator', err);\n }\n }\n }, {\n key: \"render\",\n value: function () {\n var _render = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n // parse page data\n this.pageElement.parse(this.data);\n\n // Host injection — walk the freshly-parsed tree and assign\n // `host = this` on every element + overlay BEFORE render runs,\n // so Element/Overlay code can reach `this.host.{events,options,…}`\n // from the very first render() / afterMount() pass.\n this._adopt(this.pageElement);\n\n // Load and inject the PageElement theme\n this.pageElement.render();\n case 3:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4, this);\n }));\n function render() {\n return _render.apply(this, arguments);\n }\n return render;\n }()\n }, {\n key: \"loadCSS\",\n value: function () {\n var _loadCSS = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5(cssPath) {\n var response;\n return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n while (1) switch (_context5.prev = _context5.next) {\n case 0:\n _context5.next = 2;\n return fetch(cssPath);\n case 2:\n response = _context5.sent;\n if (response.ok) {\n _context5.next = 5;\n break;\n }\n throw new Error(\"Failed to load CSS from \".concat(cssPath));\n case 5:\n _context5.next = 7;\n return response.text();\n case 7:\n return _context5.abrupt(\"return\", _context5.sent);\n case 8:\n case \"end\":\n return _context5.stop();\n }\n }, _callee5);\n }));\n function loadCSS(_x6) {\n return _loadCSS.apply(this, arguments);\n }\n return loadCSS;\n }()\n }, {\n key: \"insertElements\",\n value: function insertElements(elements) {\n this.pageElement.appendElements(elements);\n this.pageElement.render();\n }\n }, {\n key: \"clear\",\n value: function clear() {\n var _this6 = this;\n // PLAN_UNDO_REDO — programmatic page wipe. F1 + F3 fix:\n // - removeAllBlocks no longer leaks N per-block `structure_remove`\n // commits (clean teardown bypasses BaseElement.remove).\n // - We still wrap in `silent()` as a defense-in-depth so any\n // future commit added to the teardown path is suppressed; then\n // emit ONE `history.clear` summary so the user can undo the\n // clear in one step (without it, clear was effectively\n // irreversible after F1 silenced the leak).\n if (this.history) {\n this.history.silent(function () {\n return _this6.pageElement.clear();\n });\n this.history.commit('history.page_clear', {\n source: 'builder.clear',\n change: 'page:clear'\n });\n } else {\n this.pageElement.clear();\n }\n }\n }, {\n key: \"validateStructure\",\n value: function validateStructure(data) {\n try {\n this.structureValidator.validate(data);\n } catch (error) {\n console.warn('Builder JSON validation:', error.message);\n }\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, {\n theme: this.themeConfigs.name\n }), this.pageElement.getData());\n }\n\n /**\n * Sanitise + strip editor-only artefacts from a CLONED export root.\n *\n * Single source of truth for the `getHtml()` / `getRenderedBlocks()`\n * pipelines (HARD RULE T12 — export-output consistency). Pre-2026-05-20\n * each method open-coded its own cleanup, which drifted: `getRenderedBlocks`\n * was missing the `inline-edit` host normalize pass + mutated live\n * DOM directly. Centralising here guarantees:\n *\n * 1. Every export path strips the same set of editor-only attrs +\n * builder-helper nodes — no surprises when a new export consumer\n * ships (AIBuilder Wave N, \"Save\", \"Preview\", \"Export HTML\",\n * etc.).\n * 2. HARD RULE T11 holds for every export — every `[inline-edit]`\n * host is run through `InlineSanitizer.normalize` so block-level\n * descendants (Chrome's contenteditable Enter-inserted `<div>`s)\n * get unwrapped to inline `<br>` BEFORE serialization. Without\n * this, saved HTML round-trips through the HTML5 fragment parser\n * as `<p>…<div>…</div></p>` → auto-close → orphan siblings →\n * lost inline style on the host. See BUILDER.md Lesson 88.\n *\n * ⚠ NEVER pass a live iframe node here — this method mutates `root`\n * in place. Callers MUST clone first. (Past incident: stripping\n * [data-control=\"builder-helper\"] in place wiped the autosize-overrides\n * `<style>` from the live iframe head; with that gone, Page.template.html's\n * `min-height: 100vh` snapped back and the auto-resize poll grew the\n * iframe forever after every Save click. Clone-then-clean is the\n * only safe pattern.)\n *\n * @param {HTMLElement} root CLONED root (document element, body, or\n * any container whose subtree should be\n * sanitised for export).\n */\n }, {\n key: \"_sanitiseForExport\",\n value: function _sanitiseForExport(root) {\n if (!root) return;\n // Order is intentional:\n // 1. Inline-edit normalize MUST run BEFORE stripping\n // `inline-edit` attr — that's how we identify hosts.\n // 2. Builder-helper removal runs ANY time before serialization;\n // placed after normalize so we don't accidentally drop\n // content the normalize pass touches (it doesn't, but the\n // order makes the contract obvious).\n // 3. Editor-only attr strip runs LAST so the inline-edit\n // attribute survives long enough for step 1 to find hosts.\n root.querySelectorAll('[inline-edit]').forEach(function (host) {\n try {\n _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"].normalize(host);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].error('builder:sanitiseForExport-normalize', err);\n }\n });\n root.querySelectorAll('[data-control=\"builder-helper\"]').forEach(function (el) {\n return el.remove();\n });\n\n // NOTE: `builder-element` is intentionally kept — Page.template.html\n // uses `[builder-element=\"PageElement\"]` / `[builder-element=\"BlockElement\"]`\n // selectors in the generated `<style>` block for container-width\n // constraints, block gap, block padding, and default background\n // color. Removing it breaks all layout rules in the served HTML.\n root.querySelectorAll('[contenteditable]').forEach(function (el) {\n return el.removeAttribute('contenteditable');\n });\n root.querySelectorAll('[inline-edit]').forEach(function (el) {\n return el.removeAttribute('inline-edit');\n });\n // W0.2b runtime marker stamped on every inline-edit host so\n // selection-aware overlays can scope their listeners. Saved HTML\n // has no use for it.\n root.querySelectorAll('[data-bjs-inline-text]').forEach(function (el) {\n return el.removeAttribute('data-bjs-inline-text');\n });\n }\n }, {\n key: \"getHtml\",\n value: function getHtml() {\n // Clone the entire document — see `_sanitiseForExport` doc for the\n // \"never mutate live iframe DOM\" invariant + the autosize-overrides\n // past incident that motivated it.\n var htmlDoc = this.iframe.contentDocument.documentElement.cloneNode(true);\n this._sanitiseForExport(htmlDoc);\n\n // Strip editor-only inline `overflow: hidden` that _injectIframeHelpers()\n // pins onto <html> to stop the editor iframe from double-scrolling. It's\n // on documentElement itself (not a child), so the querySelectorAll\n // filters inside `_sanitiseForExport` can't catch it. Leaving it would\n // bake `<html style=\"overflow: hidden;\">` into exported HTML → breaks\n // scroll on campaign web-view / email preview.\n htmlDoc.style.removeProperty('overflow');\n if (!htmlDoc.getAttribute('style') || !htmlDoc.getAttribute('style').trim()) {\n htmlDoc.removeAttribute('style');\n }\n return htmlDoc.outerHTML;\n }\n\n /**\n * Get rendered HTML with all asset URLs converted back to relative paths.\n *\n * During editing, transferMediaAbsUrl() converts relative paths to absolute:\n * \"assets/profile_image/avatar.png\" → \"https://app.example.com/p/templates/000abc/assets/profile_image/avatar.png\"\n *\n * This method reverses that — strips the themeMediaUrl prefix so saved HTML\n * stays portable and works regardless of domain or template URL changes:\n * \"https://app.example.com/p/templates/000abc/assets/profile_image/avatar.png\" → \"assets/profile_image/avatar.png\"\n *\n * @returns {string} HTML with relative asset paths (ready for database storage).\n */\n }, {\n key: \"getHtmlWithRelativeLinks\",\n value: function getHtmlWithRelativeLinks() {\n var html = this.getHtml();\n html = html.replace(new RegExp(this.themeMediaUrl + '/', 'g'), '');\n return html;\n }\n }, {\n key: \"getSelectedElement\",\n value: function getSelectedElement() {\n return this.selectedElement;\n }\n }, {\n key: \"setSelectedElement\",\n value: function setSelectedElement(element) {\n this.selectedElement = element;\n }\n }, {\n key: \"selectElement\",\n value: function selectElement(element) {\n // unselect\n this.unselect();\n\n // set element\n this.setSelectedElement(element);\n\n // render settings box\n this.renderElementControls(element);\n\n // PLAN_EFFECT W2.1 — tear down any hover overlay lingering on\n // the element we just selected. Without this, the mouseout\n // debounce (50 ms) leaves a hover outline on top of the new\n // selection outline for one frame → visible \"double outline\n // messup\" (user feedback 2026-04-19). Idempotent if no hover\n // was live.\n element.removeHoverHightlight();\n\n // PLAN_EFFECT W2.1b — also tear down the container padding-\n // region highlight on the parent. Without this, the green-\n // striped padding pattern on the parent container lingers\n // until the user moves the mouse, even though the child is\n // now selected (user feedback 2026-04-19 \"container highlight\n // hover gì đó remove ngay khi remove cái highlight luôn nha\").\n if (element.container && typeof element.container.removeContainerHightlight === 'function') {\n element.container.removeContainerHightlight();\n }\n\n // PLAN_EFFECT W1.4 — mark the element's iframe DOM node with\n // `data-bjs-selected=\"true\"` (kept for legacy tests / ARIA)\n // and, if focus-dim is currently ON, mount the spotlight\n // overlay over this element's rect. The spotlight's box-\n // shadow dims everything in the iframe OUTSIDE the rect so\n // the selected element + its parent section both read as\n // bright against a dimmed surround.\n if (element.domNode) {\n element.domNode.setAttribute('data-bjs-selected', 'true');\n }\n this._applyFocusDim();\n\n // Add selected class\n element.addSelectedHighlight();\n\n // Canvas overlays — mount any overlay declared with trigger 'select'.\n // Default getOverlays() returns [] so zero work for opt-out elements.\n // See docs/core/OVERLAY.md §3 + docs/archived/OVERLAY_PLAN.md §3.2.\n element.mountOverlays('select');\n\n // @todo depenency: open settings tab.\n // W6.A.A.1: cookbook presets that omit the settings sidebar also omit\n // `window.sidebarTabManager` — guard the openTab call so selection\n // still works (overlays + highlight) without a sidebar to switch.\n if (window.sidebarTabManager) {\n window.sidebarTabManager.openTab(document.querySelector('[data-tab=\"controls\"]'));\n }\n if (window.smenu) {\n window.smenu.openTab(document.querySelector('[data-smenu=\"design\"]'));\n }\n }\n }, {\n key: \"unselect\",\n value: function unselect() {\n if (!this.getSelectedElement()) {\n return; // no selected > do nothing\n }\n\n // Tear down any 'select'-trigger overlays before removing the highlight.\n // Ordering: unmount overlays FIRST, then existing highlight removal\n // — matchingDomNode observers may fire between the two, and\n // overlay DOM should be gone by the time the hover state shifts.\n this.getSelectedElement().unmountOverlays('select');\n\n // Phase 1.8 (SA I14) — dispose currently-active sidebar controls\n // when nothing is selected. Without this, the last-selected element's\n // controls would keep their sync subscriptions alive until another\n // element is selected. unselect() is a natural teardown point.\n var prevControls = this._activeControlList || [];\n var _iterator5 = _createForOfIteratorHelper(prevControls),\n _step5;\n try {\n for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {\n var ctrl = _step5.value;\n if (ctrl && typeof ctrl.destroy === 'function') {\n try {\n ctrl.destroy();\n } catch (_) {/* no-op */}\n }\n }\n } catch (err) {\n _iterator5.e(err);\n } finally {\n _iterator5.f();\n }\n this._activeControlList = [];\n\n // remove selected effect\n this.getSelectedElement().removeSelectedHighlight();\n\n // PLAN_EFFECT W1.4 — clear selection marker + tear down any\n // spotlight overlay mounted for this element.\n var prev = this.getSelectedElement();\n if (prev && prev.domNode) {\n prev.domNode.removeAttribute('data-bjs-selected');\n }\n this._unmountFocusSpotlight();\n\n // ──────────────────────────────────────────────────────────────────\n // CRITICAL — clear `selectedElement` AFTER all per-element teardown.\n // Without this, the field stays pointing at the just-unselected\n // element, and downstream code that conditionalises on\n // `getSelectedElement()` reads stale state.\n //\n // Concrete regression (2026-05-05, \"hover lost on re-hover after\n // toolbar Unselect\"): UIManager.mouseover applies the W2.1b\n // \"skip container highlight when hovered === selected\" rule\n // (UIManager.js around line 283). With selectedElement still set\n // to the just-unselected element X, the rule misfires for X\n // exclusively — re-hovering X removes the container highlight\n // instead of adding it. Y (any other element) is unaffected\n // because Y !== stale X. Selecting another element Z masks the\n // bug because selectElement→setSelectedElement(Z) overwrites the\n // stale field.\n //\n // Order matters: this null-set MUST come AFTER the per-element\n // teardown calls above (they read getSelectedElement() to know\n // what to teardown) but BEFORE any UI state that observes\n // \"no selection\" (sidebar tab open, future bus events, etc).\n // ──────────────────────────────────────────────────────────────────\n this.setSelectedElement(null);\n\n // @todo depenency: open widgets tab.\n // W6.A.A.1: same null-tolerance guard as selectElement.\n if (window.sidebarTabManager) {\n window.sidebarTabManager.openTab(document.querySelector('[data-tab=\"widgets\"]'));\n }\n if (window.smenu) {\n window.smenu.openTab(document.querySelector('[data-smenu=\"design\"]'));\n }\n }\n }, {\n key: \"getMode\",\n value: function getMode() {\n return this.mode;\n }\n }, {\n key: \"setMode\",\n value: function setMode(mode) {\n // W6.A.A.4: emit `mode:changed` so cookbook chrome presets can\n // reactively update header pills / status indicators without\n // polling the mode field. Idempotent calls (`setMode(currentMode)`)\n // STILL fire — subscribers must handle that themselves; we keep\n // the emit unconditional for symmetry with the existing pattern\n // (any state-mutation call triggers its event regardless of whether\n // the value really changed).\n var from = this.mode;\n this.mode = mode;\n this.applyMode();\n this.events.emit(Builder.EVENTS.MODE_CHANGED, {\n from: from,\n to: mode\n });\n }\n }, {\n key: \"applyMode\",\n value: function applyMode() {\n if (this.getMode() === 'design') {\n this.iframe.contentDocument.body.classList.add('builder-mode-design');\n } else {\n this.iframe.contentDocument.body.classList.remove('builder-mode-design');\n }\n }\n }, {\n key: \"removeElement\",\n value: function removeElement(element) {\n // unselect if the element is selected\n if (this.getSelectedElement() == element) {\n this.unselect();\n }\n\n // Capture identity BEFORE the remove tears down the element graph —\n // post-remove the node may already be detached and helpers stop\n // resolving cleanly.\n var elementUid = element ? element.id : null;\n var elementType = element && typeof element.getName === 'function' ? element.getName() : undefined;\n\n // do remove\n this.pageElement.removeElement(element);\n\n // CD-3 — element:removed fires raw (no debounce) so host listeners\n // (Wave 4 SavedTicker, future Wave 14 Layers tree) can react in the\n // same frame. The structure:remove history commit independently fires\n // history:commit + document:changed (debounced) via HistoryManager.\n if (elementUid != null) {\n this.events.emit(Builder.EVENTS.ELEMENT_REMOVED, {\n elementUid: elementUid,\n elementType: elementType\n });\n }\n }\n }, {\n key: \"renderElementControls\",\n value: function renderElementControls(element) {\n var _this7 = this;\n // W6.A.A.1: cookbook presets without a settings sidebar pass\n // `settingsContainer: null` — element selection still mounts overlays\n // + applies the highlight, but there is no panel to render controls\n // into. Bail before any DOM work; sync subscriptions stay disposed\n // by the unselect path so nothing leaks across selections.\n if (!this.settingsContainer) {\n this._activeControlList = [];\n return;\n }\n var container = this.settingsContainer;\n\n // Phase 1.8 (SA invariant I14) — dispose outgoing controls BEFORE we\n // replace the DOM. Any Control that subscribed to element state\n // (via element.addSyncListener) or held DOM listeners / observers\n // stashed disposers on itself via BaseControl.addDisposer. Calling\n // destroy() here is the single teardown point — without it,\n // subscriptions would outlive the Control instance and leak across\n // sidebar rebuilds. Guarded so plain controls without destroy pass\n // through untouched (back-compat).\n var prevControls = this._activeControlList || [];\n var _iterator6 = _createForOfIteratorHelper(prevControls),\n _step6;\n try {\n for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {\n var ctrl = _step6.value;\n if (ctrl && typeof ctrl.destroy === 'function') {\n try {\n ctrl.destroy();\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[bjs:builder] control destroy threw:', err);\n }\n }\n }\n } catch (err) {\n _iterator6.e(err);\n } finally {\n _iterator6.f();\n }\n this._activeControlList = [];\n\n // Settings panel shell — breadcrumb, element header (name + action\n // icons), then the control list. 2026-04-17 refinement:\n // - `.bjs-settings-header` is the canonical panel-header primitive:\n // bold element name left + icon-button toolbar right +\n // 1 px border-bottom, 16 px inset (matches the section\n // header treatment).\n // - Action icons are `.bjs-icon-btn` (32 px square) grouped in a\n // subtle `.bjs-settings-actions` pill. No more Bootstrap\n // `.btn-light .p-1 .d-flex`.\n // - Dropped the dedicated \"CONFIGURATIONS\" section header —\n // user flagged it as redundant noise 2026-04-17. The element\n // header above is the only divider needed before the control list.\n container.innerHTML = \"\\n <div class=\\\"settings-container styles-box shadow-sm rounded-0 bg-white\\\">\\n <div class=\\\"settings-breadcrumb\\\" style=\\\"width:100%;overflow-x:auto;\\\">\\n <span data-control=\\\"breadcrumb\\\" class=\\\"d-flex align-items-center\\\"></span>\\n </div>\\n <div class=\\\"bjs-settings-header\\\">\\n <h4 class=\\\"bjs-settings-header-title\\\">\".concat(element.getName(), \"</h4>\\n <div data-control=\\\"actions\\\" class=\\\"bjs-settings-actions\\\"></div>\\n </div>\\n <div data-control=\\\"settings-controls-container\\\"></div>\\n </div>\\n \");\n var currentElement = element.container;\n var breadcrumbContent = container.querySelector('[data-control=\"breadcrumb\"]');\n var _loop = function _loop() {\n breadcrumbItem = document.createElement('a');\n breadcrumbItem.setAttribute('class', 'd-flex align-items-center py-2 px-2 settings-breadcrumb-item text-nowrap');\n breadcrumbItem.setAttribute('href', 'javascript:;');\n breadcrumbItem.innerHTML = currentElement.getName() + '<span class=\"material-symbols-rounded settings-breadcrumb-arrow\" style=\"margin-right:-17px\">arrow_right</span>';\n if (currentElement.getClassName() === 'PageElement') {\n breadcrumbItem.innerHTML = \"<span class=\\\"material-symbols-rounded\\\">home</span>\";\n }\n\n // prepend breadcrumbItem to breadcrumbContent\n breadcrumbContent.prepend(breadcrumbItem);\n\n // click event\n var i = currentElement; // capture the current value of currentElement\n\n breadcrumbItem.addEventListener('click', function () {\n _this7.selectElement(i);\n });\n currentElement = currentElement.container;\n },\n breadcrumbItem;\n while (currentElement) {\n _loop();\n }\n\n //\n var controls = element.getControls();\n // Host injection — controls are emitted lazily on selection (NOT\n // adopted by `_adopt()` which only walks elements + overlays).\n // Assign `host = this` here so each control can reach the bus,\n // pin-set, recent-color LRU, active-control slot, etc., without\n // any global reach-in.\n var _iterator7 = _createForOfIteratorHelper(controls),\n _step7;\n try {\n for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {\n var c = _step7.value;\n if (c) c.host = this;\n }\n // Track the new control list so the NEXT renderElementControls call\n // can tear them down via destroy() — Phase 1.8 SA I14.\n } catch (err) {\n _iterator7.e(err);\n } finally {\n _iterator7.f();\n }\n this._activeControlList = controls.slice();\n // (No \"CONFIGURATIONS\" divider — removed 2026-04-17; the element\n // header above is the only panel-level heading needed.)\n\n // render element controls\n var controlsContainer = container.querySelector('[data-control=\"settings-controls-container\"]');\n controls.forEach(function (control) {\n var controlObj = control.domNode;\n controlsContainer.appendChild(controlObj);\n\n //\n if (control.afterRender) {\n control.afterRender();\n }\n });\n\n // 2026-04-18 panel parent-merge: for content elements (anything whose\n // container is a CellElement or GridElement), append the parent-chain\n // sections at the bottom of the panel as collapsed `<details>`. Each\n // section renders the parent's full control list so the author can\n // edit cell / grid settings without leaving the current selection.\n //\n // Rules:\n // - Only content-inside-container situations. If the selected element\n // IS a Cell or Grid, don't merge (it's already at the target\n // scope).\n // - Walk at most 2 levels up (typical: Block → Cell → Grid). Stop\n // before hitting PageElement.\n // - Collapsed by default — keeps the panel compact; authors expand\n // when they need the section.\n // - Section labels carry a \"(parent)\" qualifier so control labels\n // reading like \"Padding\" or \"Background\" aren't confused with\n // this-element-level controls of the same name.\n this._renderParentSections(element, controlsContainer);\n\n // Render head actions — select-parent / copy / delete / unselect.\n // Uses `.bjs-icon-btn` (32 px square) so the toolbar feels clicky\n // instead of the prior cramped `.btn-light .p-1`.\n element.getActions().forEach(function (action) {\n var actionButton = document.createElement('button');\n actionButton.className = 'element-action-item bjs-icon-btn';\n actionButton.type = 'button';\n actionButton.setAttribute('data-tooltip', action.label);\n actionButton.setAttribute('aria-label', action.label);\n actionButton.innerHTML = \"<span class=\\\"material-symbols-rounded\\\">\".concat(action.icon, \"</span>\");\n container.querySelector('[data-control=\"actions\"]').appendChild(actionButton);\n actionButton.addEventListener('click', function () {\n return action.run();\n });\n });\n }\n }, {\n key: \"_renderParentSections\",\n value: function _renderParentSections(element, controlsContainer) {\n var _this8 = this;\n if (!element || !element.container) return;\n var selfClass = element.getClassName && element.getClassName();\n if (selfClass === 'CellElement' || selfClass === 'GridElement' || selfClass === 'PageElement') return;\n var parents = [];\n var cur = element.container;\n var depth = 0;\n while (cur && cur.getClassName && cur.getClassName() !== 'PageElement' && depth < 2) {\n parents.push(cur);\n cur = cur.container;\n depth++;\n }\n if (!parents.length) return;\n parents.forEach(function (parent, idx) {\n var klass = parent.getClassName();\n var label = parent.getName ? parent.getName() : klass;\n // Nested: outer wraps inner so CELL sits above GRID when the chain\n // is `Block inside Cell inside Grid`. We also render them in the\n // order they appear in the container chain (direct parent first).\n var details = document.createElement('details');\n details.className = 'bjs-panel-parent-section';\n details.setAttribute('data-parent-class', klass);\n details.open = false;\n var summary = document.createElement('summary');\n summary.className = 'bjs-panel-parent-summary';\n summary.innerHTML = \"\\n <span class=\\\"material-symbols-rounded bjs-panel-parent-icon\\\" aria-hidden=\\\"true\\\">\".concat(klass === 'CellElement' ? 'view_column' : klass === 'GridElement' ? 'grid_view' : 'dashboard', \"</span>\\n <span class=\\\"bjs-panel-parent-label\\\">\").concat(label.toUpperCase(), \" <small class=\\\"bjs-panel-parent-qualifier\\\">(\").concat(idx === 0 ? 'parent' : 'grandparent', \")</small></span>\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-panel-parent-select\\\" data-parent-select data-tooltip=\\\"Select this \").concat(label, \"\\\" aria-label=\\\"Select this \").concat(label, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">arrow_forward</span>\\n </button>\\n <span class=\\\"material-symbols-rounded bjs-panel-parent-chevron\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n \");\n details.appendChild(summary);\n var body = document.createElement('div');\n body.className = 'bjs-panel-parent-body';\n details.appendChild(body);\n\n // Render the parent's own controls into the section body. We\n // intentionally re-invoke getControls() so the parent constructs\n // fresh control instances with its own state + callbacks —\n // editing here mutates the parent and re-renders canvas.\n try {\n var parentControls = parent.getControls();\n // Host injection — same as the primary getControls() path.\n var _iterator8 = _createForOfIteratorHelper(parentControls),\n _step8;\n try {\n for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {\n var c = _step8.value;\n if (c) c.host = _this8;\n }\n } catch (err) {\n _iterator8.e(err);\n } finally {\n _iterator8.f();\n }\n parentControls.forEach(function (c) {\n if (c && c.domNode) body.appendChild(c.domNode);\n if (c && c.afterRender) c.afterRender();\n });\n } catch (err) {\n console.warn(\"[parent-merge] failed to render \".concat(klass, \" controls:\"), err);\n body.innerHTML = \"<div class=\\\"bjs-panel-parent-error\\\">Could not render \".concat(label, \" settings: \").concat(err.message, \"</div>\");\n }\n\n // Wire the \"select this parent\" jump button.\n var selectBtn = summary.querySelector('[data-parent-select]');\n if (selectBtn) {\n selectBtn.addEventListener('click', function (ev) {\n ev.preventDefault();\n ev.stopPropagation();\n _this8.selectElement(parent);\n });\n }\n controlsContainer.appendChild(details);\n });\n }\n\n /**\n * Builder-mode helper CSS. Returned as a raw string so `_injectIframeHelpers`\n * can wrap it in a single <style data-helper-id=\"debug-css\"> node that\n * survives PageElement.render() head replacement. See `_injectIframeHelpers`\n * for the re-injection contract — this method has no side effects.\n */\n }, {\n key: \"_getDebugCss\",\n value: function _getDebugCss() {\n return \"\\n /* Holed-box primitive \\u2014 minimal iframe-local copy of just\\n the classes the focus-dim spotlight needs. Main builder.css\\n lives in the parent document; iframe needs its own copy\\n because the spotlight mounts into iframe body. --blur is\\n NOT mirrored here: focus-dim went blur-less to sidestep\\n the Chrome/Safari backdrop-filter \\xD7 clip-path compositing\\n quirk (filtered snapshot leaks into the hole area \\u2014 user\\n report \\\"dim blur lu\\xF4n c\\u1EA3 element \\u0111ang ch\\u1ECDn\\\"). Dim is\\n black-alpha which reads as neutral gray on any canvas. */\\n .bjs-holed-box {\\n position: absolute;\\n inset: 0;\\n pointer-events: none;\\n }\\n .bjs-holed-box--dim {\\n background-color: rgba(0, 0, 0, 0.42);\\n }\\n\\n /* Focus-dim spot transition \\u2014 single holed-box element, so\\n only one selector to target. */\\n .bjs-focus-dim-spot {\\n transition: opacity 0.18s ease;\\n }\\n @media (prefers-reduced-motion: reduce) {\\n .bjs-focus-dim-spot { transition: none; }\\n }\\n\\n [builder-element] {\\n cursor: pointer;\\n position: relative;\\n }\\n\\n [builder-element]::before {\\n font-size: 10px!important;\\n }\\n \\n .builder-mode-design [builder-element=\\\"PageElement\\\"] {\\n display: flex;\\n flex-direction: column;\\n gap: 10px;\\n padding: 30px;\\n background-color: #f0f0f0;\\n position: relative;\\n }\\n\\n .builder-mode-design [builder-element]::before {\\n font-family: monospace;\\n font-size: 90%;\\n position: absolute;\\n top: 0;\\n right: 0;\\n font-weight: bold;\\n color: #333;\\n border: solid 1px #ddd;\\n padding: 2px 5px;\\n border-top: none;\\n border-right: none;\\n\\n pointer-events: none;\\n }\\n\\n .builder-mode-design [builder-element=\\\"PageElement\\\"]::before {\\n content: \\\"PageElement\\\";\\n pointer-events: none;\\n }\\n\\n .builder-mode-design [builder-element=\\\"BlockElement\\\"] {\\n display: flex;\\n flex-direction: column;\\n gap: 10px;\\n padding: 15px;\\n background-color: #e0e0e0;\\n border: 1px solid #ccc;\\n margin-bottom: 10px;\\n position: relative;\\n }\\n\\n .builder-mode-design [builder-element=\\\"BlockElement\\\"]::before {\\n content: \\\"BlockElement\\\";\\n border-color: #ccc;\\n\\n pointer-events: none;\\n }\\n\\n .builder-mode-design [builder-element=\\\"H1Element\\\"] {\\n padding: 10px;\\n background-color: #cfdce4;\\n border: 1px solid #bbb;\\n position: relative;\\n }\\n\\n .builder-mode-design [builder-element=\\\"H1Element\\\"]::before {\\n content: \\\"H1Element\\\";\\n border-color: #bbb;\\n font-size: initial;\\n\\n pointer-events: none;\\n }\\n\\n .builder-mode-design [builder-element=\\\"PElement\\\"] {\\n padding: 10px;\\n background-color: #cfdce4;\\n border: 1px solid #bbb;\\n position: relative;\\n }\\n\\n .builder-mode-design [builder-element=\\\"PElement\\\"]::before {\\n content: \\\"PElement\\\";\\n border-color: #bbb;\\n\\n pointer-events: none;\\n }\\n\\n .builder-mode-design [builder-element=\\\"MenuElement\\\"] {\\n padding: 10px;\\n background-color: #cfdce4;\\n border: 1px solid #bbb;\\n position: relative;\\n }\\n\\n .builder-mode-design [builder-element=\\\"MenuElement\\\"]::before {\\n content: \\\"MenuElement\\\";\\n border-color: #bbb;\\n\\n pointer-events: none;\\n }\\n .builder-mode-design [builder-element=\\\"GridElement\\\"] {\\n gap: 10px;\\n padding: 10px;\\n background-color: #ccc;\\n border: 1px solid #aaa;\\n margin: 10px 0;\\n position: relative;\\n }\\n\\n .builder-mode-design [builder-element=\\\"GridElement\\\"]::before {\\n content: \\\"GridElement\\\";\\n border-color: #bbb;\\n\\n pointer-events: none;\\n }\\n\\n .builder-mode-design [builder-element=\\\"CellElement\\\"] {\\n padding: 10px;\\n background-color: #e0e0e0;\\n border: 1px solid #aaa;\\n margin: 10px 0;\\n position: relative;\\n }\\n\\n .builder-mode-design [builder-element=\\\"CellElement\\\"]::before {\\n content: \\\"CellElement\\\";\\n border-color: #ccc;\\n\\n pointer-events: none;\\n }\\n\\n [builder-element=\\\"BlockElement\\\"] {\\n position: relative;\\n }\\n\\n /* inside iframe's document */\\n ::-webkit-scrollbar {\\n width: 7px;\\n height: 7px;\\n }\\n\\n ::-webkit-scrollbar-thumb {\\n background: rgba(0, 0, 0, 0.3);\\n border-radius: 4px;\\n }\\n\\n ::-webkit-scrollbar-track {\\n background: transparent;\\n }\\n\\n [contenteditable] {\\n outline: none!important;\\n -webkit-focus-ring-color: transparent;\\n }\\n\\n [contenteditable]:focus, [contenteditable]:focus-visible {\\n outline: none!important;\\n border-color: transparent!important;\\n box-shadow: none!important;\\n -webkit-focus-ring-color: transparent;\\n }\\n\\n /* Kill default browser focus outline on every focusable element in design iframe */\\n *:focus, *:focus-visible, *:focus-within {\\n outline: none!important;\\n -webkit-focus-ring-color: transparent;\\n }\\n\\n input, select, textarea, button {\\n pointer-events: none;\\n }\\n input:focus, select:focus, textarea:focus, button:focus,\\n input:focus-visible, select:focus-visible, textarea:focus-visible, button:focus-visible {\\n outline: none!important;\\n box-shadow: none!important;\\n border-color: inherit!important;\\n }\\n\\n /* PLAN_UNDO_REDO W7.3 \\u2014 history apply suppression.\\n * HistoryManager._apply toggles .bjs-history-applying on\\n * <body> around the render pass. Disables ALL transitions\\n * and animations iframe-wide so undo/redo snaps instantly\\n * to the target state \\u2014 no block fade-in cascade, no shake,\\n * no jank. Standard batch-update pattern. 2x rAF in\\n * HistoryManager._apply keeps the class on through layout\\n * plus paint \\u2014 post-apply interactions resume with full\\n * motion. */\\n body.bjs-history-applying,\\n body.bjs-history-applying *,\\n body.bjs-history-applying *::before,\\n body.bjs-history-applying *::after {\\n transition: none !important;\\n animation: none !important;\\n animation-duration: 0s !important;\\n animation-delay: 0s !important;\\n }\\n \";\n }\n }, {\n key: \"validateKeysUsage\",\n value: function validateKeysUsage(html, keys, failedCallback) {\n // Scan every identifier inside each <% ... %> block, not just the first\n // token after <%. Templates may legitimately access a required key from\n // inside a nested expression — e.g. `<% if (blocks && blocks.length) {\n // blocks.forEach(...) %>` — where the leading token is `if`, not the key\n // itself. Grabbing only the first word produced false-positive\n // \"DESIGN ERROR: Template does not use required key: blocks\" warnings.\n var blockRegex = /<%[=\\-]?([\\s\\S]*?)%>/g;\n var idRegex = /[A-Za-z_][\\w]*/g;\n var usedKeys = new Set();\n var blockMatch;\n while ((blockMatch = blockRegex.exec(html)) !== null) {\n var body = blockMatch[1];\n var idMatch = void 0;\n while ((idMatch = idRegex.exec(body)) !== null) {\n usedKeys.add(idMatch[0]);\n }\n }\n var unusedKeys = keys.filter(function (k) {\n return !usedKeys.has(k);\n });\n if (unusedKeys.length > 0) {\n if (typeof failedCallback === 'function') {\n failedCallback(unusedKeys);\n } else {\n _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].alert({\n title: _I18n_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].t('errors.unused_ejs_keys_title', 'Unused EJS keys'),\n message: \"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].t('errors.unused_ejs_keys_msg', 'The following template keys were not used during render:'), \" \").concat(unusedKeys.join(', ')),\n kind: 'warn'\n });\n throw new Error(\"Unused EJS keys: \".concat(unusedKeys.join(', ')));\n }\n }\n }\n }, {\n key: \"renderTemplate\",\n value: function renderTemplate(template) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var html = this.getTemplate(template);\n\n // EJS render — elements resolve their own URLs via transferMediaAbsUrl()\n // before passing to templates, so no post-processing needed here.\n html = ejs.render(html, options);\n return html;\n }\n\n /**\n * Convert a relative asset path to an absolute URL using themeMediaUrl.\n *\n * Relative paths stored in template JSON (e.g. \"assets/profile_image/avatar.png\")\n * become absolute for the browser (e.g. \"https://app.example.com/p/templates/000abc/assets/profile_image/avatar.png\").\n *\n * Already-absolute URLs (http://, https://), root-relative (/path), anchors (#),\n * template tags ([[tag]], {tag}), and data URIs (data:image/...) are returned as-is.\n *\n * Inverse operation: getHtmlWithRelativeLinks() strips themeMediaUrl back out for saving.\n *\n * @param {string} url - The URL to resolve (may be relative or absolute).\n * @returns {string} Absolute URL if input was relative, otherwise unchanged.\n */\n }, {\n key: \"transferMediaAbsUrl\",\n value: function transferMediaAbsUrl(url) {\n if (!/^https?:\\/\\//i.test(url) && !url.startsWith('/') && !url.startsWith('#') && !url.startsWith('/javascript:;') && !url.startsWith('[[') && !url.startsWith('[') && !url.startsWith('{') && !url.startsWith('data:image')) {\n return this.themeMediaUrl + '/' + url;\n } else {\n return url;\n }\n }\n }, {\n key: \"browseMedia\",\n value: function browseMedia(onSelectCallback) {\n this.fileManager.browseFile(onSelectCallback);\n }\n }, {\n key: \"closeBrowseMedia\",\n value: function closeBrowseMedia() {\n var modal = document.getElementById('filemanagerModal');\n if (modal) {\n var bootstrapModal = bootstrap.Modal.getInstance(modal);\n if (bootstrapModal) {\n bootstrapModal.hide();\n }\n }\n modal.remove();\n }\n\n /**\n * Register a custom element class so JSON documents containing\n * `{ \"name\": \"<typeName>\", … }` can parse + render via the canvas pipeline.\n *\n * AIBuilder Wave 1 — CD-1 (2026-05-04). Replaces the previously frozen\n * `ELEMENT_REGISTRY` plain object with a mutable `Map`. Host apps (e.g. the\n * AI Builder WordPress plugin) call this BEFORE `builder.load()` to add\n * host-specific element types (T4 — see AIBuilder DESIGN.md §3) without\n * forking BuilderJS. Existing JSON samples continue to render byte-identical\n * (N16) — this method only adds capability, never removes.\n *\n * Re-registering an existing name is allowed (replaces) so a plugin can\n * override a stock element (e.g. provide its own HeadingElement variant);\n * the responsibility for the resulting compatibility lies with the host.\n *\n * @param {string} name JSON `name` field used in saved templates (e.g. `\"WPNavMenuElement\"`).\n * @param {Function} klass Element class. Must expose `static parse(data)` returning an instance.\n * @throws {Error} when `name` is not a non-empty string or `klass.parse` is not callable.\n *\n * @example\n * class WPNavMenuElement extends BaseElement {\n * static parse(data) { … }\n * render() { … }\n * }\n * Builder.registerElement('WPNavMenuElement', WPNavMenuElement);\n * await builder.load(json, themeTemplates, themeConfig, themeMediaUrl);\n */\n /**\n * Frozen enum of canonical event names emitted on `builder.events` AND\n * expected by host apps subscribing for save / dirty / element-graph\n * concerns. Use these constants instead of string literals so a typo\n * surfaces at parse-time and renames are tractable.\n *\n * AIBuilder Wave 4 — CD-3 (2026-05-05). See `docs/core/USAGE.md`\n * \"Event bus (CD-3)\" for the full table including payload shapes,\n * debounce config, and host-vs-engine emitter ownership.\n *\n * Adding a new event = update this enum + the canonical-events table +\n * R-bjs-docs in one commit.\n */\n }, {\n key: \"getRenderedBlocks\",\n value:\n /**\n * Return the rendered body inner HTML of the canvas — no `<html>`, no\n * `<head>`, no `<body>` wrap. Stripped of editor-only artefacts identically\n * to `getHtml()` (no `data-control=\"builder-helper\"` nodes, no\n * `[contenteditable]`/`[inline-edit]` attrs, no editor-only `overflow:hidden`\n * on `<html>`). Theme media URLs are converted back to relative paths\n * matching `getHtmlWithRelativeLinks()` so the saved cache is portable\n * across domains / templates.\n *\n * AIBuilder Wave 1 — CD-1c (2026-05-04). Added so host apps can cache the\n * canvas-rendered blocks without owning the surrounding `<html>` shell —\n * the WordPress plugin wraps this body inner via 3 PHP page templates\n * (theme-default / canvas-only / fullwidth) so the same cache serves all\n * three modes. See AIBuilder DESIGN.md §5.\n *\n * @returns {string} Body inner HTML, sanitized of editor-only attributes,\n * with relative theme asset paths.\n */\n function getRenderedBlocks() {\n // Clone the document — same invariant as getHtml. Pre-2026-05-20 this\n // mutated the live iframe DOM directly (stripping builder-helper\n // styles + inline-edit attrs in place); that was an unrelated\n // dormant bug because PageElement.render() runs\n // `_injectIframeHelpers` afterwards and re-injects the autosize\n // override, so users never saw the half-second of broken layout.\n // Switching to clone-then-clean kills that race AND lets us route\n // through the shared `_sanitiseForExport` so HARD RULE T11 (no\n // block tags inside inline-edit hosts) is enforced for THIS export\n // path too — saved HTML round-trip parity with `getHtml()`.\n var htmlDoc = this.iframe.contentDocument.documentElement.cloneNode(true);\n this._sanitiseForExport(htmlDoc);\n\n // Body-inner — query the CLONE's body (not the live iframe).\n var body = htmlDoc.querySelector('body');\n if (!body) return '';\n var inner = body.innerHTML;\n\n // Match getHtmlWithRelativeLinks() — strip themeMediaUrl prefix so the\n // saved cache is portable across domains / template installs.\n if (this.themeMediaUrl) {\n inner = inner.split(this.themeMediaUrl + '/').join('');\n }\n return inner;\n }\n }], [{\n key: \"registerElement\",\n value: function registerElement(name, klass) {\n if (typeof name !== 'string' || !name) {\n throw new Error('Builder.registerElement: name must be a non-empty string');\n }\n if (!klass || typeof klass.parse !== 'function') {\n throw new Error(\"Builder.registerElement(\\\"\".concat(name, \"\\\"): klass.parse(data) must be a function\"));\n }\n var constructorName = klass.name || name;\n _ElementFactory_js__WEBPACK_IMPORTED_MODULE_17__.ELEMENT_REGISTRY.set(name, constructorName);\n // Mirror onto window so ElementFactory.getElementClass() can resolve it\n // — same lookup path stock elements use.\n if (typeof window !== 'undefined') {\n window[constructorName] = klass;\n }\n }\n }]);\n}();\n_defineProperty(Builder, \"EVENTS\", Object.freeze({\n DOCUMENT_CHANGED: 'document:changed',\n DOCUMENT_SAVED: 'document:saved',\n ELEMENT_ADDED: 'element:added',\n ELEMENT_REMOVED: 'element:removed',\n // W6.A.A.4 — fires on every `setMode(mode)` call with `{from, to}`.\n // Cookbook chrome presets subscribe to keep header pills in sync.\n // Originally paired with `theme:changed` in the W6 plan; that one\n // was deferred because Builder.js has no `setTheme()` API yet —\n // theme switching today is page-reload, so there is no caller to\n // emit from. Will land alongside a future setTheme method (likely\n // when a no-reload theme-swap cookbook variant ships).\n MODE_CHANGED: 'mode:changed'\n}));\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Builder);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/Builder.js?");
/***/ }),
/***/ "./src/includes/BuilderJsonStructureValidator.js":
/*!*******************************************************!*\
!*** ./src/includes/BuilderJsonStructureValidator.js ***!
\*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar BuilderJsonStructureValidator = /*#__PURE__*/function () {\n function BuilderJsonStructureValidator() {\n _classCallCheck(this, BuilderJsonStructureValidator);\n this.pageElements = new Set(['PageElement']);\n this.blockElements = new Set(['BlockElement']);\n this.gridElements = new Set(['GridElement', 'PricingCardsElement']);\n this.cellElements = new Set(['CellElement', 'PricingCardElement', 'FormContainerCell']);\n this.supportedLeafElements = new Set(['HeadingElement', 'H1Element', 'H2Element', 'H3Element', 'H4Element', 'H5Element', 'PElement', 'LabelElement', 'LinkElement', 'AlertElement', 'ImageElement', 'VideoElement', 'YoutubeElement', 'SocialIconsElement', 'FieldElement', 'TextInputElement', 'SelectElement', 'RadioElement', 'CheckboxElement', 'CheckoutElement', 'CheckoutSimpleElement', 'ListElement', 'MenuElement', 'RSSElement', 'ButtonElement', 'SubmitButtonElement', 'DividerElement', 'HTMLElement']);\n this.requiredAttributes = {\n HeadingElement: ['text', 'type'],\n H1Element: ['text'],\n H2Element: ['text'],\n H3Element: ['text'],\n H4Element: ['text'],\n H5Element: ['text'],\n PElement: ['text'],\n LabelElement: ['text'],\n LinkElement: ['text', 'url'],\n AlertElement: ['text'],\n ImageElement: ['src'],\n VideoElement: ['src'],\n YoutubeElement: ['url'],\n SocialIconsElement: ['items'],\n FieldElement: [],\n TextInputElement: [],\n SelectElement: ['items'],\n RadioElement: ['items'],\n CheckboxElement: ['items'],\n CheckoutElement: [],\n CheckoutSimpleElement: [],\n ListElement: ['items'],\n MenuElement: ['items'],\n RSSElement: [],\n ButtonElement: ['text', 'url'],\n SubmitButtonElement: ['text'],\n DividerElement: [],\n HTMLElement: ['html'],\n PageElement: ['blocks'],\n BlockElement: ['elements'],\n GridElement: ['cells'],\n PricingCardsElement: ['cells'],\n CellElement: ['blocks'],\n PricingCardElement: ['blocks'],\n FormContainerCell: ['blocks']\n };\n }\n return _createClass(BuilderJsonStructureValidator, [{\n key: \"validate\",\n value: function validate(data) {\n var _this = this;\n if (!data || _typeof(data) !== 'object' || Array.isArray(data)) {\n throw new Error('Builder JSON root must be an object.');\n }\n this.assertNodeShape(data, 'root');\n if (!this.pageElements.has(data.name)) {\n throw new Error('Builder JSON root must be a PageElement or supported page subclass.');\n }\n this.assertArray(data.blocks, 'root.blocks');\n data.blocks.forEach(function (block, index) {\n return _this.assertPageBlock(block, \"root.blocks.\".concat(index));\n });\n }\n }, {\n key: \"assertPageBlock\",\n value: function assertPageBlock(node, path) {\n var _this2 = this;\n this.assertNodeShape(node, path);\n if (!this.blockElements.has(node.name)) {\n throw new Error(\"\".concat(path, \" must be a BlockElement or supported block subclass.\"));\n }\n this.assertRequiredAttributes(node, path);\n this.assertArray(node.elements, \"\".concat(path, \".elements\"));\n node.elements.forEach(function (element, index) {\n return _this2.assertBlockChild(element, \"\".concat(path, \".elements.\").concat(index));\n });\n }\n }, {\n key: \"assertBlockChild\",\n value: function assertBlockChild(node, path) {\n this.assertNodeShape(node, path);\n if (this.pageElements.has(node.name)) {\n throw new Error(\"\".concat(path, \" cannot use PageElement inside BlockElement.elements.\"));\n }\n if (this.cellElements.has(node.name)) {\n throw new Error(\"\".concat(path, \" cannot use CellElement inside BlockElement.elements.\"));\n }\n if (this.gridElements.has(node.name)) {\n this.assertGrid(node, path);\n return;\n }\n if (this.blockElements.has(node.name)) {\n throw new Error(\"\".concat(path, \" cannot use block-like elements inside BlockElement.elements.\"));\n }\n if (!this.supportedLeafElements.has(node.name)) {\n throw new Error(\"\".concat(path, \" uses unsupported element `\").concat(node.name, \"`.\"));\n }\n this.assertRequiredAttributes(node, path);\n }\n }, {\n key: \"assertGrid\",\n value: function assertGrid(node, path) {\n var _this3 = this;\n this.assertRequiredAttributes(node, path);\n this.assertArray(node.cells, \"\".concat(path, \".cells\"));\n node.cells.forEach(function (cell, index) {\n return _this3.assertCell(cell, \"\".concat(path, \".cells.\").concat(index));\n });\n }\n }, {\n key: \"assertCell\",\n value: function assertCell(node, path) {\n var _this4 = this;\n this.assertNodeShape(node, path);\n if (!this.cellElements.has(node.name)) {\n throw new Error(\"\".concat(path, \" must be a CellElement.\"));\n }\n this.assertRequiredAttributes(node, path);\n this.assertArray(node.blocks, \"\".concat(path, \".blocks\"));\n node.blocks.forEach(function (block, index) {\n return _this4.assertPageBlock(block, \"\".concat(path, \".blocks.\").concat(index));\n });\n }\n }, {\n key: \"assertNodeShape\",\n value: function assertNodeShape(node, path) {\n if (!node || _typeof(node) !== 'object' || Array.isArray(node)) {\n throw new Error(\"\".concat(path, \" must be an object.\"));\n }\n if (typeof node.name !== 'string' || node.name.trim() === '') {\n throw new Error(\"\".concat(path, \".name is required.\"));\n }\n if (typeof node.template !== 'string' || node.template.trim() === '') {\n throw new Error(\"\".concat(path, \".template is required.\"));\n }\n if (!Object.prototype.hasOwnProperty.call(node, 'formats')) {\n throw new Error(\"\".concat(path, \".formats is required.\"));\n }\n\n // if (!node.formats || typeof node.formats !== 'object' || Array.isArray(node.formats)) {\n // throw new Error(`${path}.formats must be an object.`);\n // }\n }\n }, {\n key: \"assertRequiredAttributes\",\n value: function assertRequiredAttributes(node, path) {\n var required = this.requiredAttributes[node.name] || [];\n required.forEach(function (attribute) {\n if (!Object.prototype.hasOwnProperty.call(node, attribute)) {\n throw new Error(\"\".concat(path, \".\").concat(attribute, \" is required for \").concat(node.name, \".\"));\n }\n });\n }\n }, {\n key: \"assertArray\",\n value: function assertArray(value, path) {\n if (!Array.isArray(value)) {\n throw new Error(\"\".concat(path, \" must be an array.\"));\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BuilderJsonStructureValidator);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BuilderJsonStructureValidator.js?");
/***/ }),
/***/ "./src/includes/BuilderjsPopup.js":
/*!****************************************!*\
!*** ./src/includes/BuilderjsPopup.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/*\n * BuilderjsPopup — themed replacement for native window.alert / confirm / prompt\n *\n * Why: native dialogs look ugly, can't be styled to match the builder theme,\n * block the browser event loop, and don't respect dark mode. BuilderjsPopup\n * is a pure-DOM, Promise-based, keyboard-accessible modal that matches the\n * rest of the `.bjs-*` design system.\n *\n * Public API — static helpers cover 95% of use cases:\n *\n * await BuilderjsPopup.alert({\n * title: 'Template not found',\n * message: 'The \"xyz\" template could not be located.',\n * kind: 'error', // info | warn | error | success\n * });\n *\n * const ok = await BuilderjsPopup.confirm({\n * title: 'Delete block?',\n * message: 'This cannot be undone.',\n * okLabel: 'Delete',\n * cancelLabel: 'Keep',\n * destructive: true, // red OK button\n * });\n *\n * const url = await BuilderjsPopup.prompt({\n * title: 'Image link URL',\n * label: 'URL',\n * value: 'https://…',\n * placeholder: 'https://example.com',\n * validate: (v) => /^https?:\\/\\//.test(v) || 'URL must start with http(s)://',\n * });\n * if (url === null) return; // user cancelled\n *\n * Semantics match native:\n * - alert → Promise<void> (resolves on OK or Esc)\n * - confirm → Promise<boolean> (true = OK; false = Cancel/Esc)\n * - prompt → Promise<string | null> (string = OK; null = Cancel/Esc)\n *\n * Advanced (instance) API — use directly for custom forms (multi-field,\n * conditional UI, etc.). Not currently consumed in the builder; static\n * helpers cover the existing native-dialog callsites.\n *\n * const popup = new BuilderjsPopup({ title, bodyRenderer: (container) => {...} });\n * const result = await popup.open(); // resolves when popup.close(value) is called\n *\n * Accessibility:\n * - role=\"dialog\" + aria-modal=\"true\" + aria-labelledby + aria-describedby\n * - Focus trap (Tab cycles within popup; Shift+Tab reverses)\n * - Focus restoration (returns to previously-focused element on close)\n * - Esc cancels; Enter confirms (or submits when input is focused)\n *\n * Styling: see /* Builderjs Popup *\\/ section in src/builder.css. Uses the\n * same `.bjs-*` design tokens as the rest of the builder — light + dark\n * mode inherit automatically.\n *\n * Stacking:\n * - z-index: 10000 (above Canvas Overlay System which sits at 1000)\n * - Mounts in parent `document.body`; safe when builder is in an iframe.\n */\n\nvar FOCUSABLE = ['a[href]', 'button:not([disabled])', 'input:not([disabled]):not([type=\"hidden\"])', 'select:not([disabled])', 'textarea:not([disabled])', '[tabindex]:not([tabindex=\"-1\"])'].join(',');\n\n// Icon glyphs (material-symbols-rounded — already loaded by builder)\nvar ICONS = {\n info: 'info',\n warn: 'warning',\n error: 'error',\n success: 'check_circle'\n};\nvar BuilderjsPopup = /*#__PURE__*/function () {\n function BuilderjsPopup() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _classCallCheck(this, BuilderjsPopup);\n this.options = Object.assign({\n title: '',\n message: '',\n kind: 'info',\n okLabel: 'OK',\n cancelLabel: 'Cancel',\n showCancel: false,\n destructive: false,\n bodyRenderer: null // optional custom body renderer\n }, options);\n this._resolve = null;\n this._previousFocus = null;\n this._rootNode = null;\n this._onKeyDown = this._onKeyDown.bind(this);\n }\n\n // ─── Static helpers ─────────────────────────────────────────────────────\n return _createClass(BuilderjsPopup, [{\n key: \"open\",\n value:\n // ─── Instance lifecycle ──────────────────────────────────────────────────\n\n function open() {\n var _this = this;\n return new Promise(function (resolve) {\n _this._resolve = resolve;\n _this._previousFocus = document.activeElement;\n _this._mount();\n // Force reflow before adding .is-open so CSS transition runs\n /* eslint-disable-next-line no-unused-expressions */\n _this._rootNode.offsetWidth;\n _this._rootNode.classList.add('is-open');\n _this._focusInitial();\n document.addEventListener('keydown', _this._onKeyDown, true);\n });\n }\n\n /**\n * Close the popup. Resolves the open() promise with `{ ok, value }` so\n * callers never have to synchronize through static state.\n * - ok === true : user clicked OK (or pressed Enter on alert)\n * - ok === false : user clicked Cancel, pressed Esc (when cancelable),\n * or clicked the backdrop (when cancelable)\n * - value : current input value (prompt only); undefined otherwise\n *\n * If `okOverride` is passed, it replaces the computed ok flag — used by\n * Esc/backdrop paths to force `false` even when no Cancel button is shown.\n */\n }, {\n key: \"close\",\n value: function close(okOverride) {\n if (!this._rootNode) return;\n var ok = typeof okOverride === 'boolean' ? okOverride : true;\n var value = this._ctx && typeof this._ctx.getValue === 'function' ? this._ctx.getValue() : undefined;\n document.removeEventListener('keydown', this._onKeyDown, true);\n this._rootNode.classList.remove('is-open');\n\n // Wait for close animation then detach\n var node = this._rootNode;\n setTimeout(function () {\n if (node && node.parentNode) node.parentNode.removeChild(node);\n }, 220);\n this._rootNode = null;\n\n // Restore focus\n if (this._previousFocus && typeof this._previousFocus.focus === 'function') {\n try {\n this._previousFocus.focus();\n } catch (_) {/* no-op */}\n }\n if (this._resolve) {\n var r = this._resolve;\n this._resolve = null;\n r({\n ok: ok,\n value: value\n });\n }\n }\n\n // ─── Internal ────────────────────────────────────────────────────────────\n }, {\n key: \"_mount\",\n value: function _mount() {\n var _this2 = this;\n var popupId = 'bjs-popup-' + Math.random().toString(36).slice(2, 9);\n var titleId = popupId + '-title';\n var descId = popupId + '-desc';\n var inputId = popupId + '-input';\n this._ctx = {\n inputId: inputId,\n getValue: null,\n autoFocus: null,\n validateSubmit: null\n };\n\n // Backdrop (click-outside to cancel unless alert)\n var backdrop = document.createElement('div');\n backdrop.className = 'bjs-popup-backdrop';\n backdrop.setAttribute('aria-hidden', 'true');\n\n // Popup card\n var popup = document.createElement('div');\n popup.className = 'bjs-popup';\n popup.setAttribute('role', 'dialog');\n popup.setAttribute('aria-modal', 'true');\n popup.setAttribute('aria-labelledby', titleId);\n if (this.options.message) popup.setAttribute('aria-describedby', descId);\n popup.tabIndex = -1;\n\n // Header (icon + title)\n var header = document.createElement('div');\n header.className = 'bjs-popup-header';\n var icon = document.createElement('span');\n icon.className = 'bjs-popup-icon bjs-popup-icon--' + (this.options.kind || 'info');\n icon.innerHTML = '<span class=\"material-symbols-rounded\" aria-hidden=\"true\">' + (ICONS[this.options.kind] || ICONS.info) + '</span>';\n header.appendChild(icon);\n var title = document.createElement('div');\n title.className = 'bjs-popup-title';\n title.id = titleId;\n title.textContent = this.options.title || '';\n header.appendChild(title);\n popup.appendChild(header);\n\n // Body\n var body = document.createElement('div');\n body.className = 'bjs-popup-body';\n if (this.options.message) {\n var message = document.createElement('p');\n message.className = 'bjs-popup-message';\n message.id = descId;\n message.textContent = this.options.message;\n body.appendChild(message);\n }\n if (typeof this.options.bodyRenderer === 'function') {\n this.options.bodyRenderer(body, this._ctx);\n }\n popup.appendChild(body);\n\n // Footer (buttons)\n var footer = document.createElement('div');\n footer.className = 'bjs-popup-footer';\n if (this.options.showCancel) {\n var cancelBtn = document.createElement('button');\n cancelBtn.type = 'button';\n cancelBtn.className = 'bjs-popup-btn bjs-popup-btn--secondary';\n cancelBtn.textContent = this.options.cancelLabel || 'Cancel';\n cancelBtn.addEventListener('click', function () {\n return _this2._cancel();\n });\n footer.appendChild(cancelBtn);\n }\n var okBtn = document.createElement('button');\n okBtn.type = 'button';\n okBtn.className = 'bjs-popup-btn ' + (this.options.destructive ? 'bjs-popup-btn--destructive' : 'bjs-popup-btn--primary');\n okBtn.textContent = this.options.okLabel || 'OK';\n okBtn.addEventListener('click', function () {\n return _this2._submitOk();\n });\n footer.appendChild(okBtn);\n this._okBtn = okBtn;\n popup.appendChild(footer);\n backdrop.appendChild(popup);\n\n // Backdrop click: cancel for prompt/confirm; alert resolves as OK\n // (there's no Cancel button to signal otherwise, and clicking\n // outside a pure alert is a dismissal — matches the native behavior\n // where alert returns regardless of which key dismisses it).\n backdrop.addEventListener('click', function (e) {\n if (e.target !== backdrop) return; // don't close when clicking the card\n if (_this2.options.showCancel) _this2._cancel();else _this2.close(true);\n });\n document.body.appendChild(backdrop);\n this._rootNode = backdrop;\n }\n }, {\n key: \"_submitOk\",\n value: function _submitOk() {\n if (this._ctx && typeof this._ctx.validateSubmit === 'function') {\n if (!this._ctx.validateSubmit()) return; // validation blocked\n }\n this.close(true);\n }\n }, {\n key: \"_cancel\",\n value: function _cancel() {\n this.close(false);\n }\n }, {\n key: \"_focusInitial\",\n value: function _focusInitial() {\n var target = this._ctx && this._ctx.autoFocus || this._okBtn;\n if (target && typeof target.focus === 'function') {\n try {\n target.focus();\n if (target.tagName === 'INPUT') target.select();\n } catch (_) {/* no-op */}\n }\n }\n }, {\n key: \"_onKeyDown\",\n value: function _onKeyDown(e) {\n if (!this._rootNode) return;\n if (e.key === 'Escape') {\n e.preventDefault();\n // Cancelable popup: Esc = Cancel. Alert-only: Esc = OK (dismiss,\n // matches native alert where any dismissal key \"accepts\" the\n // message — there's no cancel signal to send).\n if (this.options.showCancel) this._cancel();else this.close(true);\n return;\n }\n if (e.key === 'Enter') {\n // Enter in a <textarea> stays a newline; Enter elsewhere submits.\n if (e.target && e.target.tagName === 'TEXTAREA') return;\n e.preventDefault();\n this._submitOk();\n return;\n }\n if (e.key === 'Tab') {\n this._trapFocus(e);\n }\n }\n }, {\n key: \"_trapFocus\",\n value: function _trapFocus(e) {\n var focusables = Array.from(this._rootNode.querySelectorAll(FOCUSABLE)).filter(function (el) {\n return el.offsetParent !== null;\n });\n if (focusables.length === 0) return;\n var first = focusables[0];\n var last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }], [{\n key: \"alert\",\n value: function alert() {\n var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n return new BuilderjsPopup(Object.assign({\n showCancel: false\n }, opts)).open().then(function () {\n return undefined;\n });\n }\n }, {\n key: \"confirm\",\n value: function confirm() {\n var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n return new BuilderjsPopup(Object.assign({\n showCancel: true\n }, opts)).open().then(function (result) {\n return !!(result && result.ok);\n });\n }\n\n /** Prompt for text input. Returns the submitted value (string), or null\n * when the user cancels or dismisses via Esc. Empty string is a valid\n * submission (NOT treated as cancel — matches the native prompt when\n * the user clears the field and clicks OK). */\n }, {\n key: \"prompt\",\n value: function prompt() {\n var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var title = opts.title,\n message = opts.message,\n label = opts.label,\n _opts$value = opts.value,\n value = _opts$value === void 0 ? '' : _opts$value,\n _opts$placeholder = opts.placeholder,\n placeholder = _opts$placeholder === void 0 ? '' : _opts$placeholder,\n okLabel = opts.okLabel,\n cancelLabel = opts.cancelLabel,\n validate = opts.validate;\n return new BuilderjsPopup({\n title: title,\n message: message,\n okLabel: okLabel,\n cancelLabel: cancelLabel,\n showCancel: true,\n bodyRenderer: function bodyRenderer(container, ctx) {\n if (label) {\n var labelEl = document.createElement('label');\n labelEl.className = 'bjs-popup-input-label';\n labelEl.textContent = label;\n labelEl.setAttribute('for', ctx.inputId);\n container.appendChild(labelEl);\n }\n var input = document.createElement('input');\n input.type = 'text';\n input.id = ctx.inputId;\n input.className = 'bjs-popup-input';\n input.value = value != null ? String(value) : '';\n input.placeholder = placeholder || '';\n input.autocomplete = 'off';\n input.spellcheck = false;\n container.appendChild(input);\n var errorEl = document.createElement('div');\n errorEl.className = 'bjs-popup-error-message';\n errorEl.setAttribute('role', 'alert');\n errorEl.style.display = 'none';\n container.appendChild(errorEl);\n ctx.getValue = function () {\n return input.value;\n };\n ctx.autoFocus = input;\n ctx.validateSubmit = function () {\n if (typeof validate !== 'function') return true;\n var result = validate(input.value);\n if (result === true || result === undefined) {\n input.classList.remove('bjs-popup-input--error');\n errorEl.style.display = 'none';\n return true;\n }\n input.classList.add('bjs-popup-input--error');\n errorEl.textContent = typeof result === 'string' ? result : 'Invalid value';\n errorEl.style.display = '';\n input.focus();\n return false;\n };\n }\n }).open().then(function (result) {\n return result && result.ok ? result.value : null;\n });\n }\n }]);\n}(); // Make the class accessible to non-module contexts (tests, host apps)\nif (typeof window !== 'undefined') {\n window.BuilderjsPopup = BuilderjsPopup;\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BuilderjsPopup);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BuilderjsPopup.js?");
/***/ }),
/***/ "./src/includes/ButtonElement.js":
/*!***************************************!*\
!*** ./src/includes/ButtonElement.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./LinkConfigControl.js */ \"./src/includes/LinkConfigControl.js\");\n/* harmony import */ var _InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./InnerPaddingControl.js */ \"./src/includes/InnerPaddingControl.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./SegmentedTextControl.js */ \"./src/includes/SegmentedTextControl.js\");\n/* harmony import */ var _StylePickerControl_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./StylePickerControl.js */ \"./src/includes/StylePickerControl.js\");\n/* harmony import */ var _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./IconPickerControl.js */ \"./src/includes/IconPickerControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _overlays_ButtonActionsOverlay_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./overlays/ButtonActionsOverlay.js */ \"./src/includes/overlays/ButtonActionsOverlay.js\");\n/* harmony import */ var _overlays_LinkPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./overlays/LinkPopoverOverlay.js */ \"./src/includes/overlays/LinkPopoverOverlay.js\");\n/* harmony import */ var _overlays_ButtonPresetPickerOverlay_js__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./overlays/ButtonPresetPickerOverlay.js */ \"./src/includes/overlays/ButtonPresetPickerOverlay.js\");\n/* harmony import */ var _overlays_ButtonSettingsPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./overlays/ButtonSettingsPopoverOverlay.js */ \"./src/includes/overlays/ButtonSettingsPopoverOverlay.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\n/* harmony import */ var _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./buttonPresets.js */ \"./src/includes/buttonPresets.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * Formatter keys emitted via `toStyleStringAll(...)` — kept in sync with\n * `Button.template.html`. applyFormatStyles() patches ONLY these on the\n * existing <a> so the click target, contenteditable cursor, and any\n * in-flight navigation state are preserved across format tweaks.\n *\n * 2026-04-19: `box_shadow` joined the list to back the new Shadow scale\n * control (page-only, but emitted via inline style — Outlook safely\n * strips it on render so flat fallback degrades cleanly).\n */\nvar CSS_KEYS = ['font_family', 'font_weight', 'font_size', 'text_color', 'link_color', 'text_align', 'line_height', 'letter_spacing', 'text_direction', 'paragraph_spacing', 'background_color', 'background_image', 'background_position', 'background_size', 'background_repeat', 'padding_top', 'padding_right', 'padding_bottom', 'padding_left', 'border_top_style', 'border_top_width', 'border_top_color', 'border_right_style', 'border_right_width', 'border_right_color', 'border_bottom_style', 'border_bottom_width', 'border_bottom_color', 'border_left_style', 'border_left_width', 'border_left_color', 'border_radius', 'box_shadow', 'width', 'max_width', 'min_width'];\nvar ButtonElement = /*#__PURE__*/function (_BaseElement) {\n function ButtonElement(template, text) {\n var _this;\n var url = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '#';\n _classCallCheck(this, ButtonElement);\n _this = _callSuper(this, ButtonElement);\n _this.template = template;\n _this.text = text;\n // Link semantics — kept as top-level properties (not formatter\n // entries). Target/rel/title/download are attribute-level, not\n // visual styles.\n _this.url = url || '';\n _this.target = '';\n _this.rel = '';\n _this.title = '';\n _this.download = '';\n // W4.3 — a11y override. Set via LinkConfigControl; rendered as\n // `aria-label` on the `<a>` inside the button template.\n _this.ariaLabel = '';\n\n // Style preset identity + orthogonal modifier axes (2026-04-19).\n // Default = `solid-ink` LG centered — replaces the older blue-pill\n // default (#0d6efd, padding 6/12) which user feedback flagged as\n // \"ugly\". Defaults are picked so a fresh widget drag delivers a\n // confident, ready-to-publish button (no first-time tuning needed).\n // Saved data with explicit values overrides defaults via parse().\n _this.preset_id = 'solid-ink';\n _this.size_key = 'lg';\n _this.shadow_key = 'none';\n _this.hover_effect = 'none';\n _this.icon = null;\n _this.icon_position = 'none';\n _this.domNode = null;\n _this.requiredTemplateKeys = ['text'];\n // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n _this.registerInlineEdit('text');\n\n // Defaults below mirror PRESETS['solid-ink'] + SIZE_SCALE.lg so a\n // new ButtonElement boots into the \"solid ink, large\" look even\n // before the picker overlay has a chance to apply the preset\n // (the constructor runs sync, applyPreset needs a mounted DOM).\n // Keep these in sync with buttonPresets.js solid-ink + SIZE_SCALE.lg.\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_19__[\"default\"]({\n align: 'center',\n font_family: \"inherit\",\n font_weight: \"500\",\n font_size: \"16px\",\n text_color: \"#ffffff\",\n link_color: \"#ffffff\",\n paragraph_spacing: null,\n text_align: 'center',\n line_height: \"1.5\",\n letter_spacing: null,\n text_direction: \"ltr\",\n background_color: \"#111827\",\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n padding_top: 12,\n padding_right: 28,\n padding_bottom: 12,\n padding_left: 28,\n border_top_style: \"solid\",\n border_top_width: \"1px\",\n border_top_color: \"#111827\",\n border_right_style: \"solid\",\n border_right_width: \"1px\",\n border_right_color: \"#111827\",\n border_bottom_style: \"solid\",\n border_bottom_width: \"1px\",\n border_bottom_color: \"#111827\",\n border_left_width: \"1px\",\n border_left_style: \"solid\",\n border_left_color: \"#111827\",\n border_radius: \"6px\",\n box_shadow: '',\n width: null,\n max_width: null,\n min_width: null\n });\n return _this;\n }\n _inherits(ButtonElement, _BaseElement);\n return _createClass(ButtonElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.button');\n }\n\n /**\n * Canvas overlays (Phase 1.7 + Style Picker upgrade 2026-04-19):\n * - ButtonActionsOverlay (FloatingActionBarOverlay, trigger 'select')\n * — 3-pill toolbar anchored top-right of the button: \"Edit text\"\n * / \"Link\" / \"Style\" — the Style pill enters 'style-picker'\n * edit mode which mounts ButtonPresetPickerOverlay below.\n * - LinkPopoverOverlay (AnchoredPopoverOverlay, trigger 'edit',\n * mode 'link-popover') — compact URL editor.\n * - ButtonPresetPickerOverlay (AnchoredPopoverOverlay, trigger\n * 'edit', mode 'style-picker') — anchored 9-tab preset picker.\n * Anchor reads from `_lastActionAnchorRect` so it works for both\n * entry points: action-bar palette pill AND sidebar Change btn.\n *\n * See docs/core/OVERLAY.md §7.5 + §7.7 + docs/BUTTON_UPGRADE_PLAN.md.\n */\n }, {\n key: \"getOverlays\",\n value: function getOverlays() {\n var _this2 = this;\n var anchorTo = function anchorTo() {\n return _this2._lastActionAnchorRect || null;\n };\n return [new _overlays_ButtonActionsOverlay_js__WEBPACK_IMPORTED_MODULE_20__[\"default\"](this), new _overlays_LinkPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_21__[\"default\"](this, {\n anchorTo: anchorTo,\n side: 'right',\n width: 380\n }), new _overlays_ButtonSettingsPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_23__[\"default\"](this), new _overlays_ButtonPresetPickerOverlay_js__WEBPACK_IMPORTED_MODULE_22__[\"default\"](this)];\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter + text auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n url: this.url || '#',\n target: this.target,\n rel: this.rel,\n title: this.title,\n download: this.download,\n icon: this.icon,\n iconPosition: this.icon_position,\n hoverEffect: this.hover_effect\n });\n\n // Inline-edit wiring auto-fires from BaseElement.afterRender (W0.2b).\n this.applyButtonExtras();\n }\n\n /**\n * Format-only update (structure-preserving). Patches the <a>'s inline\n * style + outer wrapper text-align in place. No innerHTML swap →\n * contenteditable cursor + DOM identity survive every tweak.\n *\n * Fires `notifySyncListeners()` at the end so sidebar surfaces (Style\n * summary thumb, dual-view link control, future preview tiles) re-read\n * the live formatter state after any color / border / padding tweak\n * — not just preset / size / shadow / hover changes that go through\n * apply*() helpers.\n */\n }, {\n key: \"applyFormatStyles\",\n value: function applyFormatStyles() {\n if (!this.domNode) {\n this.render();\n return;\n }\n var a = this.domNode.querySelector('a');\n var wrapper = this.domNode.firstElementChild;\n if (!a || !wrapper) {\n this.render();\n return;\n }\n wrapper.style.textAlign = this.formatter.getFormat('align', 'center');\n var hasWidth = !!this.formatter.getFormat('width');\n var display = hasWidth ? \"display: block; \".concat(this.formatter.getFormat('align') === 'center' ? 'margin-left: auto; margin-right: auto;' : '') : 'display: inline-block;';\n var styleBase = this.formatter.toStyleStringAll(CSS_KEYS);\n a.setAttribute('style', \"\".concat(styleBase, \" \").concat(display, \" text-decoration: none;\"));\n this.notifySyncListeners();\n }\n\n /**\n * Patches the icon slot + hover-effect data attribute on the existing\n * <a> in place. Called from render() AND from any preset / icon /\n * hover_effect mutation path so the structural extras stay current\n * without a full innerHTML swap (preserves contenteditable caret).\n */\n }, {\n key: \"applyButtonExtras\",\n value: function applyButtonExtras() {\n var _this3 = this;\n if (!this.domNode) return;\n var a = this.domNode.querySelector('a');\n if (!a) return;\n\n // Hover effect attribute — CSS rules in builder.css act on this\n if (this.hover_effect && this.hover_effect !== 'none') {\n a.setAttribute('data-bjs-hover-fx', this.hover_effect);\n } else {\n a.removeAttribute('data-bjs-hover-fx');\n }\n\n // Icon slot patch\n var existingLeft = a.querySelector(':scope > .bjs-btn-icon--left');\n var existingRight = a.querySelector(':scope > .bjs-btn-icon--right');\n var existingOnly = a.querySelector(':scope > .bjs-btn-icon--only');\n var textNode = a.querySelector(':scope > [inline-edit=\"text\"]');\n\n // Wipe any existing icon spans before re-adding (idempotent)\n if (existingLeft) existingLeft.remove();\n if (existingRight) existingRight.remove();\n if (existingOnly) existingOnly.remove();\n var wantsIcon = !!this.icon && this.icon_position && this.icon_position !== 'none';\n if (!wantsIcon) {\n if (textNode) textNode.style.display = '';\n return;\n }\n\n // Inline SVG — theme iframes don't load the Material Symbols font,\n // and exported HTML (especially email) is even less reliable. SVG\n // renders deterministically everywhere. Unknown names fall back to\n // a letter-in-a-circle glyph (InlineIcons.render's built-in\n // fallback) so a typo doesn't produce an empty span.\n //\n // Spacing — apply margin INLINE (not via CSS class) because:\n // 1. The canvas iframe loads the THEME stylesheet, not the\n // builder.css that carries `.bjs-btn-icon--left { margin-* }`.\n // 2. Exported email HTML is stripped of external stylesheets\n // entirely — only inline styles survive.\n // Inline margin is the only approach that renders identically\n // across builder canvas, preview iframe, and exported email.\n var iconSpan = function iconSpan(cls, side) {\n var s = document.createElement('span');\n s.className = \"bjs-btn-icon \".concat(cls);\n s.setAttribute('aria-hidden', 'true');\n s.style.display = 'inline-flex';\n s.style.alignItems = 'center';\n s.style.justifyContent = 'center';\n s.style.verticalAlign = 'middle';\n s.style.lineHeight = '1';\n if (side === 'left') s.style.marginRight = '8px';\n if (side === 'right') s.style.marginLeft = '8px';\n s.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_24__[\"default\"].render(_this3.icon, {\n size: 18,\n color: 'currentColor'\n });\n return s;\n };\n if (this.icon_position === 'only') {\n if (textNode) textNode.style.display = 'none';\n var ic = iconSpan('bjs-btn-icon--only', 'only');\n a.insertBefore(ic, a.firstChild);\n } else if (this.icon_position === 'left') {\n if (textNode) textNode.style.display = '';\n var _ic = iconSpan('bjs-btn-icon--left', 'left');\n a.insertBefore(_ic, a.firstChild);\n } else if (this.icon_position === 'right') {\n if (textNode) textNode.style.display = '';\n var _ic2 = iconSpan('bjs-btn-icon--right', 'right');\n a.appendChild(_ic2);\n }\n }\n\n /**\n * Apply a named preset by id. Mutates formatter (full snapshot\n * overwrite — preset is the new identity), keeps user's current size\n * (preset is a LOOK, size is an axis), then re-runs\n * applyFormatStyles + applyButtonExtras + applySize.\n *\n * Side-effects (in addition to formatter rewrite):\n * - preset_id ← presetId\n * - icon ← preset.icon (preset owns icon identity)\n * - icon_position ← preset.iconPosition\n *\n * Size / shadow / hover_effect persist across preset switches because\n * they're orthogonal modifier axes — switching look shouldn't lose\n * the user's \"I want a large button with a glow\" intent.\n */\n }, {\n key: \"applyPreset\",\n value: function applyPreset(presetId) {\n var preset = (0,_buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.findPreset)(presetId);\n if (!preset) return;\n this.preset_id = presetId;\n this.icon = preset.icon || null;\n this.icon_position = preset.iconPosition || 'none';\n // Overwrite formatter with preset's snapshot (full-overwrite —\n // partial would leak previous preset's color into the new one)\n if (preset.formats && this.formatter) {\n var desiredKeys = Object.keys(preset.formats);\n // Reset any CSS_KEYS the preset doesn't own to their pre-set\n // values from its DEFAULT_MD skeleton — handled because\n // every preset includes the full skeleton. So we just merge:\n for (var _i = 0, _desiredKeys = desiredKeys; _i < _desiredKeys.length; _i++) {\n var k = _desiredKeys[_i];\n if (k in this.formatter.formats) {\n this.formatter.formats[k] = preset.formats[k];\n }\n }\n }\n // Re-apply current size on top of preset\n this._applySizeToFormatter(this.size_key || 'md');\n // Re-apply current shadow override on top of preset (shadow is\n // an axis: user wanted SHADOW=lg → keep it after switching look)\n this._applyShadowToFormatter(this.shadow_key || 'none', preset);\n this.applyFormatStyles();\n this.applyButtonExtras();\n this.notifySyncListeners();\n }\n\n /**\n * Switch size axis. Patches padding + font-size only. Keeps preset\n * identity (color/border/radius/shadow). Idempotent — re-running with\n * same key is a no-op.\n */\n }, {\n key: \"applySize\",\n value: function applySize(sizeKey) {\n if (!_buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SIZE_KEYS.includes(sizeKey)) return;\n this.size_key = sizeKey;\n this._applySizeToFormatter(sizeKey);\n this.applyFormatStyles();\n this.notifySyncListeners();\n }\n }, {\n key: \"_applySizeToFormatter\",\n value: function _applySizeToFormatter(sizeKey) {\n var scale = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SIZE_SCALE[sizeKey];\n if (!scale || !this.formatter) return;\n for (var _i2 = 0, _Object$entries = Object.entries(scale); _i2 < _Object$entries.length; _i2++) {\n var _Object$entries$_i = _slicedToArray(_Object$entries[_i2], 2),\n k = _Object$entries$_i[0],\n v = _Object$entries$_i[1];\n if (k in this.formatter.formats) this.formatter.formats[k] = v;\n }\n }\n\n /**\n * Switch shadow axis. The 'none' value clears box_shadow (so the\n * preset's intrinsic shadow returns); other values OVERRIDE the\n * preset's shadow (user's per-element shadow choice wins).\n */\n }, {\n key: \"applyShadow\",\n value: function applyShadow(shadowKey) {\n if (!_buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SHADOW_KEYS.includes(shadowKey)) return;\n this.shadow_key = shadowKey;\n var preset = (0,_buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.findPreset)(this.preset_id);\n this._applyShadowToFormatter(shadowKey, preset);\n this.applyFormatStyles();\n this.notifySyncListeners();\n }\n }, {\n key: \"_applyShadowToFormatter\",\n value: function _applyShadowToFormatter(shadowKey) {\n var preset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n if (!this.formatter) return;\n if (shadowKey === 'none') {\n // Restore preset's intrinsic shadow (or empty)\n var intrinsic = preset && preset.formats && preset.formats.box_shadow || '';\n this.formatter.formats.box_shadow = intrinsic;\n } else {\n this.formatter.formats.box_shadow = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SHADOW_SCALE[shadowKey] || '';\n }\n }\n\n /**\n * Switch hover-effect axis. Hover effect lives as a data attribute\n * (`data-bjs-hover-fx`) — actual :hover CSS rules in builder.css\n * key off it. No formatter mutation needed.\n */\n }, {\n key: \"applyHoverEffect\",\n value: function applyHoverEffect(key) {\n if (!_buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.HOVER_EFFECT_KEYS.includes(key)) return;\n this.hover_effect = key;\n this.applyButtonExtras();\n this.notifySyncListeners();\n }\n\n /**\n * Set or clear the icon. `name` null = remove icon (also resets\n * icon_position to 'none'). `position` ignored when name null.\n */\n }, {\n key: \"applyIcon\",\n value: function applyIcon(name) {\n var position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'left';\n if (!name) {\n this.icon = null;\n this.icon_position = 'none';\n } else {\n this.icon = name;\n this.icon_position = ['left', 'right', 'only', 'none'].includes(position) ? position : 'left';\n }\n this.applyButtonExtras();\n this.notifySyncListeners();\n }\n }, {\n key: \"applyIconPosition\",\n value: function applyIconPosition(position) {\n if (!['left', 'right', 'only', 'none'].includes(position)) return;\n this.icon_position = position;\n this.applyButtonExtras();\n this.notifySyncListeners();\n }\n\n /**\n * Width axis — auto / 50% / full. Translates to formatter.width.\n */\n }, {\n key: \"applyWidth\",\n value: function applyWidth(key) {\n if (!this.formatter) return;\n if (key === 'auto') this.formatter.formats.width = null;else if (key === 'half') this.formatter.formats.width = '50%';else if (key === 'full') this.formatter.formats.width = '100%';\n this.applyFormatStyles();\n this.notifySyncListeners();\n }\n }, {\n key: \"_currentWidthKey\",\n value: function _currentWidthKey() {\n var w = this.formatter && this.formatter.getFormat('width');\n if (!w) return 'auto';\n if (String(w).trim() === '50%') return 'half';\n if (String(w).trim() === '100%') return 'full';\n return 'auto';\n }\n\n /**\n * Radius axis — sharp / sm / md / lg / pill. Maps to border_radius.\n */\n }, {\n key: \"applyRadiusKey\",\n value: function applyRadiusKey(key) {\n if (!this.formatter) return;\n var map = {\n sharp: '0px',\n sm: '4px',\n md: '8px',\n lg: '16px',\n pill: '999px'\n };\n if (!(key in map)) return;\n this.formatter.formats.border_radius = map[key];\n this.applyFormatStyles();\n this.notifySyncListeners();\n }\n }, {\n key: \"_currentRadiusKey\",\n value: function _currentRadiusKey() {\n var r = String(this.formatter && this.formatter.getFormat('border_radius') || '').trim();\n if (r === '0px' || r === '0') return 'sharp';\n if (r === '4px') return 'sm';\n if (r === '8px') return 'md';\n if (r === '16px') return 'lg';\n if (r === '999px' || r === '9999px') return 'pill';\n return null; // custom — none of the chips active, slider in Advanced shows current\n }\n\n /**\n * Link-attrs update (also structure-preserving). Updates href/target/\n * rel/title/download on the existing <a> — does NOT touch style.\n */\n }, {\n key: \"applyLinkAttrs\",\n value: function applyLinkAttrs() {\n if (!this.domNode) {\n this.render();\n return;\n }\n var a = this.domNode.querySelector('a');\n if (!a) {\n this.render();\n return;\n }\n a.setAttribute('href', this.url || '#');\n if (this.target) a.setAttribute('target', this.target);else a.removeAttribute('target');\n if (this.rel) a.setAttribute('rel', this.rel);else a.removeAttribute('rel');\n if (this.title) a.setAttribute('title', this.title);else a.removeAttribute('title');\n if (this.download) a.setAttribute('download', this.download);else a.removeAttribute('download');\n if (this.ariaLabel) a.setAttribute('aria-label', this.ariaLabel);else a.removeAttribute('aria-label');\n this.notifySyncListeners();\n }\n\n /**\n * LinkConfigControl factory — see Phase 1.7 / Lesson 39.\n */\n }, {\n key: \"buildLinkControl\",\n value: function buildLinkControl() {\n var _this4 = this;\n return new _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link'), {\n url: this.url,\n target: this.target,\n rel: this.rel,\n title: this.title,\n download: this.download,\n ariaLabel: this.ariaLabel\n }, {\n setLink: function setLink(_ref) {\n var url = _ref.url,\n target = _ref.target,\n rel = _ref.rel,\n title = _ref.title,\n download = _ref.download,\n ariaLabel = _ref.ariaLabel;\n _this4.url = url || '';\n _this4.target = target || '';\n _this4.rel = rel || '';\n _this4.title = title || '';\n _this4.download = download || '';\n _this4.ariaLabel = ariaLabel || '';\n _this4.applyLinkAttrs();\n }\n }, {\n subscribe: function subscribe(fn) {\n return _this4.addSyncListener('LinkConfigControl:' + Math.random().toString(36).slice(2, 7), fn);\n },\n readState: function readState() {\n return {\n url: _this4.url,\n target: _this4.target,\n rel: _this4.rel,\n title: _this4.title,\n download: _this4.download,\n ariaLabel: _this4.ariaLabel\n };\n }\n });\n }\n\n /**\n * IconPicker factory — shared by sidebar + ButtonSettingsPopoverOverlay.\n * Wires a sync listener so programmatic icon changes (preset apply,\n * popover mutation) visibly update every live instance without each\n * call-site having to renderElementControls from scratch.\n */\n }, {\n key: \"_buildIconPicker\",\n value: function _buildIconPicker() {\n var _this5 = this;\n var picker = new _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_18__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon.label', 'Icon'), this.icon || '', {\n setValue: function setValue(name) {\n return _this5.applyIcon(name || null, _this5.icon_position && _this5.icon_position !== 'none' ? _this5.icon_position : 'left');\n }\n });\n // Silent sync — only patches the trigger glyph + label; does not\n // re-invoke the callback (which would loop back into applyIcon).\n var dispose = this.addSyncListener('ButtonIconPicker:' + Math.random().toString(36).slice(2, 7), function () {\n var next = _this5.icon || '';\n if (picker.value !== next) {\n picker.value = next;\n picker.isCustomOpen = picker._detectCustom(next);\n if (typeof picker._refreshTrigger === 'function') picker._refreshTrigger();\n }\n });\n var prevDestroy = typeof picker.destroy === 'function' ? picker.destroy.bind(picker) : null;\n picker.destroy = function () {\n try {\n dispose && dispose();\n } catch (_) {/* no-op */}\n if (prevDestroy) {\n try {\n prevDestroy();\n } catch (_) {/* no-op */}\n }\n };\n return picker;\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(ButtonElement, \"getData\", this, 3)([])), {}, {\n text: this.text,\n url: this.url,\n target: this.target,\n rel: this.rel,\n title: this.title,\n download: this.download,\n ariaLabel: this.ariaLabel,\n preset_id: this.preset_id,\n size_key: this.size_key,\n shadow_key: this.shadow_key,\n hover_effect: this.hover_effect,\n icon: this.icon,\n icon_position: this.icon_position\n });\n }\n }, {\n key: \"getControls\",\n value:\n /**\n * getControls — 2026-04-19 reorganized into 4 sections matching the\n * sidebar showcase + design preview:\n *\n * STYLE SETTINGS → StylePickerControl (compound) + Size + Radius\n * EFFECTS → Shadow + HoverEffect (page-only — banner badge)\n * ICON → IconPicker + IconPosition\n * LAYOUT → Width\n * ADVANCED → text / link / colors / border / padding / font /\n * spacing — every legacy power-user knob lives here\n *\n * SectionLabelControl renders divider rows between groups.\n */\n function getControls() {\n var _this6 = this,\n _this$host;\n var setFmt = function setFmt(key) {\n return function (value) {\n _this6.formatter.setFormat(key, value);\n _this6.applyFormatStyles();\n };\n };\n // W3.1 — bus wiring for dual-view sync with FontPopoverOverlay.\n var busOpts = function busOpts(key) {\n var _this6$host;\n return {\n bus: (_this6$host = _this6.host) === null || _this6$host === void 0 ? void 0 : _this6$host.events,\n elementUid: _this6.id,\n formatterKey: key\n };\n };\n var sizeOpts = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SIZE_KEYS.map(function (k) {\n return {\n value: k,\n label: k.toUpperCase(),\n tooltip: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.size.' + k, k.toUpperCase())\n };\n });\n var shadowOpts = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SHADOW_KEYS.map(function (k) {\n return {\n value: k,\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.shadow.' + k, k === 'inner' ? 'Inner' : k.toUpperCase())\n };\n });\n var hoverOpts = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.HOVER_EFFECT_KEYS.map(function (k) {\n return {\n value: k,\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.hover.' + k, k.charAt(0).toUpperCase() + k.slice(1))\n };\n });\n var radiusOpts = [{\n value: 'sharp',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.sharp', 'Sharp')\n }, {\n value: 'sm',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.sm', 'SM')\n }, {\n value: 'md',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.md', 'MD')\n }, {\n value: 'lg',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.lg', 'LG')\n }, {\n value: 'pill',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.pill', 'Pill')\n }];\n var iconPosOpts = [{\n value: 'left',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon_pos.left', 'Left')\n }, {\n value: 'right',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon_pos.right', 'Right')\n }, {\n value: 'only',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon_pos.only', 'Only')\n }, {\n value: 'none',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon_pos.none', 'None')\n }];\n var widthOpts = [{\n value: 'auto',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.width.auto', 'Auto')\n }, {\n value: 'half',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.width.half', '50%')\n }, {\n value: 'full',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.width.full', 'Full')\n }];\n var controls = [\n // ═══ STYLE SETTINGS ═══\n new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.style', 'Style Settings'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.style_desc', 'Preset look, size, shape & modifiers.')), new _StylePickerControl_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"](this), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.size.label', 'Size'), this.size_key || 'md', function (v) {\n return _this6.applySize(v);\n }, sizeOpts, {\n element: this,\n readValue: function readValue() {\n return _this6.size_key || 'md';\n }\n }), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.label', 'Radius'), this._currentRadiusKey() || 'md', function (v) {\n return _this6.applyRadiusKey(v);\n }, radiusOpts, {\n element: this,\n readValue: function readValue() {\n return _this6._currentRadiusKey() || 'md';\n }\n }),\n // ═══ EFFECTS (page-only) ═══\n new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.effects', 'Effects'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.effects_desc', 'Depth and micro-interactions. Page mode only.')), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.shadow.label', 'Shadow'), this.shadow_key || 'none', function (v) {\n return _this6.applyShadow(v);\n }, shadowOpts, {\n element: this,\n readValue: function readValue() {\n return _this6.shadow_key || 'none';\n }\n }), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.hover.label', 'Hover effect'), this.hover_effect || 'none', function (v) {\n return _this6.applyHoverEffect(v);\n }, hoverOpts, {\n element: this,\n readValue: function readValue() {\n return _this6.hover_effect || 'none';\n }\n }),\n // ═══ ICON ═══\n new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.icon', 'Icon'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.icon_desc', 'Optional pictogram beside, before, or instead of the label.')), this._buildIconPicker(), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon_pos.label', 'Position'), this.icon_position || 'none', function (v) {\n return _this6.applyIconPosition(v);\n }, iconPosOpts, {\n element: this,\n readValue: function readValue() {\n return _this6.icon_position || 'none';\n }\n }),\n // ═══ LAYOUT ═══\n new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.layout', 'Layout'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.layout_desc', 'Width within the block row.')), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.width.label', 'Width'), this._currentWidthKey(), function (v) {\n return _this6.applyWidth(v);\n }, widthOpts, {\n element: this,\n readValue: function readValue() {\n return _this6._currentWidthKey();\n }\n }),\n // ═══ ADVANCED — every legacy power-user control ═══\n new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.advanced', 'Advanced'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.advanced_desc', 'Color, border, padding, font, spacing overrides.')),\n // Text — inline-edit on canvas is the primary path; this control\n // is a panel-side fallback. Text change = content mutation,\n // patch <a> innerHTML directly to preserve identity.\n new _TextControl_js__WEBPACK_IMPORTED_MODULE_14__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text'), this.text, {\n setText: function setText(text) {\n _this6.text = text;\n var a = _this6.domNode && _this6.domNode.querySelector('a');\n var tn = a && a.querySelector('[inline-edit=\"text\"]');\n if (tn) tn.innerHTML = text;else _this6.render();\n }\n }), this.buildLinkControl(), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('align'), {\n setValue: setFmt('align')\n }, ['left', 'center', 'right']), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n setValue: setFmt('font_family')\n }, busOpts('font_family')), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n setValue: setFmt('font_weight')\n }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n setValue: setFmt('font_size')\n }, _objectSpread({\n defaultValue: 16,\n minValue: 8,\n maxValue: 72,\n suffix: 'px',\n allowZero: false\n }, busOpts('font_size'))), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n setValue: setFmt('text_color')\n }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n setValue: setFmt('link_color')\n }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_alignment'), this.formatter.getFormat('text_align'), {\n setValue: setFmt('text_align')\n }, ['left', 'justify', 'center', 'right'], {\n bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n elementUid: this.id,\n formatterKey: 'text_align'\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n setValue: setFmt('paragraph_spacing')\n }, {\n defaultValue: 0,\n minValue: 0,\n maxValue: 50,\n suffix: 'px',\n allowZero: true\n }), new _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n setValue: setFmt('line_height')\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n setValue: setFmt('letter_spacing')\n }, {\n defaultValue: 0,\n minValue: -5,\n maxValue: 10,\n step: 0.1,\n suffix: 'px',\n allowZero: true,\n allowNegative: true\n }), new _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n setValue: setFmt('text_direction')\n }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n color: this.formatter.getFormat('background_color'),\n image: this.formatter.getFormat('background_image'),\n position: this.formatter.getFormat('background_position'),\n size: this.formatter.getFormat('background_size'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n }, {\n setBackground: function setBackground(values) {\n _this6.formatter.setFormat('background_color', values.color);\n _this6.formatter.setFormat('background_image', values.image);\n _this6.formatter.setFormat('background_position', values.position);\n _this6.formatter.setFormat('background_size', values.size);\n _this6.formatter.setFormat('background_repeat', values.repeat);\n _this6.applyFormatStyles();\n }\n }, {\n features: ['color', 'image', 'size', 'repeat', 'gradient']\n }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style'),\n border_top_width: this.formatter.getFormat('border_top_width'),\n border_top_color: this.formatter.getFormat('border_top_color'),\n border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n border_left_style: this.formatter.getFormat('border_left_style'),\n border_left_width: this.formatter.getFormat('border_left_width'),\n border_left_color: this.formatter.getFormat('border_left_color'),\n border_right_style: this.formatter.getFormat('border_right_style'),\n border_right_width: this.formatter.getFormat('border_right_width'),\n border_right_color: this.formatter.getFormat('border_right_color')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this6.formatter.setFormat('border_top_style', border_top_style);\n _this6.formatter.setFormat('border_top_width', border_top_width);\n _this6.formatter.setFormat('border_top_color', border_top_color);\n _this6.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this6.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this6.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this6.formatter.setFormat('border_left_style', border_left_style);\n _this6.formatter.setFormat('border_left_width', border_left_width);\n _this6.formatter.setFormat('border_left_color', border_left_color);\n _this6.formatter.setFormat('border_right_style', border_right_style);\n _this6.formatter.setFormat('border_right_width', border_right_width);\n _this6.formatter.setFormat('border_right_color', border_right_color);\n _this6.applyFormatStyles();\n }\n }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n setRadius: function setRadius(v) {\n _this6.formatter.setFormat('border_radius', v);\n _this6.applyFormatStyles();\n }\n }), new _InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.button_padding'), {\n top: this.formatter.getFormat('padding_top'),\n right: this.formatter.getFormat('padding_right'),\n bottom: this.formatter.getFormat('padding_bottom'),\n left: this.formatter.getFormat('padding_left')\n }, {\n setValues: function setValues(values) {\n _this6.formatter.setFormat('padding_top', values.top);\n _this6.formatter.setFormat('padding_right', values.right);\n _this6.formatter.setFormat('padding_bottom', values.bottom);\n _this6.formatter.setFormat('padding_left', values.left);\n _this6.applyFormatStyles();\n }\n })];\n return controls;\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var e = new ButtonElement(data.template, data.text, data.url);\n e.target = data.target || '';\n e.rel = data.rel || '';\n e.title = data.title || '';\n e.download = data.download || '';\n e.ariaLabel = data.ariaLabel || '';\n // New optional fields — back-compat: missing keys leave defaults\n if ('preset_id' in data) e.preset_id = data.preset_id || null;\n if ('size_key' in data) e.size_key = data.size_key || 'md';\n if ('shadow_key' in data) e.shadow_key = data.shadow_key || 'none';\n if ('hover_effect' in data) e.hover_effect = data.hover_effect || 'none';\n if ('icon' in data) e.icon = data.icon || null;\n if ('icon_position' in data) e.icon_position = data.icon_position || 'none';\n return this.parseFormats(e, data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ButtonElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ButtonElement.js?");
/***/ }),
/***/ "./src/includes/ButtonWidget.js":
/*!**************************************!*\
!*** ./src/includes/ButtonWidget.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ButtonElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ButtonElement.js */ \"./src/includes/ButtonElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar ButtonWidget = /*#__PURE__*/function (_BaseWidget) {\n function ButtonWidget() {\n var _this;\n _classCallCheck(this, ButtonWidget);\n _this = _callSuper(this, ButtonWidget); // Call the parent class constructor\n\n // Add a ButtonElement to the widget\n var button = new _ButtonElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Button', 'Click Me');\n\n // Append the new element to the block\n _this.block.appendElements([button]);\n return _this;\n }\n _inherits(ButtonWidget, _BaseWidget);\n return _createClass(ButtonWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.button');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'smart_button';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ButtonWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ButtonWidget.js?");
/***/ }),
/***/ "./src/includes/CellElement.js":
/*!*************************************!*\
!*** ./src/includes/CellElement.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _DimensionControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./DimensionControl.js */ \"./src/includes/DimensionControl.js\");\n/* harmony import */ var _DropdownControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./DropdownControl.js */ \"./src/includes/DropdownControl.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./overlays/PaddingVisualizerOverlay.js */ \"./src/includes/overlays/PaddingVisualizerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar CellElement = /*#__PURE__*/function (_BaseElement) {\n function CellElement(template) {\n var _this;\n _classCallCheck(this, CellElement);\n _this = _callSuper(this, CellElement);\n _this.template = template;\n _this.blocks = [];\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = [\"blocks\"];\n _this.Auto = {\n heightAuto: false,\n widthAuto: false\n };\n\n // Formatter\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"]({\n width: \"auto\",\n // display and flex\n display: null,\n flex_direction: null,\n flex: null,\n gap: null,\n // background\n background_color: null,\n background_image: null,\n background_position: null,\n background_size: null,\n background_repeat: null,\n background_blend_mode: null,\n opacity: null,\n filter: null,\n // border\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_style: null,\n border_left_width: null,\n border_left_color: null,\n // border radius\n border_radius: null,\n // box shadow\n box_shadow: null,\n // padding\n padding_top: null,\n padding_right: null,\n padding_bottom: null,\n padding_left: null,\n // margin\n margin_top: null,\n margin_right: null,\n margin_bottom: null,\n margin_left: null,\n // size\n height: null,\n max_width: null,\n max_height: null,\n min_width: null,\n min_height: null,\n // additional layout properties\n justify_content: null,\n align_items: null\n });\n return _this;\n }\n _inherits(CellElement, _BaseElement);\n return _createClass(CellElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.cell');\n }\n\n // 2026-04-19 — Cell is hoverable + selectable on canvas. Click on the\n // cell's padding (anywhere NOT inside an inner block) selects the cell;\n // top-element rule still gives inner blocks priority for clicks on\n // their own DOM. See docs/core/OVERLAY.md §7.3 (updated). Same precedent as\n // PricingCardElement.isHoverable() — selecting the container is a\n // first-class user intent now that Grid resize/insert affordances live\n // in the cell-selection overlay set.\n }, {\n key: \"isHoverable\",\n value: function isHoverable() {\n return true;\n }\n }, {\n key: \"isDroppable\",\n value: function isDroppable() {\n return true;\n }\n\n // Cell composes its parent Grid's overlays into its own overlay set —\n // same pattern as getControls() concat(this.container.getControls()).\n // When the user selects a cell on canvas, the Grid's GridStructureOverlay\n // + GridColumnResizeOverlay × (n-1) + GridInsertColumnOverlay × (n+1)\n // all mount, giving full grid editing affordances without forcing the\n // user to navigate up to the Grid via breadcrumb. Cell itself contributes\n // no overlays of its own (today) — composition delegates entirely.\n // Defensive: container may not yet exist for orphaned cells in widget-\n // construction code paths.\n }, {\n key: \"getOverlays\",\n value: function getOverlays() {\n var overlays = [];\n\n // PLAN_EFFECT W3.5 — padding visualiser (trigger 'select'). Always\n // emit; the overlay self-disposes in afterMount() when host's\n // usePaddingVisualizer flag is off. Why: getOverlays() runs during\n // parse — `this.host` is null then, so a flag check here would\n // always skip. The flag gate moved to PaddingVisualizerOverlay\n // (commit 4 + 6 of host-injection refactor).\n overlays.push(new _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](this));\n if (this.container && typeof this.container.getOverlays === 'function') {\n overlays.push.apply(overlays, _toConsumableArray(this.container.getOverlays()));\n }\n return overlays;\n }\n\n /** Host-injection recursion hook — returns this cell's blocks so\n * Builder._adopt() can walk down the tree. See BUILDER.md \"Host\n * Injection\" lesson. */\n }, {\n key: \"getChildren\",\n value: function getChildren() {\n return this.blocks || [];\n }\n\n /**\n * In-place style patch — fast path that avoids Cell.render().\n *\n * Cell.render() is heavier than Block.render() — it clears child DOMs\n * and re-appends them, which causes any block-level overlay's\n * ResizeObserver to see a transient size-0 tick as blocks are\n * disconnected then re-attached. Keystroke-rate padding changes\n * AND drag-rate column resize both trigger applyFormatStyles many\n * times per second; render() each tick produces visible flicker on\n * the CHILD overlays (NO-FLICKER, SA I9).\n *\n * Patches the inline `style` attribute in place by stripping the\n * declarations this method owns (padding-*, flex) and re-emitting\n * fresh ones from the formatter. Everything else in the style string\n * — height, background, border, etc. — is left untouched.\n *\n * **CONTRACT:** must cover EVERY declaration the Cell template emits\n * from formatter values that callers mutate at hot-path rates. Today\n * that's padding (PaddingMarginControl stepper) + flex (driven by\n * `width`, mutated by GridColumnResizeOverlay drag). Adding more\n * hot-path mutations means extending this method — partial coverage\n * is a silent-failure trap (the formatter changes but the DOM doesn't\n * update because the fallback `render()` branch in callers never runs\n * once `applyFormatStyles` exists).\n *\n * Width / flex math MUST stay in sync with Cell.template.html — both\n * read the same `formatter.width` shape (auto / fill / \"N%\" / \"Npx\"\n * / bare number). The shared helper is `_computeFlexStyle()` below.\n *\n * Falls back to render() when domNode is absent (orphaned cell or\n * pre-initial-render call).\n */\n }, {\n key: \"applyFormatStyles\",\n value: function applyFormatStyles() {\n if (!this.domNode) {\n this.render();\n return;\n }\n\n // Strip padding-* AND flex declarations. We rebuild both from\n // formatter state below. min-width is left untouched: the template\n // emits `min-width: 0` next to flex (always 0, value-agnostic), and\n // user-set min_width via toStyleStringAll comes later in the string\n // and would be lost if we stripped it. The fresh `flex: ...; min-\n // width: 0;` we re-emit is harmless when concatenated after an\n // existing `min-width: 0` (same value, no cascade conflict).\n var stripped = (this.domNode.getAttribute('style') || '').replace(/(?:^|;)\\s*padding(?:-top|-right|-bottom|-left)?\\s*:[^;]*;?/gi, ';').replace(/(?:^|;)\\s*flex\\s*:[^;]*;?/gi, ';').replace(/;{2,}/g, ';').replace(/^[;\\s]+|[;\\s]+$/g, '').trim();\n var f = this.formatter;\n var padRules = ['top', 'right', 'bottom', 'left'].map(function (side) {\n var v = f.getFormat(\"padding_\".concat(side));\n if (v === null || v === undefined || v === '') return '';\n var val = typeof v === 'number' || /^-?\\d+(\\.\\d+)?$/.test(String(v)) ? \"\".concat(v, \"px\") : v;\n return \"padding-\".concat(side, \": \").concat(val, \";\");\n }).filter(Boolean).join(' ');\n var flexRule = this._computeFlexStyle();\n var parts = [stripped, flexRule, padRules].filter(Boolean);\n this.domNode.setAttribute('style', parts.join('; ').trim());\n }\n\n /**\n * Compute the `flex: ...; min-width: 0;` declaration (or empty string\n * for content-sized cells) from the formatter's `width` value.\n *\n * **MUST stay in sync with Cell.template.html width branch.** Both\n * code paths consume the same `formatter.width` shape — auto / fill /\n * \"N%\" / \"Npx|em|rem|vw|vh|ch|ex\" / bare number. Any change to one\n * MUST be mirrored in the other. The template runs at full-render\n * time; this helper runs at applyFormatStyles fast-path time. Two\n * call sites, one truth.\n */\n }, {\n key: \"_computeFlexStyle\",\n value: function _computeFlexStyle() {\n var width = this.formatter.getFormat('width', 'auto');\n if (width === 'auto' || width === null || width === undefined || width === '') {\n return '';\n }\n if (width === 'fill') {\n return 'flex: 1 1 0; min-width: 0;';\n }\n var str = String(width).trim();\n if (/%$/.test(str)) {\n var pct = parseFloat(str);\n if (!isNaN(pct) && pct > 0) {\n var gap = this.container && typeof this.container.cell_gap === 'number' ? this.container.cell_gap : 0;\n var count = this.container && Array.isArray(this.container.cells) ? this.container.cells.length : 1;\n if (gap > 0 && count > 1) {\n var gapShare = gap * (count - 1) / count;\n return \"flex: 0 0 calc(\".concat(pct, \"% - \").concat(gapShare, \"px); min-width: 0;\");\n }\n return \"flex: 0 0 \".concat(pct, \"%; min-width: 0;\");\n }\n return 'flex: 1 1 0; min-width: 0;';\n }\n if (/(px|em|rem|vw|vh|ch|ex)$/i.test(str)) {\n return \"flex: 0 0 \".concat(str, \"; min-width: 0;\");\n }\n var numWidth = parseFloat(str);\n if (!isNaN(numWidth) && numWidth > 0) {\n return \"flex: \".concat(numWidth, \" 1 0; min-width: 0;\");\n }\n return 'flex: 1 1 0; min-width: 0;';\n }\n }, {\n key: \"canDropInside\",\n value: function canDropInside() {\n // ─────────────────────────────────────────────────────────────────\n // RULE: drop-inside is allowed on a CellElement ONLY when it's empty.\n // ─────────────────────────────────────────────────────────────────\n //\n // Same rule as PageElement.canDropInside() — see that method for the\n // full rationale. Short version:\n //\n // • Empty cell → drop-inside is allowed (whole cell highlights, the\n // block becomes the first child of the cell).\n // • Non-empty cell → drop-inside is DISABLED. The user must hover an\n // existing block inside the cell and drop above/below\n // it. This makes the landing position unambiguous and\n // prevents the \"whole cell lights up but the block\n // silently lands at the bottom\" UX bug.\n //\n // Cells are special because they live inside a GridElement and the user\n // already has a hard time telling cells apart from the grid. A\n // misleading highlight here is even worse than on the page. The rule\n // must stay symmetrical with PageElement so the two containers behave\n // identically from the user's point of view.\n //\n // Regression tests: e2e/drop-inside-empty-only.spec.js\n return this.blocks.length === 0;\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n var _this2 = this;\n // reset domNode\n while (this.domNode.firstChild) {\n this.domNode.removeChild(this.domNode.firstChild);\n }\n\n // Thread parent-grid context into the template so the percent-width branch can\n // subtract the proportional share of `gap` from each cell's `flex-basis`. Without\n // this, two 50%-cells inside a Grid with `cell_gap: 20` overflow the canvas by\n // 20px (2×50% + 20px > 100%). With it, flex-basis becomes `calc(50% - 10px)`\n // so the cells share the gap evenly and the total lands at exactly 100%.\n var parentGap = this.container && typeof this.container.cell_gap === \"number\" ? this.container.cell_gap : 0;\n var parentCellCount = this.container && Array.isArray(this.container.cells) ? this.container.cells.length : 1;\n\n // 2026-04-18 refactor — drop the block-anchor text-placeholder pattern\n // for the same reason as GridElement: a failed-replacement leaves the\n // raw block ID (\"_xxxxxxxxx\") visible on canvas. Render the cell\n // wrapper EMPTY, then DOM-append each block's domNode directly.\n // formatter auto-merged (W0.2c)\n var html = this.renderTemplate({\n blocks: [],\n vertical_align: this.vertical_align,\n cell_gap: parentGap,\n cell_count: parentCellCount\n });\n var temp = document.createElement(\"div\");\n temp.innerHTML = html;\n var parsedDiv = temp.firstElementChild;\n var _iterator = _createForOfIteratorHelper(parsedDiv.attributes),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var attr = _step.value;\n this.domNode.setAttribute(attr.name, attr.value);\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n this.domNode.innerHTML = parsedDiv.innerHTML;\n this.blocks.forEach(function (block) {\n var blockDom = block.render();\n _this2.domNode.appendChild(blockDom);\n _this2.host.uiManager.addElement(block);\n });\n\n // empty cell — delegate visual to renderEmptyPlaceholder() so subclasses\n // (e.g. FormContainerCell) can override the placeholder without copying\n // the whole _doRender() method.\n if (this.blocks.length == 0) {\n this.domNode.innerHTML = this.renderEmptyPlaceholder();\n }\n }\n\n // Override point for subclasses. Default = \"empty gallery\" SVG icon on\n // a subtle dashed background — signals \"drop blocks here\" in generic\n // cells. Subclasses that want a domain-specific empty state (form,\n // pricing, etc.) override this to change only the visual.\n }, {\n key: \"renderEmptyPlaceholder\",\n value: function renderEmptyPlaceholder() {\n return \"\\n <div style=\\\"display: flex;\\n align-items: center;\\n justify-content: center;\\n height: 100%;\\n min-height: 100px;\\n background-color: rgba(34,83,159,0.05);\\n border: dashed 1px rgba(120, 130, 150, 0.5);\\n \\\">\\n <svg style=\\\"width: 100px;\\n display: inline-block;\\n margin: auto;\\n opacity: 1;\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"48px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"48px\\\" fill=\\\"#808080\\\"><path d=\\\"M345-285q-24 0-42-18t-18-42v-435q0-24 18-42t42-18h435q24 0 42 18t18 42v435q0 24-18 42t-42 18H345Zm0-60h435v-435H345v435ZM149.82-615q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Z\\\"/></svg>\\n\\n </div>\\n \";\n }\n }, {\n key: \"appendBlock\",\n value: function appendBlock(block) {\n // private\n // set container\n block.container = this;\n\n // Host injection — adopt before insert. No-op when this cell isn't\n // yet adopted; the outer `_adopt` walk reaches it via getChildren().\n if (this.host && typeof this.host._adopt === 'function') {\n this.host._adopt(block);\n }\n this.blocks.push(block);\n // Surgical DOM mount when this cell is live. Parse-path callers\n // (CellElement.parse + parent's parse cascade) run BEFORE the\n // owning Page renders, so domNode is null → no-op. The full\n // _doRender path mounts everything after parse.\n this._mountChildBlockDom(block, {\n append: true\n });\n }\n }, {\n key: \"addBlockAfter\",\n value: function addBlockAfter(newBlock, referenceBlock) {\n // set container\n newBlock.container = this;\n var index = this.blocks.indexOf(referenceBlock);\n if (index === -1) {\n throw new Error(\"Reference block not found\");\n }\n this.blocks.splice(index + 1, 0, newBlock);\n this._mountChildBlockDom(newBlock, {\n afterDomNode: referenceBlock.domNode\n });\n }\n }, {\n key: \"addBlockBefore\",\n value: function addBlockBefore(newBlock, referenceBlock) {\n // set container\n newBlock.container = this;\n var index = this.blocks.indexOf(referenceBlock);\n if (index === -1) {\n throw new Error(\"Reference block not found\");\n }\n this.blocks.splice(index, 0, newBlock);\n this._mountChildBlockDom(newBlock, {\n beforeDomNode: referenceBlock.domNode\n });\n }\n\n /**\n * Surgical mount + empty-placeholder swap. Same contract as\n * PageElement._mountBlockDom but scoped to the Cell's child wrapper.\n * Pre-fix the host called `cell.render()` after every add/remove,\n * which churned every sibling block; see BlockElement.removeElement\n * + PageElement.removeElement notes for the cascade-bug rationale.\n */\n }, {\n key: \"_mountChildBlockDom\",\n value: function _mountChildBlockDom(block, position) {\n if (!this.domNode) return;\n // Strip any inline empty-state placeholder before the first real\n // mount. The placeholder lives directly inside `this.domNode`.\n if (this.blocks.length === 1) {\n this.domNode.innerHTML = \"\"; // wipe placeholder\n }\n var rendered = block.render();\n if (position && position.afterDomNode && position.afterDomNode.parentNode === this.domNode) {\n this.domNode.insertBefore(rendered, position.afterDomNode.nextSibling);\n } else if (position && position.beforeDomNode && position.beforeDomNode.parentNode === this.domNode) {\n this.domNode.insertBefore(rendered, position.beforeDomNode);\n } else {\n this.domNode.appendChild(rendered);\n }\n if (this.host && this.host.uiManager) {\n this.host.uiManager.addElement(block);\n }\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(CellElement, \"getData\", this, 3)([])), {}, {\n blocks: this.blocks.map(function (block) {\n return block.getData();\n }),\n vertical_align: this.vertical_align\n });\n }\n }, {\n key: \"removeElement\",\n value: function removeElement(element) {\n var idx = this.blocks.indexOf(element);\n if (idx === -1) return;\n this.blocks.splice(idx, 1);\n if (element.domNode && element.domNode.parentNode) {\n element.domNode.remove();\n }\n\n // Empty-state — drop the inline placeholder. Reuses the same\n // markup that _doRender emits when blocks.length === 0.\n if (this.blocks.length === 0 && this.domNode) {\n this.domNode.innerHTML = this.renderEmptyPlaceholder();\n }\n }\n }, {\n key: \"isAutoFormat\",\n value: function isAutoFormat(key) {\n var value = this.formatter.getFormat(key);\n return value === null || value === undefined || value === '' || value === 'auto';\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this3 = this;\n var cellControls = [\n // BackgroundControl renders its own CELL BACKGROUND header — no\n // extra SectionLabelControl needed here (would duplicate).\n new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_background'), {\n color: this.formatter.getFormat('background_color', '#ffffff'),\n image: this.formatter.getFormat('background_image', ''),\n position: this.formatter.getFormat('background_position', 'center'),\n size: this.formatter.getFormat('background_size', '100'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat'),\n blendMode: this.formatter.getFormat('background_blend_mode', 'normal'),\n opacity: Math.round((parseFloat(this.formatter.getFormat('opacity', 1)) || 1) * 100),\n filter: this.formatter.getFormat('filter', '')\n }, {\n setBackground: function setBackground(values) {\n _this3.formatter.setFormat('background_color', values.color);\n _this3.formatter.setFormat('background_image', values.image);\n _this3.formatter.setFormat('background_position', values.position);\n _this3.formatter.setFormat('background_size', values.size);\n _this3.formatter.setFormat('background_repeat', values.repeat);\n _this3.formatter.setFormat('background_blend_mode', values.blendMode === 'normal' ? null : values.blendMode);\n _this3.formatter.setFormat('opacity', values.opacity === 1 ? null : values.opacity);\n _this3.formatter.setFormat('filter', values.filter || null);\n _this3.render();\n }\n }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_border'), {\n border_top_style: this.formatter.getFormat('border_top_style'),\n border_top_width: this.formatter.getFormat('border_top_width'),\n border_top_color: this.formatter.getFormat('border_top_color'),\n border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n border_left_style: this.formatter.getFormat('border_left_style'),\n border_left_width: this.formatter.getFormat('border_left_width'),\n border_left_color: this.formatter.getFormat('border_left_color'),\n border_right_style: this.formatter.getFormat('border_right_style'),\n border_right_width: this.formatter.getFormat('border_right_width'),\n border_right_color: this.formatter.getFormat('border_right_color')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this3.formatter.setFormat('border_top_style', border_top_style);\n _this3.formatter.setFormat('border_top_width', border_top_width);\n _this3.formatter.setFormat('border_top_color', border_top_color);\n _this3.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this3.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this3.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this3.formatter.setFormat('border_left_style', border_left_style);\n _this3.formatter.setFormat('border_left_width', border_left_width);\n _this3.formatter.setFormat('border_left_color', border_left_color);\n _this3.formatter.setFormat('border_right_style', border_right_style);\n _this3.formatter.setFormat('border_right_width', border_right_width);\n _this3.formatter.setFormat('border_right_color', border_right_color);\n _this3.render();\n }\n }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_radius'), this.formatter.getFormat('border_radius'), {\n setRadius: function setRadius(value) {\n _this3.formatter.setFormat('border_radius', value);\n _this3.render();\n }\n }), new _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_padding'), {\n top: this.formatter.getFormat('padding_top'),\n right: this.formatter.getFormat('padding_right'),\n bottom: this.formatter.getFormat('padding_bottom'),\n left: this.formatter.getFormat('padding_left')\n }, {\n setValues: function setValues(values) {\n _this3.formatter.setFormat('padding_top', values.top);\n _this3.formatter.setFormat('padding_right', values.right);\n _this3.formatter.setFormat('padding_bottom', values.bottom);\n _this3.formatter.setFormat('padding_left', values.left);\n // PLAN_EFFECT W3.5 — in-place patch; keeps child block\n // overlays anchored without the render() strip+re-append\n // cycle that caused flicker.\n _this3.applyFormatStyles();\n }\n },\n // Host-injection — PaddingMarginControl reads bus + pinSet\n // directly off `this.host` set by Builder.renderElementControls.\n // No prop-drilling needed.\n {\n elementUid: this.id\n }), new _DimensionControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_height'), this.formatter.getFormat('height', 'auto'), {\n units: ['px', '%', 'em', 'rem', 'vh', 'auto'],\n onChange: function onChange(value) {\n _this3.formatter.setFormat('height', value === null ? null : value);\n _this3.render();\n }\n }), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.display'), this.formatter.getFormat('display') || '', [{\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.default'),\n value: ''\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.block'),\n value: 'block'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.flex'),\n value: 'flex'\n }], function (value) {\n _this3.formatter.setFormat('display', value || null);\n _this3.render();\n }), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.direction'), this.formatter.getFormat('flex_direction') || '', [{\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.default'),\n value: ''\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.row'),\n value: 'row'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.column'),\n value: 'column'\n }], function (value) {\n _this3.formatter.setFormat('flex_direction', value || null);\n _this3.render();\n }), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.justify'), this.formatter.getFormat('justify_content') || '', [{\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.default'),\n value: ''\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.start'),\n value: 'flex-start'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.center'),\n value: 'center'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.end'),\n value: 'flex-end'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.space_between'),\n value: 'space-between'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.space_around'),\n value: 'space-around'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.space_evenly'),\n value: 'space-evenly'\n }], function (value) {\n _this3.formatter.setFormat('justify_content', value || null);\n _this3.render();\n }), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.align_items'), this.formatter.getFormat('align_items') || '', [{\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.default'),\n value: ''\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.stretch'),\n value: 'stretch'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.start'),\n value: 'flex-start'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.center'),\n value: 'center'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.end'),\n value: 'flex-end'\n }], function (value) {\n _this3.formatter.setFormat('align_items', value || null);\n _this3.render();\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.content_gap'), this.formatter.getFormat('gap', 0), {\n setValue: function setValue(value) {\n _this3.formatter.setFormat('gap', value);\n _this3.render();\n }\n }, {\n defaultValue: 0,\n minValue: 0,\n maxValue: 400,\n suffix: 'px',\n allowZero: true\n }),\n // Explicit separator before the inherited Grid-level controls so\n // users notice the transition from \"this cell\" to \"the whole grid\".\n new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.parent_grid'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.parent_grid_desc'))];\n var gridControls = this.container.getControls();\n return cellControls.concat(gridControls);\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var cell = new this(data.template);\n var blocks = Array.isArray(data.blocks) ? data.blocks : [];\n blocks.forEach(function (blockData) {\n var block = _ElementFactory_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"].createElement(blockData);\n block.container = cell;\n cell.appendBlock(block);\n });\n cell.vertical_align = data.vertical_align || \"top\";\n return this.parseFormats(cell, data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CellElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CellElement.js?");
/***/ }),
/***/ "./src/includes/CheckboxControl.js":
/*!*****************************************!*\
!*** ./src/includes/CheckboxControl.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * CheckboxControl — labeled boolean toggle.\n *\n * 2026-04-18 (Phase 2.24) rewrite — drops `.builder-checkbox-modern`\n * + `.toggle-label` legacy pair and Bootstrap utility classes. Uses\n * the shared `.bjs-toggle` primitive.\n */\nvar CheckboxControl = /*#__PURE__*/function () {\n function CheckboxControl(label, description, value, callback) {\n _classCallCheck(this, CheckboxControl);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.description = description;\n this.value = value;\n this.callback = callback;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-checkbox-control');\n this.render();\n }\n return _createClass(CheckboxControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row bjs-checkbox-control-row\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"checkbox_\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label>\\n \").concat(this.description ? \"<span class=\\\"bjs-control-description\\\">\".concat(this.description, \"</span>\") : '', \"\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <label class=\\\"bjs-toggle\\\">\\n <input id=\\\"checkbox_\").concat(this.id, \"\\\" type=\\\"checkbox\\\" class=\\\"bjs-toggle-input\\\" \").concat(this.value ? 'checked' : '', \">\\n <span class=\\\"bjs-toggle-track\\\"></span>\\n <span class=\\\"bjs-toggle-thumb\\\"></span>\\n </label>\\n </div>\\n </div>\\n \");\n var checkbox = this.domNode.querySelector(\"#checkbox_\".concat(this.id));\n checkbox.addEventListener('change', function (e) {\n _this.value = e.target.checked;\n if (typeof _this.callback === 'function') _this.callback(_this.value);\n });\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.value = newValue;\n var checkbox = this.domNode.querySelector(\"#checkbox_\".concat(this.id));\n if (checkbox) {\n checkbox.checked = this.value;\n if (typeof this.callback === 'function') this.callback(this.value);\n }\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckboxControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckboxControl.js?");
/***/ }),
/***/ "./src/includes/CheckboxElement.js":
/*!*****************************************!*\
!*** ./src/includes/CheckboxElement.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SelectControl.js */ \"./src/includes/SelectControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar CheckboxElement = /*#__PURE__*/function (_BaseElement) {\n function CheckboxElement(template) {\n var _this;\n var inputName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"\";\n var items = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];\n _classCallCheck(this, CheckboxElement);\n _this = _callSuper(this, CheckboxElement);\n _this.template = template;\n _this.inputName = inputName;\n _this.items = _this.normalizeItems(items);\n _this.domNode = null;\n _this.requiredTemplateKeys = ['items'];\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({});\n return _this;\n }\n _inherits(CheckboxElement, _BaseElement);\n return _createClass(CheckboxElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.checkbox');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n items: this.items,\n inputName: this.inputName\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(CheckboxElement, \"getData\", this, 3)([])), {}, {\n inputName: this.inputName,\n items: this.items\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this;\n return [new _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.checkbox_options'), this.items.map(function (item) {\n return {\n label: item.label,\n value: item.value\n };\n }), {\n setItems: function setItems(items) {\n _this2.items = _this2.normalizeItems(items);\n _this2.render();\n },\n setName: function setName(name) {\n _this2.inputName = name;\n _this2.render();\n }\n }, this.inputName)];\n }\n }, {\n key: \"normalizeItems\",\n value: function normalizeItems(items) {\n return (Array.isArray(items) ? items : []).map(function (item, index) {\n var _item$label, _item$value;\n return {\n label: (_item$label = item === null || item === void 0 ? void 0 : item.label) !== null && _item$label !== void 0 ? _item$label : \"Option \".concat(index + 1),\n value: (_item$value = item === null || item === void 0 ? void 0 : item.value) !== null && _item$value !== void 0 ? _item$value : \"option_\".concat(index + 1)\n };\n });\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.inputName || \"\", data.items || []), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckboxElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckboxElement.js?");
/***/ }),
/***/ "./src/includes/CheckboxWidget.js":
/*!****************************************!*\
!*** ./src/includes/CheckboxWidget.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _CheckboxElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./CheckboxElement.js */ \"./src/includes/CheckboxElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar CheckboxWidget = /*#__PURE__*/function (_BaseWidget) {\n function CheckboxWidget() {\n var _this;\n _classCallCheck(this, CheckboxWidget);\n _this = _callSuper(this, CheckboxWidget);\n _this.block.appendElements([new _CheckboxElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Checkbox', 'interests', [{\n label: 'Product updates',\n value: 'product_updates'\n }, {\n label: 'Events',\n value: 'events'\n }, {\n label: 'Promotions',\n value: 'promotions'\n }])]);\n return _this;\n }\n _inherits(CheckboxWidget, _BaseWidget);\n return _createClass(CheckboxWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.checkbox');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'check_box';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckboxWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckboxWidget.js?");
/***/ }),
/***/ "./src/includes/CheckoutControl.js":
/*!*****************************************!*\
!*** ./src/includes/CheckoutControl.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar CheckoutControl = /*#__PURE__*/function () {\n function CheckoutControl() {\n var values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var callbacks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, CheckoutControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n this.values = values;\n this.callbacks = callbacks;\n\n // Create the main container element. Initial render is deferred\n // to afterRender() so this.host is available — Builder assigns\n // host AFTER getControls() returns and BEFORE afterRender().\n this.domNode = document.createElement(\"div\");\n }\n\n /** Builder hook — fires after host injection + DOM mount. Safe entry\n * point for the first render that depends on `this.host`. */\n return _createClass(CheckoutControl, [{\n key: \"afterRender\",\n value: function afterRender() {\n this.render();\n }\n }, {\n key: \"render\",\n value: function render() {\n this.domNode.innerHTML = this.host.renderTemplate('CheckoutControl', {\n id: this.id,\n values: this.values\n });\n this.attachEvents();\n }\n }, {\n key: \"attachEvents\",\n value: function attachEvents() {\n var _this = this;\n var inputs = this.domNode.querySelectorAll('[data-path]');\n inputs.forEach(function (input) {\n var update = function update() {\n var path = input.getAttribute('data-path');\n var value = input.type === 'checkbox' ? input.checked : input.value;\n _this.setValue(path, value);\n\n /* Color chip: reflect picked value on the parent .bjs-checkout-color-chip\n via --bjs-color-current so the preview updates live during the native\n color picker session, before the element re-renders. */\n if (input.type === 'color') {\n var chip = input.closest('.bjs-checkout-color-chip');\n if (chip) chip.style.setProperty('--bjs-color-current', value);\n }\n };\n input.addEventListener('input', update);\n input.addEventListener('change', update);\n });\n }\n }, {\n key: \"setValue\",\n value: function setValue(path, value) {\n this.setValueByPath(this.values, path, value);\n if (this.callbacks && typeof this.callbacks.update === 'function') {\n this.callbacks.update(path, value, this.values);\n }\n }\n }, {\n key: \"setValueByPath\",\n value: function setValueByPath(obj, path, value) {\n if (!path) {\n return;\n }\n var segments = path.split('.');\n var cursor = obj;\n segments.forEach(function (segment, index) {\n if (index === segments.length - 1) {\n cursor[segment] = value;\n } else {\n if (!cursor[segment] || _typeof(cursor[segment]) !== 'object') {\n cursor[segment] = {};\n }\n cursor = cursor[segment];\n }\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutControl.js?");
/***/ }),
/***/ "./src/includes/CheckoutElement.js":
/*!*****************************************!*\
!*** ./src/includes/CheckoutElement.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _CheckoutControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./CheckoutControl.js */ \"./src/includes/CheckoutControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar CheckoutElement = /*#__PURE__*/function (_BaseElement) {\n function CheckoutElement(template, action, method) {\n var _this;\n _classCallCheck(this, CheckoutElement);\n _this = _callSuper(this, CheckoutElement);\n _this.template = template;\n _this.action = action || '';\n _this.method = method || '';\n _this.domNode = null;\n\n // text + label values that drive the checkout template\n _this.values = _this.getDefaultValues();\n\n // required keys for the element template\n _this.requiredTemplateKeys = [];\n\n // W0.2b — no inline-edit registrations (CheckoutElement renders a\n // multi-section form, not a single editable text). The base class\n // _wireInlineEdit() short-circuits cleanly when the registry is empty.\n\n // Formatter - Bootstrap button default styles\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n // \n });\n return _this;\n }\n _inherits(CheckoutElement, _BaseElement);\n return _createClass(CheckoutElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.checkout');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c). W0.2b: legacy applyInlineEdit()\n // removed; the new framework (auto-fired _wireInlineEdit from\n // afterRender) is a no-op when the registry is empty.\n this.domNode.innerHTML = this.renderTemplate({\n action: this.action,\n method: this.method,\n values: this.values\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(CheckoutElement, \"getData\", this, 3)([])), {}, {\n action: this.action,\n method: this.method,\n values: this.values\n });\n }\n }, {\n key: \"getDefaultValues\",\n value: function getDefaultValues() {\n return {\n ui: {\n previewLabel: 'Checkout Preview',\n modeLabel: 'Guest Checkout'\n },\n headerTitle: 'Checkout Form',\n buttonTexts: {\n guestSubmit: 'Complete Order',\n saved: 'Rush My Order!',\n upgrade: 'Update My Order!',\n submitting: 'Submitting...'\n },\n headlines: {\n contact: 'CONTACT INFORMATION',\n billing: 'BILLING INFORMATION',\n payment: 'PAYMENT INFORMATION',\n privacy: 'We Never Share Your Information With Anyone'\n },\n contactLabels: {\n firstName: 'First Name',\n lastName: 'Last Name',\n email: 'Email',\n phone: 'Phone Number',\n address: 'Address',\n apartment: 'Apartment, building, floor',\n apartmentOptional: '(optional)',\n country: 'Country',\n state: 'State',\n city: 'City',\n postal: 'Postal Code'\n },\n defaults: {\n country: 'Vietnam',\n state: 'An Giang'\n },\n paymentSummary: {\n title: 'Summary',\n cta: 'For more details, fill the form'\n }\n };\n }\n }, {\n key: \"mergeDeep\",\n value: function mergeDeep(target, source) {\n var _this2 = this;\n var output = target || {};\n if (_typeof(target) !== 'object' || target === null) {\n return source;\n }\n if (_typeof(source) !== 'object' || source === null) {\n return target;\n }\n Object.keys(source).forEach(function (key) {\n if (Array.isArray(source[key])) {\n output[key] = source[key].slice();\n } else if (_typeof(source[key]) === 'object') {\n output[key] = _this2.mergeDeep(target[key] || {}, source[key]);\n } else {\n output[key] = source[key];\n }\n });\n return output;\n }\n }, {\n key: \"setValueByPath\",\n value: function setValueByPath(obj, path, value) {\n if (!path) {\n return;\n }\n var segments = path.split('.');\n var current = obj;\n segments.forEach(function (segment, index) {\n if (index === segments.length - 1) {\n current[segment] = value;\n } else {\n if (!current[segment] || _typeof(current[segment]) !== 'object') {\n current[segment] = {};\n }\n current = current[segment];\n }\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this3 = this;\n return [\n // TextControl\n new TextControl(\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.action_url'),\n // value\n this.action,\n // callback\n {\n // set name\n setText: function setText(action) {\n _this3.action = action;\n _this3.render();\n }\n }),\n // TextControl\n new TextControl(\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.method'),\n // value\n this.method,\n // callback\n {\n // set name\n setText: function setText(method) {\n _this3.method = method;\n _this3.render();\n }\n }), new _CheckoutControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](this.values, {\n update: function update(path, value) {\n _this3.setValueByPath(_this3.values, path, value);\n _this3.render();\n }\n })\n\n // new AlignControl(\n // 'Alignment',\n // this.formatter.getFormat('align'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('align', value);\n // this.render();\n // }\n // },\n // ['left', 'center', 'right']\n // ),\n\n // new FontFamilyControl(\n // 'Font Family',\n // this.formatter.getFormat('font_family'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('font_family', value);\n // this.render();\n // }\n // }\n // ),\n\n // new FontWeightControl(\n // 'Font Weight',\n // this.formatter.getFormat('font_weight'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('font_weight', value);\n // this.render();\n // }\n // }\n // ),\n\n // new NumberControl(\n // 'Font Size',\n // this.formatter.getFormat('font_size'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('font_size', value);\n // this.render();\n // }\n // },\n // {\n // defaultValue: 16,\n // minValue: 8,\n // maxValue: 72,\n // suffix: 'px',\n // allowZero: false\n // }\n // ),\n\n // new ColorPickerControl(\n // 'Text Color',\n // this.formatter.getFormat('text_color'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('text_color', value);\n // this.render();\n // }\n // }\n // ),\n\n // new ColorPickerControl(\n // 'Link Color',\n // this.formatter.getFormat('link_color'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('link_color', value);\n // this.render();\n // }\n // }\n // ),\n\n // new AlignControl(\n // 'Text alignment',\n // this.formatter.getFormat('text_align'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('text_align', value);\n // this.render();\n // }\n // }\n // ),\n\n // new NumberControl(\n // 'Paragraph Spacing',\n // this.formatter.getFormat('paragraph_spacing'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('paragraph_spacing', value);\n // this.render();\n // }\n // },\n // {\n // defaultValue: 0,\n // minValue: 0,\n // maxValue: 50,\n // suffix: 'px',\n // allowZero: true\n // }\n // ),\n\n // new LineHeightControl(\n // 'Line Height',\n // this.formatter.getFormat('line_height'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('line_height', value);\n // this.render();\n // }\n // }\n // ),\n\n // new NumberControl(\n // 'Letter Spacing',\n // this.formatter.getFormat('letter_spacing'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('letter_spacing', value);\n // this.render();\n // }\n // },\n // {\n // defaultValue: 0,\n // minValue: -5,\n // maxValue: 10,\n // step: 0.1,\n // suffix: 'px',\n // allowZero: true,\n // allowNegative: true\n // }\n // ),\n // new TextDirectionControl(\n // 'Text Direction',\n // this.formatter.getFormat('text_direction'),\n // {\n // setValue: (value) => {\n // this.formatter.setFormat('text_direction', value);\n // this.render();\n // }\n // }\n // ),\n\n // new BackgroundControl(\n // // label\n // 'Background Settings',\n // // values\n // {\n // color: this.formatter.getFormat('background_color'),\n // image: this.formatter.getFormat('background_image'),\n // position: this.formatter.getFormat('background_position'),\n // size: this.formatter.getFormat('background_size').toString().replace('%', ''),\n // toRepeat: this.formatter.getFormat('background_repeat') === 'repeat'\n // },\n // // callback\n // {\n // setBackground: (values) => {\n // this.formatter.setFormat('background_color', values.color);\n // this.formatter.setFormat('background_image', values.image);\n // this.formatter.setFormat('background_position', values.position);\n // this.formatter.setFormat('background_size', parseInt(values.size, 10) || 100);\n // this.formatter.setFormat('background_repeat', values.toRepeat ? 'repeat' : 'no-repeat');\n // this.render();\n // }\n // }\n // ),\n\n // new BorderControl(\n // 'Border Settings',\n\n // {\n // border_top_style: this.formatter.getFormat('border_top_style'),\n // border_top_width: this.formatter.getFormat('border_top_width'),\n // border_top_color: this.formatter.getFormat('border_top_color'),\n // border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n // border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n // border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n // border_left_style: this.formatter.getFormat('border_left_style'),\n // border_left_width: this.formatter.getFormat('border_left_width'),\n // border_left_color: this.formatter.getFormat('border_left_color'),\n // border_right_style: this.formatter.getFormat('border_right_style'),\n // border_right_width: this.formatter.getFormat('border_right_width'),\n // border_right_color: this.formatter.getFormat('border_right_color'),\n // },\n\n // {\n // setBorder: (\n // border_top_style, border_top_width, border_top_color,\n // border_bottom_style, border_bottom_width, border_bottom_color,\n // border_left_style, border_left_width, border_left_color,\n // border_right_style, border_right_width, border_right_color\n // ) => {\n // this.formatter.setFormat('border_top_style', border_top_style);\n // this.formatter.setFormat('border_top_width', border_top_width);\n // this.formatter.setFormat('border_top_color', border_top_color);\n\n // this.formatter.setFormat('border_bottom_style', border_bottom_style);\n // this.formatter.setFormat('border_bottom_width', border_bottom_width);\n // this.formatter.setFormat('border_bottom_color', border_bottom_color);\n\n // this.formatter.setFormat('border_left_style', border_left_style);\n // this.formatter.setFormat('border_left_width', border_left_width);\n // this.formatter.setFormat('border_left_color', border_left_color);\n\n // this.formatter.setFormat('border_right_style', border_right_style);\n // this.formatter.setFormat('border_right_width', border_right_width);\n // this.formatter.setFormat('border_right_color', border_right_color);\n\n // // re-render\n // this.render();\n // }\n // }\n // ),\n\n // new BorderRadiusControl(\n // 'Radius',\n // this.formatter.getFormat('border_radius'),\n // {\n // setRadius: (v) => {\n // this.formatter.setFormat('border_radius', v);\n // this.render();\n // }\n // }\n // ),\n\n // new PaddingMarginControl(\n // // label\n // 'Padding',\n // // value\n // {\n // top: this.formatter.getFormat('padding_top'),\n // right: this.formatter.getFormat('padding_right'),\n // bottom: this.formatter.getFormat('padding_bottom'),\n // left: this.formatter.getFormat('padding_left'),\n // },\n // // callback\n // {\n // setValues: (values) => {\n // this.formatter.setFormat('padding_top', values.top);\n // this.formatter.setFormat('padding_right', values.right);\n // this.formatter.setFormat('padding_bottom', values.bottom);\n // this.formatter.setFormat('padding_left', values.left);\n\n // this.render();\n // }\n // }\n // ),\n ];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var e = new this(data.template, data.action, data.method);\n // merge stored values with defaults to keep compatibility\n if (data.values) {\n e.values = e.mergeDeep(e.getDefaultValues(), data.values);\n }\n return this.parseFormats(e, data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutElement.js?");
/***/ }),
/***/ "./src/includes/CheckoutSimpleControl.js":
/*!***********************************************!*\
!*** ./src/includes/CheckoutSimpleControl.js ***!
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar CheckoutSimpleControl = /*#__PURE__*/function () {\n function CheckoutSimpleControl() {\n var values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var callbacks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, CheckoutSimpleControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n this.values = values;\n this.callbacks = callbacks;\n\n // Create the main container element. Initial render is deferred\n // to afterRender() so this.host is available — Builder assigns\n // host AFTER getControls() returns and BEFORE afterRender().\n this.domNode = document.createElement(\"div\");\n }\n\n /** Builder hook — fires after host injection + DOM mount. Safe entry\n * point for the first render that depends on `this.host`. */\n return _createClass(CheckoutSimpleControl, [{\n key: \"afterRender\",\n value: function afterRender() {\n this.render();\n }\n }, {\n key: \"render\",\n value: function render() {\n this.domNode.innerHTML = this.host.renderTemplate('CheckoutSimpleControl', {\n id: this.id,\n values: this.values\n });\n this.attachEvents();\n }\n }, {\n key: \"attachEvents\",\n value: function attachEvents() {\n var _this = this;\n var inputs = this.domNode.querySelectorAll('[data-path]');\n inputs.forEach(function (input) {\n var update = function update() {\n var path = input.getAttribute('data-path');\n var value = input.type === 'checkbox' ? input.checked : input.value;\n _this.setValue(path, value);\n };\n input.addEventListener('input', update);\n input.addEventListener('change', update);\n });\n }\n }, {\n key: \"setValue\",\n value: function setValue(path, value) {\n this.setValueByPath(this.values, path, value);\n if (this.callbacks && typeof this.callbacks.update === 'function') {\n this.callbacks.update(path, value, this.values);\n }\n }\n }, {\n key: \"setValueByPath\",\n value: function setValueByPath(obj, path, value) {\n if (!path) {\n return;\n }\n var segments = path.split('.');\n var cursor = obj;\n segments.forEach(function (segment, index) {\n if (index === segments.length - 1) {\n cursor[segment] = value;\n } else {\n if (!cursor[segment] || _typeof(cursor[segment]) !== 'object') {\n cursor[segment] = {};\n }\n cursor = cursor[segment];\n }\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutSimpleControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutSimpleControl.js?");
/***/ }),
/***/ "./src/includes/CheckoutSimpleElement.js":
/*!***********************************************!*\
!*** ./src/includes/CheckoutSimpleElement.js ***!
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _CheckoutSimpleControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./CheckoutSimpleControl.js */ \"./src/includes/CheckoutSimpleControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar CheckoutSimpleElement = /*#__PURE__*/function (_BaseElement) {\n function CheckoutSimpleElement(template) {\n var _this;\n _classCallCheck(this, CheckoutSimpleElement);\n _this = _callSuper(this, CheckoutSimpleElement);\n _this.template = template;\n _this.domNode = null;\n\n // text + label values that drive the checkout template\n _this.values = _this.getDefaultValues();\n\n // required keys for the element template\n _this.requiredTemplateKeys = [];\n\n // W0.2b — no inline-edit registrations (CheckoutSimpleElement renders\n // a multi-section form, not a single editable text). The base class\n // _wireInlineEdit() short-circuits cleanly when the registry is empty.\n // The `inlineEditableAttributes()` accessor below still works via the\n // `inlineEditParams` computed getter on BaseElement (returns [] here).\n\n // Formatter - Bootstrap button default styles\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n // text styles\n font_family: \"inherit\",\n font_weight: \"400\",\n font_size: \"16px\",\n text_color: \"#ffffff\",\n link_color: \"#ffffff\",\n paragraph_spacing: null,\n text_align: 'center',\n // left, center, right,\n line_height: \"1.5\",\n letter_spacing: null,\n text_direction: \"ltr\",\n // ltr, rtl\n\n // background - Bootstrap primary button\n background_color: \"#0d6efd\",\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n // spacing - Bootstrap button padding\n padding_top: 6,\n padding_right: 12,\n padding_bottom: 6,\n padding_left: 12,\n // border - Bootstrap button border\n border_top_style: \"solid\",\n border_top_width: \"1px\",\n border_top_color: \"#0d6efd\",\n border_right_style: \"solid\",\n border_right_width: \"1px\",\n border_right_color: \"#0d6efd\",\n border_bottom_style: \"solid\",\n border_bottom_width: \"1px\",\n border_bottom_color: \"#0d6efd\",\n border_left_width: \"1px\",\n border_left_style: \"solid\",\n border_left_color: \"#0d6efd\",\n // border radius - Bootstrap button radius\n border_radius: \"0.375rem\",\n // sizing\n width: null,\n max_width: null,\n min_width: null\n });\n return _this;\n }\n _inherits(CheckoutSimpleElement, _BaseElement);\n return _createClass(CheckoutSimpleElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.checkout_simple');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c). W0.2b: legacy applyInlineEdit()\n // removed; the new framework (auto-fired _wireInlineEdit from\n // afterRender) is a no-op when the registry is empty.\n this.domNode.innerHTML = this.renderTemplate({\n values: this.values\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(CheckoutSimpleElement, \"getData\", this, 3)([])), {}, {\n values: this.values\n });\n }\n }, {\n key: \"getDefaultValues\",\n value: function getDefaultValues() {\n return {\n ui: {\n previewLabel: 'Simple Checkout Preview',\n modeLabel: 'Contact Information'\n },\n headerTitle: 'Quick Checkout',\n buttonTexts: {\n submit: 'Submit Order',\n submitting: 'Submitting...'\n },\n headlines: {\n contact: 'CONTACT INFORMATION',\n privacy: 'We Never Share Your Information With Anyone'\n },\n contactLabels: {\n firstName: 'First Name',\n lastName: 'Last Name',\n email: 'Email',\n phone: 'Phone Number'\n }\n };\n }\n }, {\n key: \"mergeDeep\",\n value: function mergeDeep(target, source) {\n var _this2 = this;\n var output = target || {};\n if (_typeof(target) !== 'object' || target === null) {\n return source;\n }\n if (_typeof(source) !== 'object' || source === null) {\n return target;\n }\n Object.keys(source).forEach(function (key) {\n if (Array.isArray(source[key])) {\n output[key] = source[key].slice();\n } else if (_typeof(source[key]) === 'object') {\n output[key] = _this2.mergeDeep(target[key] || {}, source[key]);\n } else {\n output[key] = source[key];\n }\n });\n return output;\n }\n }, {\n key: \"setValueByPath\",\n value: function setValueByPath(obj, path, value) {\n if (!path) {\n return;\n }\n var segments = path.split('.');\n var current = obj;\n segments.forEach(function (segment, index) {\n if (index === segments.length - 1) {\n current[segment] = value;\n } else {\n if (!current[segment] || _typeof(current[segment]) !== 'object') {\n current[segment] = {};\n }\n current = current[segment];\n }\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this3 = this;\n return [new _CheckoutSimpleControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](this.values, {\n update: function update(path, value) {\n _this3.setValueByPath(_this3.values, path, value);\n _this3.render();\n }\n })];\n }\n }, {\n key: \"inlineEditableAttributes\",\n value: function inlineEditableAttributes() {\n return this.inlineEditParams;\n }\n }, {\n key: \"getFormats\",\n value: function getFormats() {\n return this.formatter.getFormats();\n }\n\n // W0.2c: legacy 2-arg `renderTemplate(templateName, data)` override removed.\n // BaseElement.renderTemplate(vars) now handles everything correctly.\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var e = new this(data.template);\n if (data.values) {\n e.values = e.mergeDeep(e.getDefaultValues(), data.values);\n }\n return this.parseFormats(e, data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutSimpleElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutSimpleElement.js?");
/***/ }),
/***/ "./src/includes/CheckoutSimpleWidget.js":
/*!**********************************************!*\
!*** ./src/includes/CheckoutSimpleWidget.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _CheckoutSimpleElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CheckoutSimpleElement.js */ \"./src/includes/CheckoutSimpleElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar CheckoutSimpleWidget = /*#__PURE__*/function (_BaseWidget) {\n function CheckoutSimpleWidget() {\n var _this;\n _classCallCheck(this, CheckoutSimpleWidget);\n _this = _callSuper(this, CheckoutSimpleWidget); // Call the parent class constructor\n\n // Add a CheckoutSimpleElement to the widget\n var checkout = new _CheckoutSimpleElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('CheckoutSimple');\n\n // Append the new element to the block\n _this.block.appendElements([checkout]);\n return _this;\n }\n _inherits(CheckoutSimpleWidget, _BaseWidget);\n return _createClass(CheckoutSimpleWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.checkout_simple');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'badge';\n }\n }, {\n key: \"getElements\",\n value: function getElements() {\n // Return the elements\n return this.elements;\n }\n }, {\n key: \"renderElements\",\n value: function renderElements() {\n // Clone all elements and return the cloned ones\n return this.elements.map(function (element) {\n var data = element.getData();\n return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(data);\n });\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutSimpleWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutSimpleWidget.js?");
/***/ }),
/***/ "./src/includes/CheckoutWidget.js":
/*!****************************************!*\
!*** ./src/includes/CheckoutWidget.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _CheckoutElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CheckoutElement.js */ \"./src/includes/CheckoutElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar CheckoutWidget = /*#__PURE__*/function (_BaseWidget) {\n function CheckoutWidget() {\n var _this;\n _classCallCheck(this, CheckoutWidget);\n _this = _callSuper(this, CheckoutWidget); // Call the parent class constructor\n\n // Add a CheckoutElement to the widget\n var checkout = new _CheckoutElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Checkout');\n\n // Append the new element to the block\n _this.block.appendElements([checkout]);\n return _this;\n }\n _inherits(CheckoutWidget, _BaseWidget);\n return _createClass(CheckoutWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.checkout');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'payment';\n }\n }, {\n key: \"getElements\",\n value: function getElements() {\n // Return the elements\n return this.elements;\n }\n }, {\n key: \"renderElements\",\n value: function renderElements() {\n // Clone all elements and return the cloned ones\n return this.elements.map(function (element) {\n var data = element.getData();\n return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(data);\n });\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutWidget.js?");
/***/ }),
/***/ "./src/includes/ColorPickerControl.js":
/*!********************************************!*\
!*** ./src/includes/ColorPickerControl.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _ui_ColorPalettePicker_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ui/ColorPalettePicker.js */ \"./src/includes/ui/ColorPalettePicker.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n\n/**\n * ColorPickerControl — labeled color + hex pair.\n *\n * 2026-04-18 (Phase 2.13) rewrite: drops Bootstrap `.form-control` + inline\n * `<style>` injection, replaces with the `.bjs-color-input` primitive for\n * the swatch and `.bjs-text-input` for the hex field. Null state shows the\n * transparent checkerboard pattern baked into `.bjs-color-swatch`.\n *\n * 2026-04-21 (TEXT_INLINE_PLAN W1.2+): swatch click no longer opens the\n * native browser color picker. It opens a floating popover hosting the\n * shared `ColorPalettePicker` primitive (same Google-style 60-swatch UX\n * used by the canvas inline toolbar's Text Color / Highlight popovers —\n * see `src/includes/overlays/TextColorPopoverOverlay.js`). The native\n * `<input type=\"color\">` is kept ONLY as the \"Custom\" row inside the\n * popover. Single-popover invariant enforced via a module-scoped\n * singleton — clicking a different swatch elsewhere in the sidebar\n * dismisses the previous popover automatically.\n *\n * Hex input parses 3- and 6-digit hex; invalid input reverts to the last\n * known value on blur. Empty input clears to null (`color.not_set` label).\n */\n\nvar POPOVER_Z_INDEX = 1001; // above sidebar panels / overlays\nvar RECENT_MAX = 10;\n\n// Module-scoped singleton — enforces the \"one open sidebar color popover\n// at a time\" invariant across every ColorPickerControl instance. Swapping\n// is cheaper than dismiss+reopen (no flicker); the previous popover is\n// closed synchronously when a new one opens.\nvar _activeSidebarPopover = null;\nvar ColorPickerControl = /*#__PURE__*/function () {\n function ColorPickerControl(label, color, callback) {\n _classCallCheck(this, ColorPickerControl);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.color = color;\n this.callback = callback;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-color-picker-control');\n this._popover = null;\n this.render();\n }\n return _createClass(ColorPickerControl, [{\n key: \"render\",\n value: function render() {\n var swatchColor = this.color || '#000000';\n var hexLabel = this.color || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n var isUnset = !this.color;\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"\".concat(this.id, \"_hex\\\"><span>\").concat(this.label, \"</span></label>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-color-input\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-color-swatch\\\"\\n id=\\\"\").concat(this.id, \"_swatch\\\"\\n aria-label=\\\"\").concat(this.label, \"\\\"\\n aria-haspopup=\\\"dialog\\\"\\n aria-expanded=\\\"false\\\">\\n <span class=\\\"bjs-color-preview\\\" data-role=\\\"swatch-preview\\\"\\n style=\\\"--bjs-color-current: \").concat(isUnset ? 'transparent' : swatchColor, \";\\\"></span>\\n </button>\\n <input id=\\\"\").concat(this.id, \"_hex\\\" type=\\\"text\\\"\\n class=\\\"bjs-color-hex\\\"\\n value=\\\"\").concat(hexLabel, \"\\\"\\n aria-label=\\\"\").concat(this.label, \" hex value\\\"\\n autocomplete=\\\"off\\\" spellcheck=\\\"false\\\">\\n </div>\\n </div>\\n </div>\\n \");\n this.swatchBtn = this.domNode.querySelector(\"#\".concat(this.id, \"_swatch\"));\n this.hexInput = this.domNode.querySelector(\"#\".concat(this.id, \"_hex\"));\n this.swatchPreview = this.domNode.querySelector('[data-role=\"swatch-preview\"]');\n this._bindEvents();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this = this;\n this.swatchBtn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this._togglePopover();\n });\n\n // Placeholder UX: clear \"not set\" label on focus so user can type.\n this.hexInput.addEventListener('focus', function (e) {\n if (e.target.value === _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set')) e.target.value = '';\n });\n\n // Empty on blur → clear to null.\n this.hexInput.addEventListener('blur', function (e) {\n if (e.target.value.trim() === '') {\n e.target.value = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n _this._notify(null);\n }\n });\n this.hexInput.addEventListener('change', function (e) {\n var v = e.target.value.trim();\n if (v === '' || v === _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set')) {\n _this.hexInput.value = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n _this._notify(null);\n return;\n }\n if (!v.startsWith('#')) v = '#' + v;\n if (/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(v)) {\n _this.hexInput.value = v;\n _this._notify(v);\n } else {\n // Invalid → revert to last known good.\n _this.hexInput.value = _this.color || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n }\n });\n }\n }, {\n key: \"_notify\",\n value: function _notify(val) {\n this.color = val;\n // Update swatch preview — null → transparent checkerboard shows.\n if (this.swatchPreview) {\n this.swatchPreview.style.setProperty('--bjs-color-current', val || 'transparent');\n }\n if (typeof this.callback === 'function') {\n this.callback(val);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(val);\n } else if (this.callback && typeof this.callback.setColor === 'function') {\n this.callback.setColor(val);\n }\n }\n\n /* ── popover lifecycle ─────────────────────────────────────────── */\n }, {\n key: \"_togglePopover\",\n value: function _togglePopover() {\n if (_activeSidebarPopover && _activeSidebarPopover.owner === this) {\n // Second click on same swatch → close.\n this._closePopover();\n return;\n }\n // Different control's popover open → swap (close previous first).\n if (_activeSidebarPopover) {\n try {\n _activeSidebarPopover.close();\n } catch (_) {}\n _activeSidebarPopover = null;\n }\n this._openPopover();\n }\n }, {\n key: \"_openPopover\",\n value: function _openPopover() {\n var _this2 = this;\n try {\n var popover = this._buildPopover();\n document.body.appendChild(popover.domNode);\n popover.positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n anchor: function anchor() {\n return _this2.swatchBtn.getBoundingClientRect();\n },\n target: popover.domNode,\n offset: 8,\n collisionPadding: 12,\n preferredSide: 'below',\n flip: true\n });\n this._registerDismissListeners(popover);\n this._popover = popover;\n _activeSidebarPopover = {\n owner: this,\n close: function close() {\n return _this2._closePopover();\n }\n };\n this.swatchBtn.setAttribute('aria-expanded', 'true');\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[bjs:color-picker-control] popover open failed:', err);\n this._closePopover();\n }\n }\n }, {\n key: \"_closePopover\",\n value: function _closePopover() {\n var pop = this._popover;\n if (!pop) return;\n this._unregisterDismissListeners(pop);\n if (pop.positionHandle) {\n try {\n pop.positionHandle.dispose();\n } catch (_) {}\n }\n if (pop.domNode && pop.domNode.parentNode) {\n try {\n pop.domNode.parentNode.removeChild(pop.domNode);\n } catch (_) {}\n }\n this._popover = null;\n if (_activeSidebarPopover && _activeSidebarPopover.owner === this) {\n _activeSidebarPopover = null;\n }\n if (this.swatchBtn) this.swatchBtn.setAttribute('aria-expanded', 'false');\n }\n }, {\n key: \"_buildPopover\",\n value: function _buildPopover() {\n var _this3 = this;\n var domNode = document.createElement('div');\n // Reuse the canvas popover's chrome class — same visual shell,\n // same tokens, same dark-mode rules. Adding a data-surface marker\n // so tests / styles can target the sidebar variant when needed.\n domNode.className = 'bjs-ovl bjs-ovl-color-popover';\n domNode.setAttribute('role', 'dialog');\n domNode.setAttribute('aria-label', this.label);\n domNode.setAttribute('data-surface', 'sidebar');\n domNode.style.zIndex = String(POPOVER_Z_INDEX);\n\n // Preserve focus on interactive children — prevent the mousedown\n // on the popover body from stealing focus from the hex input / etc.\n domNode.addEventListener('mousedown', function (e) {\n if (e.target && e.target.closest('input, textarea, select, button[data-role=\"eyedropper\"], button[data-role=\"swatch\"], button[data-role=\"reset\"]')) return;\n e.preventDefault();\n });\n var picker = new _ui_ColorPalettePicker_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n value: this.color,\n recent: this._getRecentColors(),\n title: this.label,\n onPick: function onPick(hex) {\n if (hex === null) {\n _this3._handleReset();\n return;\n }\n _this3._handlePick(hex);\n },\n onReset: function onReset() {\n return _this3._handleReset();\n }\n });\n domNode.appendChild(picker.domNode);\n return {\n domNode: domNode,\n picker: picker,\n positionHandle: null\n };\n }\n }, {\n key: \"_handlePick\",\n value: function _handlePick(hex) {\n this._pushRecent(hex);\n this._applyValue(hex);\n this._closePopover();\n }\n }, {\n key: \"_handleReset\",\n value: function _handleReset() {\n this._applyValue(null);\n this._closePopover();\n }\n }, {\n key: \"_applyValue\",\n value: function _applyValue(val) {\n this.color = val;\n if (this.hexInput) {\n this.hexInput.value = val || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n }\n if (this.swatchPreview) {\n this.swatchPreview.style.setProperty('--bjs-color-current', val || 'transparent');\n }\n if (typeof this.callback === 'function') {\n this.callback(val);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(val);\n } else if (this.callback && typeof this.callback.setColor === 'function') {\n this.callback.setColor(val);\n }\n }\n\n /* ── recent LRU (sidebar-wide bucket) ─────────────────────────── */\n }, {\n key: \"_getRecentColors\",\n value: function _getRecentColors() {\n // Host-injection — `this.host` is set by Builder.renderElementControls\n // when this control is emitted by an element's getControls(). Each\n // Builder owns its own LRU bucket so two on-page builders don't\n // share recent colors.\n var host = this.host;\n if (!host) return [];\n var arr = Array.isArray(host._recentElementColors) ? host._recentElementColors : [];\n return arr.slice();\n }\n }, {\n key: \"_pushRecent\",\n value: function _pushRecent(hex) {\n var host = this.host;\n if (!host || !hex) return;\n var arr = Array.isArray(host._recentElementColors) ? host._recentElementColors.slice() : [];\n var idx = arr.findIndex(function (c) {\n return c.toLowerCase() === hex.toLowerCase();\n });\n if (idx >= 0) arr.splice(idx, 1);\n arr.unshift(hex);\n if (arr.length > RECENT_MAX) arr = arr.slice(0, RECENT_MAX);\n host._recentElementColors = arr;\n }\n\n /* ── dismiss ──────────────────────────────────────────────────── */\n }, {\n key: \"_registerDismissListeners\",\n value: function _registerDismissListeners(popover) {\n var _this4 = this;\n popover.onDocKey = function (e) {\n if (e.key === 'Escape') {\n e.stopPropagation();\n _this4._closePopover();\n }\n };\n document.addEventListener('keydown', popover.onDocKey, true);\n popover.onDocMouseDown = function (e) {\n if (!_this4._popover) return;\n var t = e.target;\n if (_this4._popover.domNode.contains(t)) return;\n if (_this4.swatchBtn && _this4.swatchBtn.contains(t)) return;\n _this4._closePopover();\n };\n setTimeout(function () {\n if (_this4._popover === popover) {\n document.addEventListener('mousedown', popover.onDocMouseDown, true);\n }\n }, 0);\n }\n }, {\n key: \"_unregisterDismissListeners\",\n value: function _unregisterDismissListeners(popover) {\n if (popover.onDocKey) {\n document.removeEventListener('keydown', popover.onDocKey, true);\n popover.onDocKey = null;\n }\n if (popover.onDocMouseDown) {\n document.removeEventListener('mousedown', popover.onDocMouseDown, true);\n popover.onDocMouseDown = null;\n }\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.color = newValue;\n if (!this.hexInput) return;\n if (newValue === null || newValue === undefined) {\n this.hexInput.value = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n if (this.swatchPreview) this.swatchPreview.style.setProperty('--bjs-color-current', 'transparent');\n } else {\n this.hexInput.value = newValue;\n if (this.swatchPreview) this.swatchPreview.style.setProperty('--bjs-color-current', newValue);\n }\n if (this._popover && this._popover.picker) {\n try {\n this._popover.picker.setValue(newValue);\n } catch (_) {}\n }\n if (typeof this.callback === 'function') this.callback(this.color);else if (this.callback && typeof this.callback.setValue === 'function') this.callback.setValue(this.color);else if (this.callback && typeof this.callback.setColor === 'function') this.callback.setColor(this.color);\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.color;\n }\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this._popover) this._closePopover();\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ColorPickerControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ColorPickerControl.js?");
/***/ }),
/***/ "./src/includes/CustomRangeControl.js":
/*!********************************************!*\
!*** ./src/includes/CustomRangeControl.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar CustomRangeControl = /*#__PURE__*/function () {\n function CustomRangeControl(label, min, max, unit, isAuto, callback) {\n var value = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : '';\n _classCallCheck(this, CustomRangeControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n // Initialize properties\n this.label = label; // Label for the text control\n this.min = min; // Minimum value for the range\n this.max = max; // Maximum value for the range\n this.unit = unit; // Unit of measurement (e.g., px, em)\n this.isAuto = isAuto; // Flag to indicate if the range is auto-adjusting\n this.callback = callback; // Callback function to handle input changes\n\n if (value === '' || value === 'auto') {\n this.value = 48;\n } else {\n this.value = parseInt(value, 10);\n }\n\n // Create the main container element\n this.domNode = document.createElement(\"div\");\n\n //\n this.render(); // Call the render method to create the UI\n this.setupEventListeners(); // Set up event listeners\n }\n return _createClass(CustomRangeControl, [{\n key: \"render\",\n value: function render() {\n this.domNode.innerHTML = \"\\n <div class=\\\"py-2 px-3\\\">\\n <div class=\\\"d-flex justify-content-between mb-2 align-items-center\\\">\\n <h4 class=\\\"form-label fw-semibold mb-0\\\">\".concat(this.label, \"</h4>\\n <div class=\\\"d-flex align-items-center gap-2 ms-3\\\">\\n <span class=\\\"form-label mb-0\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.fixed'), \"</span>\\n <div class=\\\"ms-auto\\\">\\n <input type=\\\"checkbox\\\" class=\\\"builder-checkbox-modern\\\" id=\\\"toggle_\").concat(this.id, \"\\\" \").concat(this.isAuto ? 'checked' : '', \" />\\n <label class=\\\"toggle-label\\\" for=\\\"toggle_\").concat(this.id, \"\\\"></label>\\n </div>\\n <span class=\\\"form-label mb-0\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.auto'), \"</span>\\n </div>\\n </div>\\n <div class=\\\"d-flex justify-content-between align-items-center mb-0 pe-1 me-3\\\">\\n <p class=\\\"mb-0 me-2\\\">\").concat(this.min).concat(this.unit, \"</p>\\n <p class=\\\"mb-0 pe-2 me-4\\\">\").concat(this.max).concat(this.unit, \"</p>\\n </div>\\n <div class=\\\"d-flex\\\">\\n <div class=\\\"flex-grow-1\\\">\\n <input type=\\\"range\\\" min=\\\"\").concat(this.min, \"\\\" max=\\\"\").concat(this.max, \"\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-range slider w-100\\\" id=\\\"\").concat(this.id, \"_slider\\\" \").concat(this.isAuto ? 'disabled' : '', \">\\n </div>\\n <div style=\\\"min-width: 50px; text-align: right;\\\">\\n <label for=\\\"\").concat(this.id, \"_slider\\\" class=\\\"form-label ms-2 mb-0\\\">\").concat(this.isAuto ? 'auto' : this.value + this.unit, \"</label>\\n </div>\\n </div>\\n </div>\");\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n // Method to set value programmatically\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n var isAuto = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.isAuto;\n this.value = newValue;\n this.isAuto = isAuto;\n this.render();\n this.setupEventListeners();\n if (this.callback && typeof this.callback.setValue === \"function\") {\n this.callback.setValue(this.value, this.isAuto);\n }\n }\n }, {\n key: \"setupEventListeners\",\n value: function setupEventListeners() {\n var _this = this;\n var rangeInput = this.domNode.querySelector(\"input[type=\\\"range\\\"]\");\n var valueLabel = this.domNode.querySelector(\"label[for=\\\"\".concat(this.id, \"_slider\\\"]\"));\n var autoSwitch = this.domNode.querySelector(\"#toggle_\".concat(this.id));\n\n // Debounce variables\n var debounceTimeout = null;\n var debounceDelay = 50; // milliseconds\n\n if (rangeInput) {\n rangeInput.addEventListener(\"input\", function (event) {\n _this.value = event.target.value;\n if (valueLabel && !_this.isAuto) {\n valueLabel.textContent = \"\".concat(_this.value).concat(_this.unit);\n }\n\n // Debounce the callback\n if (debounceTimeout) clearTimeout(debounceTimeout);\n debounceTimeout = setTimeout(function () {\n if (_this.callback && typeof _this.callback.setValue === \"function\") {\n _this.callback.setValue(_this.value, _this.isAuto);\n }\n }, debounceDelay);\n });\n }\n if (autoSwitch) {\n autoSwitch.addEventListener(\"change\", function (event) {\n _this.isAuto = event.target.checked;\n _this.render();\n _this.setupEventListeners();\n if (_this.callback && typeof _this.callback.setValue === \"function\") {\n _this.callback.setValue(_this.value, _this.isAuto);\n }\n });\n }\n }\n\n // Method to get current value\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CustomRangeControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CustomRangeControl.js?");
/***/ }),
/***/ "./src/includes/DimensionControl.js":
/*!******************************************!*\
!*** ./src/includes/DimensionControl.js ***!
\******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseControl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseControl.js */ \"./src/includes/BaseControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n// Per-unit slider range + help text.\n// Range chosen for \"80% of real use cases\" for both email (600px-ish) AND\n// full-width web pages (up to ~1200px / Bootstrap XL). Number input accepts\n// any value beyond the slider max — slider clamps visually, value persists.\nvar UNIT_CONFIG = {\n px: {\n min: 0,\n max: 1200,\n step: 1,\n helpKey: 'dimension.help_px',\n defaultValue: 300\n },\n '%': {\n min: 0,\n max: 100,\n step: 1,\n helpKey: 'dimension.help_pct',\n defaultValue: 100\n },\n em: {\n min: 0,\n max: 20,\n step: 0.1,\n helpKey: 'dimension.help_em',\n defaultValue: 1\n },\n rem: {\n min: 0,\n max: 20,\n step: 0.1,\n helpKey: 'dimension.help_rem',\n defaultValue: 1\n },\n vw: {\n min: 0,\n max: 100,\n step: 1,\n helpKey: 'dimension.help_vw',\n defaultValue: 50\n },\n vh: {\n min: 0,\n max: 100,\n step: 1,\n helpKey: 'dimension.help_vh',\n defaultValue: 50\n },\n // `fill` — value-less unit meaning \"grow to absorb remaining row space\".\n // Used for the classic `[\"auto\", \"fill\"]` image+text layout. Slider is\n // disabled (no numeric value); serializes as `\"fill\"` (no number prefix).\n fill: {\n helpKey: 'dimension.help_fill'\n },\n auto: {\n helpKey: 'dimension.help_auto'\n }\n};\n\n// Quick-size presets per unit, shown in the dropdown menu under \"Quick size\".\n// Values cover typical web + email ranges (email column ≈ 600, page full ≈ 1200).\nvar PRESETS = {\n px: [{\n labelKey: 'dimension.preset_sm',\n value: 160\n }, {\n labelKey: 'dimension.preset_md',\n value: 400\n }, {\n labelKey: 'dimension.preset_lg',\n value: 800\n }, {\n labelKey: 'dimension.preset_full',\n value: 1200\n }],\n '%': [{\n label: '25%',\n value: 25\n }, {\n label: '50%',\n value: 50\n }, {\n label: '75%',\n value: 75\n }, {\n label: '100%',\n value: 100\n }]\n};\nvar DimensionControl = /*#__PURE__*/function (_BaseControl) {\n /**\n * @param {string} label Display label (already translated)\n * @param {*} initialOrValue One of:\n * - primitive: \"300px\" | \"50%\" | \"auto\" | null | number (legacy form)\n * - capability-token form (preferred):\n * { initial, subscribe, readState }\n * - `initial` — same shape as the primitive form\n * - `subscribe` — `(fn) => disposer` capability that\n * fires `fn()` whenever element state changes\n * (per SA I13 R3). When present, the control\n * registers a disposer + calls `syncFromExternal()`\n * on every notify.\n * - `readState` — `() => freshValue` returning the\n * current primitive form for this key (e.g.\n * `() => element.formatter.getFormat('width')`).\n * Required for observer-aware mode; without it\n * the control can't re-read state on notify.\n * @param {object} options\n * @param {string[]} options.units Subset of ['px','%','em','rem','vw','vh','auto']\n * @param {function} options.onChange Receives serialized: \"300px\" | \"50%\" | \"auto\" | null\n *\n * Embeddable in any DOM container — the `domNode` property is the root.\n * Multiple instances can coexist on the same element key (sidebar +\n * popup overlay, etc.); both subscribe and stay in sync.\n */\n function DimensionControl(label, initialOrValue) {\n var _this;\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n _classCallCheck(this, DimensionControl);\n _this = _callSuper(this, DimensionControl);\n _this.id = '_dim_' + Math.random().toString(36).substr(2, 9);\n _this.label = label;\n _this.units = options.units && options.units.length ? options.units : ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'];\n _this.onChange = typeof options.onChange === 'function' ? options.onChange : function () {};\n\n // Detect capability-token form vs legacy primitive form.\n var initial = initialOrValue;\n _this._readState = null;\n if (initialOrValue && _typeof(initialOrValue) === 'object' && (typeof initialOrValue.subscribe === 'function' || 'initial' in initialOrValue || typeof initialOrValue.readState === 'function')) {\n initial = initialOrValue.initial;\n if (typeof initialOrValue.readState === 'function') {\n _this._readState = initialOrValue.readState;\n }\n if (typeof initialOrValue.subscribe === 'function') {\n // Subscribe via capability token (SA I13 R3). Disposer auto-runs\n // in BaseControl.destroy() when sidebar rebuilds OR when popup\n // overlay tears down (popup must call control.destroy()).\n _this.addDisposer(initialOrValue.subscribe(function () {\n return _this.syncFromExternal();\n }));\n }\n }\n var parsed = _this._parse(initial);\n _this.value = parsed.value;\n _this.unit = parsed.unit;\n _this._menuOpen = false;\n _this._outsideClickHandler = null;\n _this.domNode = document.createElement('div');\n _this.domNode.classList.add('dimension-control');\n _this.render();\n _this._bindEvents();\n return _this;\n }\n\n /** Re-read state from `readState()` (supplied via capability token) and\n * patch DOM in place. Skips inputs that currently hold focus so user's\n * in-flight typing isn't clobbered (per SA I13 R4).\n *\n * Listener idempotence (per SA I13 R7) — every element.render() fires\n * this. We early-out cheaply when value+unit haven't changed. */\n _inherits(DimensionControl, _BaseControl);\n return _createClass(DimensionControl, [{\n key: \"syncFromExternal\",\n value: function syncFromExternal() {\n if (!this._readState) return; // observer mode requires readState\n if (this._destroyed) return; // disposer should have unsubscribed\n if (!this.domNode) return; // DOM gone — sidebar rebuilt or section destroyed\n var next = this._parse(this._readState());\n if (next.value === this.value && next.unit === this.unit) return;\n var unitChanged = next.unit !== this.unit;\n this.value = next.value;\n this.unit = next.unit;\n if (unitChanged) {\n // Unit change rewrites slider min/max/step + unit-button label +\n // input disabled state. Cheapest correct path is _renderAndRebind\n // (innerHTML + re-bind) since structure differs across units. The\n // sidebar instance lives in a steady-state container; rebuild here\n // doesn't trigger any sidebar-rebuild side effects.\n this._renderAndRebind();\n return;\n }\n\n // Same-unit value change — surgical patch to preserve focus/selection.\n var slider = this.domNode.querySelector('.dim-slider');\n var valueInput = this.domNode.querySelector('.dim-value');\n var sliderVal = this.value === null || isNaN(this.value) ? 0 : this.value;\n if (slider && document.activeElement !== slider) {\n slider.value = String(sliderVal);\n var cfg = this._config();\n var pct = cfg && cfg.max !== cfg.min ? (sliderVal - cfg.min) / (cfg.max - cfg.min) * 100 : 0;\n slider.style.setProperty('--pct', pct + '%');\n }\n if (valueInput && document.activeElement !== valueInput) {\n valueInput.value = this.value === null || isNaN(this.value) ? '' : String(this.value);\n }\n }\n }, {\n key: \"_parse\",\n value: function _parse(input) {\n var fallbackUnit = this.units.includes('px') ? 'px' : this.units[0];\n // Default unit for bare (unitless) numbers: prefer `%` when the caller\n // supports it. Historical reason: CellElement + GridElement storing bare\n // numbers like `50` meant-to-be \"50%\" — falling back to `px` showed\n // \"50 px\" in the panel and surprised authors (user report 2026-04-18).\n // Width-shaped DimensionControl instances include `%` in their unit set\n // → bare numbers now show as `%`. Fixed-dimension instances without `%`\n // (e.g. px-only) keep the legacy `px` fallback.\n var bareFallback = this.units.includes('%') ? '%' : this.units.includes('px') ? 'px' : this.units[0];\n if (input === null || input === undefined || input === '') {\n return {\n value: null,\n unit: fallbackUnit\n };\n }\n if (input === 'auto') {\n return {\n value: null,\n unit: this.units.includes('auto') ? 'auto' : fallbackUnit\n };\n }\n if (input === 'fill') {\n return {\n value: null,\n unit: this.units.includes('fill') ? 'fill' : fallbackUnit\n };\n }\n if (typeof input === 'number') {\n return {\n value: isNaN(input) ? null : input,\n unit: bareFallback\n };\n }\n if (typeof input === 'string') {\n var m = input.trim().match(/^(-?[\\d.]+)\\s*(px|%|em|rem|vw|vh)?$/i);\n if (m) {\n var num = parseFloat(m[1]);\n var explicitUnit = m[2] ? m[2].toLowerCase() : null;\n var unit = explicitUnit || bareFallback;\n return {\n value: isNaN(num) ? null : num,\n unit: this.units.includes(unit) ? unit : fallbackUnit\n };\n }\n }\n return {\n value: null,\n unit: fallbackUnit\n };\n }\n }, {\n key: \"_serialize\",\n value: function _serialize() {\n if (this.unit === 'auto') return 'auto';\n if (this.unit === 'fill') return 'fill';\n if (this.value === null || isNaN(this.value)) return null;\n var num = Number.isInteger(this.value) ? this.value : parseFloat(this.value.toFixed(2));\n return \"\".concat(num).concat(this.unit);\n }\n }, {\n key: \"_emit\",\n value: function _emit() {\n this.onChange(this._serialize());\n }\n }, {\n key: \"_config\",\n value: function _config() {\n return UNIT_CONFIG[this.unit] || UNIT_CONFIG.px;\n }\n }, {\n key: \"_t\",\n value: function _t(key, fallback) {\n try {\n var v = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key);\n return v && v !== key ? v : fallback;\n } catch (_e) {\n return fallback;\n }\n }\n\n /** Reset value to unset. Unit is preserved — placeholder \"auto\" appears\n * in the input to signal \"no size applied\" without changing user's pick. */\n }, {\n key: \"clear\",\n value: function clear() {\n this.value = null;\n this._closeMenu();\n this.render();\n this._bindEvents();\n this._emit();\n }\n }, {\n key: \"render\",\n value: function render() {\n var isAuto = this.unit === 'auto';\n var isFill = this.unit === 'fill';\n // `auto` + `fill` are both value-less units — slider/input are disabled\n // and a placeholder communicates the meaning.\n var isValueless = isAuto || isFill;\n var cfg = this._config();\n var presets = isValueless ? [] : PRESETS[this.unit] || [];\n var hasValue = !isValueless && this.value !== null && !isNaN(this.value);\n var placeholderText = isFill ? this._t('dimension.placeholder_fill', 'fill') : this._t('dimension.placeholder', 'auto');\n var sliderVal = hasValue ? this.value : cfg.min || 0;\n var pct = !isValueless && cfg.max !== cfg.min ? (sliderVal - cfg.min) / (cfg.max - cfg.min) * 100 : 0;\n this.domNode.innerHTML = \"\\n <div class=\\\"dim-row\\\">\\n <label class=\\\"dim-label\\\" for=\\\"\".concat(this.id, \"_slider\\\">\").concat(this.label, \"</label>\\n <div class=\\\"dim-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"dim-slider\\\" id=\\\"\").concat(this.id, \"_slider\\\"\\n min=\\\"\").concat(isValueless ? 0 : cfg.min, \"\\\"\\n max=\\\"\").concat(isValueless ? 100 : cfg.max, \"\\\"\\n step=\\\"\").concat(isValueless ? 1 : cfg.step, \"\\\"\\n value=\\\"\").concat(sliderVal, \"\\\"\\n style=\\\"--pct: \").concat(pct, \"%\\\"\\n \").concat(isValueless ? 'disabled' : '', \">\\n </div>\\n <input type=\\\"number\\\" class=\\\"dim-value\\\"\\n value=\\\"\").concat(isValueless ? '' : hasValue ? this.value : '', \"\\\"\\n placeholder=\\\"\").concat(placeholderText, \"\\\"\\n step=\\\"\").concat(cfg.step || 1, \"\\\"\\n min=\\\"0\\\"\\n \").concat(isValueless ? 'disabled' : '', \">\\n <button type=\\\"button\\\" class=\\\"dim-menu-btn\\\" aria-haspopup=\\\"true\\\" aria-expanded=\\\"\").concat(this._menuOpen, \"\\\">\\n <span class=\\\"dim-menu-btn-unit\\\">\").concat(this.unit, \"</span>\\n <span class=\\\"dim-menu-btn-caret\\\" aria-hidden=\\\"true\\\">\\u25BE</span>\\n </button>\\n </div>\\n \");\n }\n\n /** Build the popover menu element (portaled to document.body on open). */\n }, {\n key: \"_buildMenu\",\n value: function _buildMenu() {\n var _this2 = this;\n var isValueless = this.unit === 'auto' || this.unit === 'fill';\n var presets = isValueless ? [] : PRESETS[this.unit] || [];\n var hasValue = !isValueless && this.value !== null && !isNaN(this.value);\n var menuUnits = this.units.map(function (u) {\n var isActive = u === _this2.unit;\n return \"<button type=\\\"button\\\" class=\\\"dim-menu-item \".concat(isActive ? 'is-active' : '', \"\\\" data-kind=\\\"unit\\\" data-value=\\\"\").concat(u, \"\\\" role=\\\"menuitemradio\\\" aria-checked=\\\"\").concat(isActive, \"\\\">\").concat(u, \"</button>\");\n }).join('');\n var menuPresets = presets.map(function (p) {\n var label = p.label || _this2._t(p.labelKey, p.labelKey.split('.').pop());\n return \"<button type=\\\"button\\\" class=\\\"dim-menu-item dim-menu-item--preset\\\" data-kind=\\\"preset\\\" data-value=\\\"\".concat(p.value, \"\\\" role=\\\"menuitem\\\"><span>\").concat(label, \"</span><span class=\\\"dim-menu-item-value\\\">\").concat(p.value).concat(_this2.unit, \"</span></button>\");\n }).join('');\n var menu = document.createElement('div');\n menu.className = 'dim-menu dim-menu--portal is-open';\n menu.setAttribute('role', 'menu');\n menu.innerHTML = \"\\n <div class=\\\"dim-menu-section\\\">\\n <div class=\\\"dim-menu-heading\\\">\".concat(this._t('dimension.menu_unit', 'Unit'), \"</div>\\n <div class=\\\"dim-menu-grid\\\">\").concat(menuUnits, \"</div>\\n </div>\\n \").concat(menuPresets ? \"\\n <div class=\\\"dim-menu-section\\\">\\n <div class=\\\"dim-menu-heading\\\">\".concat(this._t('dimension.menu_quick', 'Quick size'), \"</div>\\n <div class=\\\"dim-menu-list\\\">\").concat(menuPresets, \"</div>\\n </div>\\n \") : '', \"\\n \").concat(hasValue ? \"\\n <div class=\\\"dim-menu-section dim-menu-section--foot\\\">\\n <button type=\\\"button\\\" class=\\\"dim-menu-item dim-menu-item--clear\\\" data-kind=\\\"clear\\\" role=\\\"menuitem\\\">\\n <span>\".concat(this._t('dimension.clear', 'Clear value'), \"</span>\\n </button>\\n </div>\\n \") : '', \"\\n \");\n return menu;\n }\n }, {\n key: \"_renderAndRebind\",\n value: function _renderAndRebind() {\n this._closeMenu();\n this.render();\n this._bindEvents();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this3 = this;\n var slider = this.domNode.querySelector('.dim-slider');\n var valueInput = this.domNode.querySelector('.dim-value');\n var menuBtn = this.domNode.querySelector('.dim-menu-btn');\n\n // Update the CSS --pct custom property so the track fill matches current value.\n var updateFill = function updateFill() {\n if (!slider) return;\n var cfg = _this3._config();\n var raw = parseFloat(slider.value);\n var pct = cfg.max !== cfg.min ? (raw - cfg.min) / (cfg.max - cfg.min) * 100 : 0;\n slider.style.setProperty('--pct', pct + '%');\n };\n if (slider) {\n var t = null;\n slider.addEventListener('input', function (e) {\n var _this3$value;\n var v = parseFloat(e.target.value);\n _this3.value = isNaN(v) ? null : v;\n if (valueInput) valueInput.value = (_this3$value = _this3.value) !== null && _this3$value !== void 0 ? _this3$value : '';\n updateFill();\n if (t) clearTimeout(t);\n t = setTimeout(function () {\n return _this3._emit();\n }, 50);\n });\n }\n if (valueInput) {\n var _t2 = null;\n valueInput.addEventListener('input', function (e) {\n var raw = e.target.value.trim();\n _this3.value = raw === '' ? null : Math.max(0, parseFloat(raw) || 0);\n var cfg = _this3._config();\n if (slider && _this3.value !== null) {\n var _cfg$min, _cfg$max;\n slider.value = Math.min(Math.max(_this3.value, (_cfg$min = cfg.min) !== null && _cfg$min !== void 0 ? _cfg$min : 0), (_cfg$max = cfg.max) !== null && _cfg$max !== void 0 ? _cfg$max : 1200);\n }\n updateFill();\n if (_t2) clearTimeout(_t2);\n _t2 = setTimeout(function () {\n return _this3._emit();\n }, 150);\n });\n }\n if (menuBtn) {\n menuBtn.addEventListener('click', function (e) {\n e.stopPropagation();\n _this3._toggleMenu();\n });\n }\n }\n }, {\n key: \"_toggleMenu\",\n value: function _toggleMenu() {\n if (this._menuOpen) this._closeMenu();else this._openMenu();\n }\n\n /**\n * Portal the menu to document.body with position:fixed so it escapes any\n * `overflow: hidden/auto` ancestors (the settings panel scrolls, which used\n * to clip the menu before this fix).\n */\n }, {\n key: \"_openMenu\",\n value: function _openMenu() {\n var _this4 = this;\n if (this._menuOpen) return;\n this._menuOpen = true;\n var btn = this.domNode.querySelector('.dim-menu-btn');\n if (!btn) return;\n btn.setAttribute('aria-expanded', 'true');\n\n // Build a fresh menu each open — keeps the \"Clear\" footer in sync with\n // the current hasValue state without needing a separate update pass.\n var menu = this._buildMenu();\n document.body.appendChild(menu);\n this._portalMenu = menu;\n this._positionMenu();\n menu.addEventListener('click', this._onMenuClick = function (e) {\n var item = e.target.closest('.dim-menu-item');\n if (!item) return;\n var kind = item.dataset.kind;\n if (kind === 'unit') {\n _this4._switchUnit(item.dataset.value);\n _this4._closeMenu();\n } else if (kind === 'preset') {\n _this4.value = parseFloat(item.dataset.value);\n _this4._closeMenu();\n _this4.render();\n _this4._bindEvents();\n _this4._emit();\n } else if (kind === 'clear') {\n _this4.clear();\n }\n });\n\n // Close on outside click\n this._onOutsideDown = function (e) {\n if (menu.contains(e.target)) return;\n if (btn.contains(e.target)) return;\n _this4._closeMenu();\n };\n // Close on scroll / resize (menu position goes stale)\n this._onReflow = function () {\n return _this4._closeMenu();\n };\n setTimeout(function () {\n document.addEventListener('mousedown', _this4._onOutsideDown, true);\n window.addEventListener('scroll', _this4._onReflow, true);\n window.addEventListener('resize', _this4._onReflow, true);\n }, 0);\n }\n }, {\n key: \"_positionMenu\",\n value: function _positionMenu() {\n if (!this._portalMenu) return;\n var btn = this.domNode.querySelector('.dim-menu-btn');\n if (!btn) return;\n var rect = btn.getBoundingClientRect();\n // Measure menu after insertion so we can flip up if no room below.\n var menu = this._portalMenu;\n menu.style.visibility = 'hidden';\n menu.style.left = '0px';\n menu.style.top = '0px';\n var mw = menu.offsetWidth;\n var mh = menu.offsetHeight;\n var vw = window.innerWidth;\n var vh = window.innerHeight;\n var left = rect.right - mw; // right-align to button\n if (left < 8) left = 8; // keep on-screen\n if (left + mw > vw - 8) left = vw - mw - 8;\n var top = rect.bottom + 4;\n if (top + mh > vh - 8) {\n // Flip above the button\n top = rect.top - mh - 4;\n if (top < 8) top = 8;\n }\n menu.style.left = \"\".concat(Math.round(left), \"px\");\n menu.style.top = \"\".concat(Math.round(top), \"px\");\n menu.style.visibility = 'visible';\n }\n }, {\n key: \"_closeMenu\",\n value: function _closeMenu() {\n this._menuOpen = false;\n var btn = this.domNode.querySelector('.dim-menu-btn');\n if (btn) btn.setAttribute('aria-expanded', 'false');\n if (this._portalMenu) {\n if (this._onMenuClick) this._portalMenu.removeEventListener('click', this._onMenuClick);\n this._portalMenu.remove();\n this._portalMenu = null;\n }\n if (this._onOutsideDown) {\n document.removeEventListener('mousedown', this._onOutsideDown, true);\n this._onOutsideDown = null;\n }\n if (this._onReflow) {\n window.removeEventListener('scroll', this._onReflow, true);\n window.removeEventListener('resize', this._onReflow, true);\n this._onReflow = null;\n }\n }\n }, {\n key: \"_switchUnit\",\n value: function _switchUnit(newUnit) {\n var prev = this.unit;\n this.unit = newUnit;\n if (newUnit === 'auto' || newUnit === 'fill') {\n this.value = null;\n } else if (prev === 'auto' || prev === 'fill' || this.value === null || isNaN(this.value)) {\n var _UNIT_CONFIG$newUnit$;\n this.value = (_UNIT_CONFIG$newUnit$ = UNIT_CONFIG[newUnit].defaultValue) !== null && _UNIT_CONFIG$newUnit$ !== void 0 ? _UNIT_CONFIG$newUnit$ : UNIT_CONFIG[newUnit].min;\n } else {\n var cfg = UNIT_CONFIG[newUnit];\n this.value = Math.max(cfg.min, Math.min(this.value, cfg.max));\n }\n this.render();\n this._bindEvents();\n this._emit();\n }\n }]);\n}(_BaseControl_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DimensionControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/DimensionControl.js?");
/***/ }),
/***/ "./src/includes/DividerElement.js":
/*!****************************************!*\
!*** ./src/includes/DividerElement.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _DividerStyleControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./DividerStyleControl.js */ \"./src/includes/DividerStyleControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\nvar DividerElement = /*#__PURE__*/function (_BaseElement) {\n function DividerElement(template) {\n var _this;\n _classCallCheck(this, DividerElement);\n _this = _callSuper(this, DividerElement); // Call the parent class constructor\n _this.template = template;\n _this.domNode = null;\n\n // Formatter\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n background_color: '#333333',\n height: 2,\n // structured style (solid|dashed|dotted|double|none) for border-top render\n divider_style: 'solid',\n // padding\n padding_top: 10,\n padding_right: null,\n padding_bottom: 10,\n padding_left: null\n });\n return _this;\n }\n _inherits(DividerElement, _BaseElement);\n return _createClass(DividerElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.divider');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({});\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread({}, _superPropGet(DividerElement, \"getData\", this, 3)([]));\n }\n }, {\n key: \"isAutoFormat\",\n value: function isAutoFormat(key) {\n return this.formatter.getFormat(key) === \"auto\";\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this;\n return [new _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.height'), this.formatter.getFormat('height'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('height', value);\n _this2.render();\n }\n }, {\n defaultValue: 1,\n minValue: 0,\n maxValue: 500,\n suffix: 'px',\n allowZero: false\n }),\n // W3.8b — PaddingMarginControl removed. Padding is a\n // container-only concern (Block/Cell/Page).\n // Divider style control (solid / dashed / dotted / double / none)\n new _DividerStyleControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.divider_style'), this.formatter.getFormat('divider_style', 'solid'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('divider_style', value);\n _this2.render();\n }\n }, ['solid', 'dashed', 'dotted', 'double']),\n // Divider colour — the template renders `background_color` as the\n // border-top colour for every divider_style. Without this control\n // users can't edit a colour set by the template (missing-control\n // bug surfaced by InternationalWomensDay sample, 2026-04-16).\n new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.color'), this.formatter.getFormat('background_color'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('background_color', value);\n _this2.render();\n }\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DividerElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/DividerElement.js?");
/***/ }),
/***/ "./src/includes/DividerStyleControl.js":
/*!*********************************************!*\
!*** ./src/includes/DividerStyleControl.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar DividerStyleControl = /*#__PURE__*/function () {\n function DividerStyleControl(label, value, callback) {\n var possibleValues = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ['solid', 'dashed', 'dotted', 'double'];\n _classCallCheck(this, DividerStyleControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = value;\n this.callback = callback;\n var iconMap = {\n solid: 'horizontal_rule',\n dashed: 'unknown_med',\n dotted: 'more_horiz',\n \"double\": 'equal'\n };\n this.options = possibleValues.map(function (val) {\n return {\n icon: iconMap[val] || 'horizontal_rule',\n value: val\n };\n });\n this.domNode = document.createElement(\"div\");\n this.render();\n }\n return _createClass(DividerStyleControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var buttons = this.options.map(function (option) {\n var isActive = _this.value === option.value;\n return \"\\n <button type=\\\"button\\\"\\n class=\\\"bjs-segmented-btn\".concat(isActive ? ' is-active' : '', \"\\\"\\n role=\\\"radio\\\"\\n aria-checked=\\\"\").concat(isActive, \"\\\"\\n data-value=\\\"\").concat(option.value, \"\\\"\\n data-tooltip=\\\"\").concat(option.value, \"\\\"\\n aria-label=\\\"\").concat(option.value, \"\\\"\\n tabindex=\\\"\").concat(isActive ? '0' : '-1', \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\").concat(option.icon, \"</span>\\n </button>\\n \");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\"><span>\".concat(this.label, \"</span></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-segmented\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(this.label, \"\\\" style=\\\"width: 180px;\\\">\\n \").concat(buttons, \"\\n </div>\\n </div>\\n </div>\\n \");\n this._bindEvents();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this2 = this;\n var group = this.domNode.querySelector('.bjs-segmented');\n if (!group) return;\n group.addEventListener('click', function (e) {\n var btn = e.target.closest('.bjs-segmented-btn');\n if (!btn || !group.contains(btn)) return;\n _this2._selectValue(btn.dataset.value, {\n focus: true\n });\n });\n group.addEventListener('keydown', function (e) {\n if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) return;\n e.preventDefault();\n var buttons = Array.from(group.querySelectorAll('.bjs-segmented-btn'));\n var currentIndex = buttons.findIndex(function (b) {\n return b.classList.contains('is-active');\n });\n var nextIndex = currentIndex;\n if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n nextIndex = (currentIndex - 1 + buttons.length) % buttons.length;\n } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n nextIndex = (currentIndex + 1) % buttons.length;\n } else if (e.key === 'Home') {\n nextIndex = 0;\n } else if (e.key === 'End') {\n nextIndex = buttons.length - 1;\n }\n var nextBtn = buttons[nextIndex];\n if (nextBtn) _this2._selectValue(nextBtn.dataset.value, {\n focus: true\n });\n });\n }\n }, {\n key: \"_selectValue\",\n value: function _selectValue(value) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$focus = _ref.focus,\n focus = _ref$focus === void 0 ? false : _ref$focus;\n if (value === this.value) return;\n this.value = value;\n this._updateActiveState();\n if (focus) {\n var active = this.domNode.querySelector('.bjs-segmented-btn.is-active');\n if (active) active.focus();\n }\n if (typeof this.callback === 'function') {\n this.callback(this.value);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(this.value);\n }\n }\n }, {\n key: \"_updateActiveState\",\n value: function _updateActiveState() {\n var _this3 = this;\n this.domNode.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n var isActive = btn.dataset.value === _this3.value;\n btn.classList.toggle('is-active', isActive);\n btn.setAttribute('aria-checked', String(isActive));\n btn.setAttribute('tabindex', isActive ? '0' : '-1');\n });\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n if (newValue === this.value) return;\n this.value = newValue;\n this._updateActiveState();\n if (typeof this.callback === 'function') {\n this.callback(this.value);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(this.value);\n }\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DividerStyleControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/DividerStyleControl.js?");
/***/ }),
/***/ "./src/includes/DividerWidget.js":
/*!***************************************!*\
!*** ./src/includes/DividerWidget.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _DividerElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./DividerElement.js */ \"./src/includes/DividerElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar DividerWidget = /*#__PURE__*/function (_BaseWidget) {\n function DividerWidget() {\n var _this;\n _classCallCheck(this, DividerWidget);\n _this = _callSuper(this, DividerWidget); // Call the parent class constructor\n\n // New element for Divider\n var divider = new _DividerElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Divider');\n\n // Append the new element to the block\n _this.block.appendElements([divider]);\n return _this;\n }\n _inherits(DividerWidget, _BaseWidget);\n return _createClass(DividerWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.divider');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'border_horizontal';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DividerWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/DividerWidget.js?");
/***/ }),
/***/ "./src/includes/DropdownControl.js":
/*!*****************************************!*\
!*** ./src/includes/DropdownControl.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * DropdownControl — labeled value picker emitting `.bjs-select` primitive\n * (see builder.css §9 + ui-showcase #9).\n *\n * 2026-04-18 audit (§2.11): migrated from `.form-select` + hardcoded 140×32\n * inline styles + `builder-select-container` pad wrapper to `.bjs-control-\n * row` + `.bjs-select` (token-driven, dark-mode safe, consistent with the\n * rest of the panel). Consumers: CellElement (×4: display, flex-direction,\n * justify, align-items), PageElement. Both auto-upgrade — signature kept.\n *\n * Failure-state audit: options are validated against the provided `options`\n * array; if the incoming `value` doesn't match, the control still renders\n * the first option but surfaces a `.bjs-link-error` row with the stale\n * value so the user knows a legacy setting was migrated.\n */\nvar DropdownControl = /*#__PURE__*/function () {\n /**\n * @param {string} label\n * @param {string} value Current value\n * @param {Array<{label: string, value: string}>} options\n * @param {function} callback Receives the new value string on change\n */\n function DropdownControl(label, value, options, callback) {\n var _this = this;\n _classCallCheck(this, DropdownControl);\n this.id = '_ddl_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = value;\n this.options = Array.isArray(options) ? options : [];\n this.callback = callback;\n this.invalidValue = this.value !== null && this.value !== undefined && this.value !== '' && !this.options.some(function (o) {\n return String(o.value) === String(_this.value);\n }) ? this.value : null;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('dropdown-control');\n this.render();\n this._bindEvents();\n }\n return _createClass(DropdownControl, [{\n key: \"render\",\n value: function render() {\n var _this2 = this;\n var optsHtml = this.options.map(function (opt) {\n var selected = String(_this2.value) === String(opt.value) ? ' selected' : '';\n return \"<option value=\\\"\".concat(opt.value, \"\\\"\").concat(selected, \">\").concat(opt.label, \"</option>\");\n }).join('');\n var errorLine = this.invalidValue ? \"<span class=\\\"bjs-link-error\\\" role=\\\"status\\\">Unknown value \\\"\".concat(String(this.invalidValue).replace(/\"/g, '"'), \"\\\" \\u2014 migrated to default.</span>\") : '';\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <span>\".concat(this.label, \"</span>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-select\\\">\\n <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"\\\">\").concat(optsHtml, \"</select>\\n <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n </div>\\n </div>\\n </div>\\n \").concat(errorLine, \"\\n \");\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this3 = this;\n var sel = this.domNode.querySelector(\"#\".concat(this.id));\n if (!sel) return;\n sel.addEventListener('change', function (e) {\n _this3.value = e.target.value;\n var hadError = !!_this3.invalidValue;\n _this3.invalidValue = null;\n if (hadError) {\n _this3.render();\n _this3._bindEvents();\n }\n if (typeof _this3.callback === 'function') _this3.callback(_this3.value);\n });\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.value = newValue;\n var sel = this.domNode.querySelector(\"#\".concat(this.id));\n if (sel) sel.value = newValue;\n if (typeof this.callback === 'function') this.callback(this.value);\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DropdownControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/DropdownControl.js?");
/***/ }),
/***/ "./src/includes/ElementFactory.js":
/*!****************************************!*\
!*** ./src/includes/ElementFactory.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ELEMENT_REGISTRY: () => (/* binding */ ELEMENT_REGISTRY),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n// Element registry. Mutable `Map` (post-CD-1, AIBuilder Wave 1 / 2026-05-04) so\n// host apps can register new element types via `Builder.registerElement(name, klass)`\n// without forking BuilderJS. Key = JSON `name` (used in saved templates); value =\n// constructor name on `window`. The constructor itself is resolved at lookup time\n// so subclasses can replace a prior registration. Stock elements are seeded below;\n// custom registrations append to the same Map.\n//\n// See `docs/core/USAGE.md` → \"Registering custom elements (CD-1)\" and\n// `docs/core/ELEMENT_DEFINITION.md` → \"Registering a new Element class (CD-1)\".\nvar ELEMENT_REGISTRY = new Map([['AlertElement', 'AlertElement'], ['BlockElement', 'BlockElement'], ['ButtonElement', 'ButtonElement'], ['CheckboxElement', 'CheckboxElement'], ['CellElement', 'CellElement'], ['CheckoutElement', 'CheckoutElement'], ['CheckoutSimpleElement', 'CheckoutSimpleElement'], ['DividerElement', 'DividerElement'], ['FieldElement', 'FieldElement'], ['FormContainerCell', 'FormContainerCell'], ['GridElement', 'GridElement'], ['H1Element', 'H1Element'], ['H2Element', 'H2Element'], ['H3Element', 'H3Element'], ['H4Element', 'H4Element'], ['H5Element', 'H5Element'], ['HeadingElement', 'HeadingElement'], ['HTMLElement', 'HTMLElement'], ['ImageElement', 'ImageElement'], ['LabelElement', 'LabelElement'], ['LinkElement', 'LinkElement'], ['ListElement', 'ListElement'], ['MenuElement', 'MenuElement'], ['PElement', 'PElement'], ['PageElement', 'PageElement'], ['PricingCardsElement', 'PricingCardsElement'], ['PricingCardElement', 'PricingCardElement'], ['RadioElement', 'RadioElement'], ['RSSElement', 'RSSElement'], ['SelectElement', 'SelectElement'], ['SocialIconsElement', 'SocialIconsElement'], ['SubmitButtonElement', 'SubmitButtonElement'], ['TermsOfServiceElement', 'TermsOfServiceElement'], ['TextInputElement', 'TextInputElement'], ['VideoElement', 'VideoElement'], ['YoutubeElement', 'YoutubeElement']]);\nvar ElementFactory = /*#__PURE__*/function () {\n function ElementFactory() {\n _classCallCheck(this, ElementFactory);\n }\n return _createClass(ElementFactory, null, [{\n key: \"getElementClass\",\n value: function getElementClass(name) {\n var constructorName = ELEMENT_REGISTRY.get(name);\n if (!constructorName) {\n throw new Error(\"Unknown element name: \".concat(name));\n }\n var elementClass = window[constructorName];\n if (!elementClass || typeof elementClass.parse !== 'function') {\n throw new Error(\"ElementFactory registry entry \\\"\".concat(constructorName, \"\\\" is not available at runtime.\"));\n }\n return elementClass;\n }\n }, {\n key: \"createElement\",\n value: function createElement(data) {\n if (!data || _typeof(data) !== 'object') {\n throw new Error('ElementFactory.createElement requires a data object.');\n }\n var elementClass = ElementFactory.getElementClass(data.name);\n return elementClass.parse(data);\n }\n }]);\n}();\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ElementFactory);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ElementFactory.js?");
/***/ }),
/***/ "./src/includes/EventEmitter.js":
/*!**************************************!*\
!*** ./src/includes/EventEmitter.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * EventEmitter — generic pub/sub primitive used by every Builder instance via\n * `builder.events`. Started life as `CanvasHighlightBus` (W0.1 control↔overlay\n * signalling); generalised in CD-3 (AIBuilder Wave 4) so host apps can drive\n * autosave, dirty-state tickers, and any other change-driven UX off the same\n * bus the History system + region-focus system already publish on.\n *\n * Design choices:\n * - Map<event, Set<fn>>: fast add/remove, stable iteration order.\n * - `on()` returns a disposer so subscribers can match the Phase 1.8\n * Control-disposer pattern (BaseControl.addDisposer).\n * - Listener throws caught via BJS.error so one bad subscriber cannot break\n * the dispatch loop — same guarantee as BaseElement.notifySyncListeners\n * (SA I15).\n * - Iterate over a snapshot (Array.from) so a listener that unsubscribes\n * itself during dispatch does not skip its sibling.\n * - Per-event debounce config (CD-3): pass `{ debounce: { 'foo': 120 } }` to\n * the constructor; emits to those events coalesce timers, with the LAST\n * payload winning. `flushPending(name)` synchronously fires any pending\n * debounced emit for that name (host calls this in Cmd-S handlers so the\n * pending autosave's debounce doesn't race the manual save's PUT).\n *\n * Canonical events — see `docs/core/USAGE.md` \"Event bus (CD-3)\" for the\n * authoritative table. Adding a new event = update Builder.EVENTS + the\n * canonical-events table + R-bjs-docs in one commit. Drift = bug (RULE E).\n */\nvar EventEmitter = /*#__PURE__*/function () {\n /**\n * @param {Object} [options]\n * @param {Object<string, number>} [options.debounce] event-name → debounce ms.\n */\n function EventEmitter() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _classCallCheck(this, EventEmitter);\n this._listeners = new Map();\n this._debounce = new Map();\n this._pending = new Map(); // name → { timerId, payload }\n\n var debounceCfg = options && options.debounce || {};\n for (var _i = 0, _Object$entries = Object.entries(debounceCfg); _i < _Object$entries.length; _i++) {\n var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),\n event = _Object$entries$_i[0],\n ms = _Object$entries$_i[1];\n if (typeof ms === 'number' && ms > 0) {\n this._debounce.set(event, ms);\n }\n }\n }\n\n /**\n * Subscribe to an event. Returns a disposer function — call it to\n * unsubscribe. Safe to call the disposer multiple times.\n */\n return _createClass(EventEmitter, [{\n key: \"on\",\n value: function on(event, fn) {\n var _this = this;\n if (typeof event !== 'string' || !event) {\n throw new Error('EventEmitter.on: event must be a non-empty string');\n }\n if (typeof fn !== 'function') {\n throw new Error('EventEmitter.on: fn must be a function');\n }\n var set = this._listeners.get(event);\n if (!set) {\n set = new Set();\n this._listeners.set(event, set);\n }\n set.add(fn);\n return function () {\n return _this.off(event, fn);\n };\n }\n\n /** Explicit unsubscribe. Idempotent. */\n }, {\n key: \"off\",\n value: function off(event, fn) {\n var set = this._listeners.get(event);\n if (!set) return;\n set[\"delete\"](fn);\n if (set.size === 0) this._listeners[\"delete\"](event);\n }\n\n /**\n * Dispatch an event. If the event has a configured debounce window, the\n * call coalesces — only the LAST payload within the window fires when the\n * timer expires. Otherwise dispatch is synchronous.\n */\n }, {\n key: \"emit\",\n value: function emit(event, payload) {\n if (this._debounce.has(event)) {\n this._scheduleDebounced(event, payload);\n return;\n }\n this._dispatch(event, payload);\n }\n\n /**\n * Synchronously fire any pending debounced emit for `event` and cancel\n * the timer. No-op if nothing is pending. Use case: a host whose UX needs\n * a deterministic \"no debounce in flight after this returns\" guarantee\n * (e.g. Cmd-S consuming the pending document:changed before issuing PUT).\n */\n }, {\n key: \"flushPending\",\n value: function flushPending(event) {\n var pending = this._pending.get(event);\n if (!pending) return;\n clearTimeout(pending.timerId);\n this._pending[\"delete\"](event);\n this._dispatch(event, pending.payload);\n }\n\n /** Cancel pending debounced emits + drop every listener. Tests + teardown. */\n }, {\n key: \"clear\",\n value: function clear() {\n var _iterator = _createForOfIteratorHelper(this._pending.values()),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var timerId = _step.value.timerId;\n clearTimeout(timerId);\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n this._pending.clear();\n this._listeners.clear();\n }\n\n /** Debug / test helper — how many listeners for `event`. */\n }, {\n key: \"listenerCount\",\n value: function listenerCount(event) {\n var set = this._listeners.get(event);\n return set ? set.size : 0;\n }\n\n /** Debug / test helper — true when a debounced emit is queued for `event`. */\n }, {\n key: \"hasPending\",\n value: function hasPending(event) {\n return this._pending.has(event);\n }\n }, {\n key: \"_scheduleDebounced\",\n value: function _scheduleDebounced(event, payload) {\n var _this2 = this;\n var ms = this._debounce.get(event);\n var existing = this._pending.get(event);\n if (existing) clearTimeout(existing.timerId);\n var timerId = setTimeout(function () {\n _this2._pending[\"delete\"](event);\n _this2._dispatch(event, payload);\n }, ms);\n this._pending.set(event, {\n timerId: timerId,\n payload: payload\n });\n }\n }, {\n key: \"_dispatch\",\n value: function _dispatch(event, payload) {\n var set = this._listeners.get(event);\n if (!set || set.size === 0) return;\n for (var _i2 = 0, _Array$from = Array.from(set); _i2 < _Array$from.length; _i2++) {\n var fn = _Array$from[_i2];\n try {\n fn(payload);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error(\"event-bus:listener \\\"\".concat(event, \"\\\"\"), err);\n }\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (EventEmitter);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/EventEmitter.js?");
/***/ }),
/***/ "./src/includes/FieldConfigControl.js":
/*!********************************************!*\
!*** ./src/includes/FieldConfigControl.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * FieldConfigControl — flat panel for FieldElement.\n *\n * Bundles every field-shaping knob (visibility of label + content of label,\n * placeholder, default value, required flag + indicator + custom messages)\n * into one panel. No panel chrome — rows align with sibling sidebar\n * primitives at the natural sidebar inset.\n *\n * Conditional UI (`_syncConditionalRows`):\n * • field-label row — hidden when `showLabel === false`\n * • placeholder row — hidden for `date|datetime|checkbox|radio`\n * (those input types don't render a placeholder)\n * • required toggle — disabled when `requiredEditable === false`\n * • locked-hint banner — visible only when `requiredEditable === false &&\n * requiredEditableHint` is non-empty\n * • indicator picker — hidden when `!showLabel || !required`\n * • msg-required row — hidden when `required === false`\n * • msg-email row — visible only when `fieldType === 'email'`\n *\n * Toggle visibility via `is-hidden` class — DO NOT remove rows from DOM,\n * so values survive a `fieldType` / `showLabel` / `required` round-trip.\n *\n * Callback contract:\n * callback.setValues({ fieldLabel?, fieldPlaceholder?, fieldValue?,\n * required?, errorMessage?, emailErrorMessage?,\n * showLabel?, requiredIndicator? })\n * The element merges + re-renders; only present keys are applied.\n * `requiredEditable` / `requiredEditableHint` are host-provided\n * read-only flags — the panel never emits them back.\n */\nvar FieldConfigControl = /*#__PURE__*/function () {\n function FieldConfigControl(label, value, callback) {\n _classCallCheck(this, FieldConfigControl);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = {\n fieldType: value && typeof value.fieldType === 'string' ? value.fieldType : 'text',\n fieldLabel: value && value.fieldLabel != null ? String(value.fieldLabel) : '',\n fieldPlaceholder: value && value.fieldPlaceholder != null ? String(value.fieldPlaceholder) : '',\n fieldValue: value && value.fieldValue != null ? String(value.fieldValue) : '',\n required: !!(value && value.required),\n errorMessage: value && typeof value.errorMessage === 'string' ? value.errorMessage : '',\n emailErrorMessage: value && typeof value.emailErrorMessage === 'string' ? value.emailErrorMessage : '',\n showLabel: value && value.showLabel === undefined ? true : !!(value && value.showLabel),\n requiredIndicator: value && typeof value.requiredIndicator === 'string' ? value.requiredIndicator : '',\n requiredEditable: value && value.requiredEditable === undefined ? true : !!(value && value.requiredEditable),\n requiredEditableHint: value && typeof value.requiredEditableHint === 'string' ? value.requiredEditableHint : '',\n requiredEditableHintActionText: value && typeof value.requiredEditableHintActionText === 'string' ? value.requiredEditableHintActionText : '',\n requiredEditableHintActionUrl: value && typeof value.requiredEditableHintActionUrl === 'string' ? value.requiredEditableHintActionUrl : ''\n };\n this.callback = callback;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-field-config-control');\n\n // Per-input debounce handles. Distinct timers so a fast typist\n // alternating between fields doesn't cancel each other's commits.\n this._labelDebounce = null;\n this._placeholderDebounce = null;\n this._valueDebounce = null;\n this._errorDebounce = null;\n this._emailErrorDebounce = null;\n this._indicatorDebounce = null;\n this.render();\n }\n return _createClass(FieldConfigControl, [{\n key: \"render\",\n value: function render() {\n var _this$value$fieldLabe, _this$value$fieldPlac, _this$value$fieldValu, _this$value$requiredI, _this$value$errorMess, _this$value$emailErro;\n var escapeAttr = function escapeAttr(s) {\n return String(s == null ? '' : s).replace(/\"/g, '"');\n };\n var escapeText = function escapeText(s) {\n return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n };\n\n // Indicator preset chips. Labels come from i18n; the `text` preset's\n // chip label IS the i18n string (so the chip reads \"required\" /\n // \"bắt buộc\" depending on locale).\n var presets = FieldConfigControl.INDICATOR_PRESETS;\n var presetButtons = presets.map(function (p) {\n var labelKey = \"controls.field_required_indicator_preset_\".concat(p.id);\n return \"\\n <button type=\\\"button\\\"\\n class=\\\"bjs-segmented-btn\\\"\\n data-preset=\\\"\".concat(escapeAttr(p.id), \"\\\"\\n role=\\\"radio\\\"\\n aria-checked=\\\"false\\\"\\n tabindex=\\\"-1\\\">\\n \").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey)), \"\\n </button>\\n \");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-stack bjs-field-config-control__head\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label><span>\".concat(escapeText(this.label), \"</span></label>\\n <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_settings_help')), \"</span>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-row bjs-field-config-control__show-label-row\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"field_show_label_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_show_label')), \"</span></label>\\n <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_show_label_help')), \"</span>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <label class=\\\"bjs-toggle\\\">\\n <input id=\\\"field_show_label_\").concat(this.id, \"\\\" type=\\\"checkbox\\\" class=\\\"bjs-toggle-input\\\" />\\n <span class=\\\"bjs-toggle-track\\\"><span class=\\\"bjs-toggle-thumb\\\"></span></span>\\n </label>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-stack bjs-field-config-control__label-row\\\" data-row=\\\"field-label\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"field_label_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_label')), \"</span></label>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input id=\\\"field_label_\").concat(this.id, \"\\\" type=\\\"text\\\" class=\\\"bjs-text-input\\\" />\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-stack bjs-field-config-control__placeholder-row\\\" data-row=\\\"placeholder\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"field_placeholder_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.placeholder')), \"</span></label>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input id=\\\"field_placeholder_\").concat(this.id, \"\\\" type=\\\"text\\\" class=\\\"bjs-text-input\\\" />\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-stack bjs-field-config-control__default-row\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"field_default_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_default')), \"</span></label>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input id=\\\"field_default_\").concat(this.id, \"\\\" type=\\\"text\\\" class=\\\"bjs-text-input\\\" />\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-row bjs-field-config-control__required-row\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"field_required_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required')), \"</span></label>\\n <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_help')), \"</span>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <label class=\\\"bjs-toggle\\\">\\n <input id=\\\"field_required_\").concat(this.id, \"\\\" type=\\\"checkbox\\\" class=\\\"bjs-toggle-input\\\" />\\n <span class=\\\"bjs-toggle-track\\\"><span class=\\\"bjs-toggle-thumb\\\"></span></span>\\n </label>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-info-banner bjs-field-config-control__locked-hint\\\" data-row=\\\"required-locked-hint\\\" role=\\\"note\\\">\\n <span class=\\\"bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">\\u24D8</span>\\n <span class=\\\"bjs-info-banner-text\\\" data-slot=\\\"locked-hint-text\\\"></span>\\n </div>\\n\\n <div class=\\\"bjs-control-stack bjs-field-config-control__indicator-row\\\" data-row=\\\"required-indicator\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator')), \"</span></label>\\n <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator_help')), \"</span>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-segmented bjs-field-config-control__indicator-presets\\\" data-group=\\\"indicator-preset\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator')), \"\\\">\\n \").concat(presetButtons, \"\\n </div>\\n <input id=\\\"field_indicator_\").concat(this.id, \"\\\"\\n type=\\\"text\\\"\\n class=\\\"bjs-text-input bjs-field-config-control__indicator-input\\\"\\n data-row=\\\"indicator-custom\\\"\\n placeholder=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator_custom_placeholder')), \"\\\" />\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-stack bjs-field-config-control__msg-required-row\\\" data-row=\\\"msg-required\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"field_msg_required_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_required')), \"</span></label>\\n <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_required_help')), \"</span>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input id=\\\"field_msg_required_\").concat(this.id, \"\\\"\\n type=\\\"text\\\"\\n class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_required_placeholder')), \"\\\" />\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-stack bjs-field-config-control__msg-email-row\\\" data-row=\\\"msg-email\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"field_msg_email_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_email')), \"</span></label>\\n <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_email_help')), \"</span>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input id=\\\"field_msg_email_\").concat(this.id, \"\\\"\\n type=\\\"text\\\"\\n class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_email_placeholder')), \"\\\" />\\n </div>\\n </div>\\n\\n <p class=\\\"bjs-field-config-control__hint\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_inline_hint')), \"</p>\\n \");\n\n // Hydrate inputs from current value\n this._showLabelInput().checked = !!this.value.showLabel;\n this._labelInput().value = (_this$value$fieldLabe = this.value.fieldLabel) !== null && _this$value$fieldLabe !== void 0 ? _this$value$fieldLabe : '';\n this._placeholderInput().value = (_this$value$fieldPlac = this.value.fieldPlaceholder) !== null && _this$value$fieldPlac !== void 0 ? _this$value$fieldPlac : '';\n this._defaultInput().value = (_this$value$fieldValu = this.value.fieldValue) !== null && _this$value$fieldValu !== void 0 ? _this$value$fieldValu : '';\n this._requiredInput().checked = !!this.value.required;\n this._requiredInput().disabled = !this.value.requiredEditable;\n // Match the ui-showcase disabled-toggle convention: the host\n // `<label class=\"bjs-toggle\">` carries the visual disabled state via\n // an `is-disabled` modifier (CSS dims opacity + blocks pointer events).\n var requiredToggleLabel = this._requiredInput().closest('.bjs-toggle');\n if (requiredToggleLabel) requiredToggleLabel.classList.toggle('is-disabled', !this.value.requiredEditable);\n this._indicatorInput().value = (_this$value$requiredI = this.value.requiredIndicator) !== null && _this$value$requiredI !== void 0 ? _this$value$requiredI : '';\n this._errorInput().value = (_this$value$errorMess = this.value.errorMessage) !== null && _this$value$errorMess !== void 0 ? _this$value$errorMess : '';\n this._emailErrorInput().value = (_this$value$emailErro = this.value.emailErrorMessage) !== null && _this$value$emailErro !== void 0 ? _this$value$emailErro : '';\n\n // Locked-hint text + optional CTA link. Library never invents copy —\n // both the hint text AND the link text/url come from the host.\n // HTML-escape both, then compose the markup safely (no innerHTML\n // injection of host strings; we only inject the host strings into\n // text content / href via escape helpers).\n var hintSlot = this.domNode.querySelector('[data-slot=\"locked-hint-text\"]');\n if (hintSlot) {\n var hintHtml = escapeText(this.value.requiredEditableHint || '');\n var actionText = this.value.requiredEditableHintActionText;\n var actionUrl = this.value.requiredEditableHintActionUrl;\n if (actionText && actionUrl) {\n hintSlot.innerHTML = hintHtml + ' <a href=\"' + escapeAttr(actionUrl) + '\"' + ' target=\"_blank\" rel=\"noopener noreferrer\"' + ' class=\"bjs-field-config-control__locked-hint-link\">' + escapeText(actionText) + '</a>';\n } else {\n hintSlot.textContent = this.value.requiredEditableHint || '';\n }\n }\n this._syncIndicatorActive();\n this._syncConditionalRows();\n this._bindEvents();\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this = this;\n // Show-label toggle — instant commit.\n this._showLabelInput().addEventListener('change', function (e) {\n _this.value.showLabel = !!e.target.checked;\n _this._syncConditionalRows();\n _this._emit({\n showLabel: _this.value.showLabel\n });\n });\n\n // Field-label input — debounced 200ms.\n this._labelInput().addEventListener('input', function () {\n if (_this._labelDebounce) clearTimeout(_this._labelDebounce);\n _this._labelDebounce = setTimeout(function () {\n _this.value.fieldLabel = _this._labelInput().value;\n _this._emit({\n fieldLabel: _this.value.fieldLabel\n });\n }, 200);\n });\n\n // Placeholder input — debounced 200ms.\n this._placeholderInput().addEventListener('input', function () {\n if (_this._placeholderDebounce) clearTimeout(_this._placeholderDebounce);\n _this._placeholderDebounce = setTimeout(function () {\n _this.value.fieldPlaceholder = _this._placeholderInput().value;\n _this._emit({\n fieldPlaceholder: _this.value.fieldPlaceholder\n });\n }, 200);\n });\n\n // Default-value input — debounced 200ms.\n this._defaultInput().addEventListener('input', function () {\n if (_this._valueDebounce) clearTimeout(_this._valueDebounce);\n _this._valueDebounce = setTimeout(function () {\n _this.value.fieldValue = _this._defaultInput().value;\n _this._emit({\n fieldValue: _this.value.fieldValue\n });\n }, 200);\n });\n\n // Required toggle — instant commit. Disabled state respects the\n // `requiredEditable` host flag; the disabled attr blocks the change\n // event already, but we double-guard so a programmatic .click()\n // doesn't sneak past.\n this._requiredInput().addEventListener('change', function (e) {\n if (!_this.value.requiredEditable) {\n e.target.checked = !!_this.value.required; // snap back\n return;\n }\n _this.value.required = !!e.target.checked;\n _this._syncConditionalRows();\n _this._emit({\n required: _this.value.required\n });\n });\n\n // Indicator preset chips\n var presetGroup = this.domNode.querySelector('.bjs-segmented[data-group=\"indicator-preset\"]');\n if (presetGroup) {\n presetGroup.addEventListener('click', function (e) {\n var btn = e.target.closest('.bjs-segmented-btn');\n if (!btn || !presetGroup.contains(btn)) return;\n _this._applyIndicatorPreset(btn.dataset.preset);\n });\n }\n\n // Indicator custom-text input — debounced 200ms. Free-typing\n // immediately switches the active chip to \"Custom\" via _syncIndicatorActive.\n this._indicatorInput().addEventListener('input', function () {\n if (_this._indicatorDebounce) clearTimeout(_this._indicatorDebounce);\n _this._indicatorDebounce = setTimeout(function () {\n _this.value.requiredIndicator = _this._indicatorInput().value;\n _this._syncIndicatorActive();\n _this._emit({\n requiredIndicator: _this.value.requiredIndicator\n });\n }, 200);\n });\n\n // Required-message input — debounced 200ms.\n this._errorInput().addEventListener('input', function () {\n if (_this._errorDebounce) clearTimeout(_this._errorDebounce);\n _this._errorDebounce = setTimeout(function () {\n _this.value.errorMessage = _this._errorInput().value;\n _this._emit({\n errorMessage: _this.value.errorMessage\n });\n }, 200);\n });\n\n // Email-format-message input — debounced 200ms.\n this._emailErrorInput().addEventListener('input', function () {\n if (_this._emailErrorDebounce) clearTimeout(_this._emailErrorDebounce);\n _this._emailErrorDebounce = setTimeout(function () {\n _this.value.emailErrorMessage = _this._emailErrorInput().value;\n _this._emit({\n emailErrorMessage: _this.value.emailErrorMessage\n });\n }, 200);\n });\n }\n }, {\n key: \"_applyIndicatorPreset\",\n value: function _applyIndicatorPreset(presetId) {\n var nextValue = this.value.requiredIndicator;\n if (presetId === 'none') nextValue = '';else if (presetId === 'star') nextValue = '★';else if (presetId === 'asterisk') nextValue = '*';else if (presetId === 'text') nextValue = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator_preset_text_value');else if (presetId === 'custom') {\n // \"Custom\" doesn't change the value — focuses the input so the\n // author can free-type. If the current value matches another\n // preset, clear it so \"Custom\" reads as a fresh slate.\n var matchedPreset = this._matchPresetId(this.value.requiredIndicator);\n if (matchedPreset && matchedPreset !== 'custom') {\n nextValue = '';\n }\n this.value.requiredIndicator = nextValue;\n this._indicatorInput().value = nextValue;\n this._indicatorInput().focus();\n this._syncIndicatorActive('custom');\n this._emit({\n requiredIndicator: nextValue\n });\n return;\n }\n this.value.requiredIndicator = nextValue;\n this._indicatorInput().value = nextValue;\n this._syncIndicatorActive(presetId);\n this._emit({\n requiredIndicator: nextValue\n });\n }\n }, {\n key: \"_matchPresetId\",\n value: function _matchPresetId(value) {\n if (value === '') return 'none';\n if (value === '★') return 'star';\n if (value === '*') return 'asterisk';\n if (value === _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator_preset_text_value')) return 'text';\n return null; // free text — Custom\n }\n }, {\n key: \"_syncIndicatorActive\",\n value: function _syncIndicatorActive() {\n var forcedId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n var group = this.domNode.querySelector('.bjs-segmented[data-group=\"indicator-preset\"]');\n if (!group) return;\n var matchId = forcedId || this._matchPresetId(this.value.requiredIndicator) || 'custom';\n group.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n var isActive = btn.dataset.preset === matchId;\n btn.classList.toggle('is-active', isActive);\n btn.setAttribute('aria-checked', isActive ? 'true' : 'false');\n btn.setAttribute('tabindex', isActive ? '0' : '-1');\n });\n\n // Custom-input visibility — only show when \"Custom\" preset is active.\n // Selecting any other preset (None/★/*/(required)) hides the input\n // since the value is already set by the preset literal.\n var customInput = this._indicatorInput();\n if (customInput) customInput.classList.toggle('is-hidden', matchId !== 'custom');\n }\n }, {\n key: \"_syncConditionalRows\",\n value: function _syncConditionalRows() {\n // field-label row — only when label is shown\n var labelRow = this.domNode.querySelector('[data-row=\"field-label\"]');\n if (labelRow) labelRow.classList.toggle('is-hidden', !this.value.showLabel);\n\n // placeholder row — only for input types that render a placeholder\n var placeholderRow = this.domNode.querySelector('[data-row=\"placeholder\"]');\n if (placeholderRow) {\n var noPlaceholder = FieldConfigControl.PLACEHOLDER_DISABLED_TYPES.includes(this.value.fieldType);\n placeholderRow.classList.toggle('is-hidden', noPlaceholder);\n }\n\n // locked-hint banner — only when locked AND host supplied a hint\n var lockedHint = this.domNode.querySelector('[data-row=\"required-locked-hint\"]');\n if (lockedHint) {\n var showLockedHint = !this.value.requiredEditable && !!this.value.requiredEditableHint;\n lockedHint.classList.toggle('is-hidden', !showLockedHint);\n }\n\n // indicator picker — only when the label IS visible AND required IS on\n var indicatorRow = this.domNode.querySelector('[data-row=\"required-indicator\"]');\n if (indicatorRow) {\n var hide = !this.value.showLabel || !this.value.required;\n indicatorRow.classList.toggle('is-hidden', hide);\n }\n\n // msg-required row — only when required is on\n var msgRequiredRow = this.domNode.querySelector('[data-row=\"msg-required\"]');\n if (msgRequiredRow) msgRequiredRow.classList.toggle('is-hidden', !this.value.required);\n\n // msg-email row — only for email type\n var msgEmailRow = this.domNode.querySelector('[data-row=\"msg-email\"]');\n if (msgEmailRow) msgEmailRow.classList.toggle('is-hidden', this.value.fieldType !== 'email');\n }\n }, {\n key: \"_emit\",\n value: function _emit(patch) {\n if (this.callback && typeof this.callback.setValues === 'function') {\n this.callback.setValues(patch);\n }\n }\n }, {\n key: \"_showLabelInput\",\n value: function _showLabelInput() {\n return this.domNode.querySelector(\"#field_show_label_\".concat(this.id));\n }\n }, {\n key: \"_labelInput\",\n value: function _labelInput() {\n return this.domNode.querySelector(\"#field_label_\".concat(this.id));\n }\n }, {\n key: \"_placeholderInput\",\n value: function _placeholderInput() {\n return this.domNode.querySelector(\"#field_placeholder_\".concat(this.id));\n }\n }, {\n key: \"_defaultInput\",\n value: function _defaultInput() {\n return this.domNode.querySelector(\"#field_default_\".concat(this.id));\n }\n }, {\n key: \"_requiredInput\",\n value: function _requiredInput() {\n return this.domNode.querySelector(\"#field_required_\".concat(this.id));\n }\n }, {\n key: \"_indicatorInput\",\n value: function _indicatorInput() {\n return this.domNode.querySelector(\"#field_indicator_\".concat(this.id));\n }\n }, {\n key: \"_errorInput\",\n value: function _errorInput() {\n return this.domNode.querySelector(\"#field_msg_required_\".concat(this.id));\n }\n }, {\n key: \"_emailErrorInput\",\n value: function _emailErrorInput() {\n return this.domNode.querySelector(\"#field_msg_email_\".concat(this.id));\n }\n }]);\n}();\n/** Field types that don't render a placeholder attribute on their input. */\n_defineProperty(FieldConfigControl, \"PLACEHOLDER_DISABLED_TYPES\", ['date', 'datetime', 'checkbox', 'radio']);\n/** Required-indicator presets. `id` is just for chip-active detection;\n * `value` is the literal that gets written into `requiredIndicator`.\n * The `text` preset reads its literal from i18n at apply-time so the\n * user's locale-aware \"required\" word lands in the saved JSON. */\n_defineProperty(FieldConfigControl, \"INDICATOR_PRESETS\", [{\n id: 'none',\n value: ''\n}, {\n id: 'star',\n value: '★'\n}, {\n id: 'asterisk',\n value: '*'\n}, {\n id: 'text',\n value: null\n},\n// resolved at apply-time via i18n\n{\n id: 'custom',\n value: null\n} // free-text — see _applyIndicatorPreset\n]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FieldConfigControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FieldConfigControl.js?");
/***/ }),
/***/ "./src/includes/FieldElement.js":
/*!**************************************!*\
!*** ./src/includes/FieldElement.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _FieldConfigControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./FieldConfigControl.js */ \"./src/includes/FieldConfigControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n/**\n * FieldElement — generic input/select/textarea/checkbox/radio renderer for\n * subscriber-list custom fields.\n *\n * Validation contract (paired with the visitor-side jQuery validate gate):\n * • `required` (bool) — emits the HTML5 `required` attribute on the input\n * so the client-side gate fires before the AJAX submit. The server-side\n * gate (e.g. the host's list-subscribe endpoint) is the safety net.\n * • `errorMessage` (string) — overrides the default required-field message\n * via `data-msg-required=\"…\"`. Empty falls through to the locale default.\n * • `emailErrorMessage` (string) — only for `fieldType === 'email'`.\n * Emits `data-msg-email=\"…\"` so format-mismatch text is independent of\n * the required-empty text.\n *\n * Label / required UX (Phase 5):\n * • `showLabel` (bool, default true) — when false, the `<label>` is omitted\n * entirely from the rendered HTML. The required indicator (which lives\n * inside the label) is also suppressed.\n * • `requiredIndicator` (string, default '') — literal text/glyph rendered\n * next to the label when `required && showLabel`. Empty = no indicator.\n * Examples: `*`, `★`, `required`, `(required)`. Library renders raw —\n * callers control content.\n * • `requiredEditable` (bool, default true) — when false, the\n * FieldConfigControl's required toggle renders as `disabled` and the\n * accompanying hint replaces the toggle's edit affordance. Lets a host\n * (whose list-field schema is the source of truth) prevent the\n * in-builder author from desyncing the flag.\n * • `requiredEditableHint` (string, default '') — caption shown beneath\n * the disabled toggle. Caller passes locale-aware copy; library never\n * defaults a string here (zero hardcoded strings — keeps BuilderJS\n * standalone).\n * • `requiredEditableHintActionText` + `requiredEditableHintActionUrl`\n * (strings, default '') — optional CTA link appended to the locked\n * hint. Both must be set for the link to render. The library\n * URL-escapes the URL into the `href` attribute and HTML-escapes the\n * text content; standalone callers passing empty values get plain\n * hint text with no link.\n *\n * Inline edit: `fieldLabel` is registered with the BaseElement inline-edit\n * framework — fixes the latent Guard A bug where the template stamped the\n * marker but the element never registered it.\n */\nvar FieldElement = /*#__PURE__*/function (_BaseElement) {\n function FieldElement(template, fieldType, fieldName, fieldValue, fieldLabel, fieldPlaceholder, fieldOptions) {\n var _this;\n var required = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;\n var errorMessage = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : '';\n var emailErrorMessage = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : '';\n var showLabel = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : true;\n var requiredIndicator = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : '';\n var requiredIndicatorColor = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : '#9b1c2e';\n var requiredEditable = arguments.length > 13 && arguments[13] !== undefined ? arguments[13] : true;\n var requiredEditableHint = arguments.length > 14 && arguments[14] !== undefined ? arguments[14] : '';\n var requiredEditableHintActionText = arguments.length > 15 && arguments[15] !== undefined ? arguments[15] : '';\n var requiredEditableHintActionUrl = arguments.length > 16 && arguments[16] !== undefined ? arguments[16] : '';\n _classCallCheck(this, FieldElement);\n _this = _callSuper(this, FieldElement);\n _this.template = template;\n _this.fieldType = fieldType;\n _this.fieldName = fieldName;\n _this.fieldValue = fieldValue;\n _this.fieldLabel = fieldLabel;\n _this.fieldPlaceholder = fieldPlaceholder;\n _this.fieldOptions = fieldOptions;\n _this.required = !!required;\n _this.errorMessage = typeof errorMessage === 'string' ? errorMessage : '';\n _this.emailErrorMessage = typeof emailErrorMessage === 'string' ? emailErrorMessage : '';\n _this.showLabel = showLabel === undefined ? true : !!showLabel;\n _this.requiredIndicator = typeof requiredIndicator === 'string' ? requiredIndicator : '';\n _this.requiredIndicatorColor = typeof requiredIndicatorColor === 'string' && requiredIndicatorColor ? requiredIndicatorColor : '#9b1c2e';\n _this.requiredEditable = requiredEditable === undefined ? true : !!requiredEditable;\n _this.requiredEditableHint = typeof requiredEditableHint === 'string' ? requiredEditableHint : '';\n _this.requiredEditableHintActionText = typeof requiredEditableHintActionText === 'string' ? requiredEditableHintActionText : '';\n _this.requiredEditableHintActionUrl = typeof requiredEditableHintActionUrl === 'string' ? requiredEditableHintActionUrl : '';\n _this.domNode = null;\n\n // Guard V — every key the template MUST receive. The new optional\n // keys (`required` / `errorMessage` / `emailErrorMessage` /\n // `showLabel` / `requiredIndicator`) are NOT listed here so legacy\n // themes that don't reference them keep parsing.\n _this.requiredTemplateKeys = ['fieldType', 'fieldName', 'fieldValue', 'fieldLabel', 'fieldPlaceholder', 'fieldOptions'];\n\n // Inline edit on the field label. MUST run AFTER `this.fieldLabel = …`\n // (Guard C: the property must exist on `this` at registration time).\n _this.registerInlineEdit('fieldLabel');\n return _this;\n }\n\n // Webpack mangling guard — registry + JSON `name` field must be stable.\n _inherits(FieldElement, _BaseElement);\n return _createClass(FieldElement, [{\n key: \"getClassName\",\n value: function getClassName() {\n return 'FieldElement';\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n this.domNode.innerHTML = this.renderTemplate({\n fieldType: this.fieldType,\n fieldName: this.fieldName,\n fieldValue: this.fieldValue,\n fieldLabel: this.fieldLabel,\n fieldPlaceholder: this.fieldPlaceholder,\n fieldOptions: this.fieldOptions,\n required: this.required,\n errorMessage: this.errorMessage,\n emailErrorMessage: this.emailErrorMessage,\n showLabel: this.showLabel,\n requiredIndicator: this.requiredIndicator,\n requiredIndicatorColor: this.requiredIndicatorColor\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n var _this$fieldOptions;\n return _objectSpread(_objectSpread({}, _superPropGet(FieldElement, \"getData\", this, 3)([])), {}, {\n fieldType: this.fieldType,\n fieldName: this.fieldName,\n fieldValue: this.fieldValue,\n fieldLabel: this.fieldLabel,\n fieldPlaceholder: this.fieldPlaceholder,\n fieldOptions: (_this$fieldOptions = this.fieldOptions) !== null && _this$fieldOptions !== void 0 ? _this$fieldOptions : [],\n required: !!this.required,\n errorMessage: this.errorMessage || '',\n emailErrorMessage: this.emailErrorMessage || '',\n showLabel: !!this.showLabel,\n requiredIndicator: this.requiredIndicator || '',\n requiredIndicatorColor: this.requiredIndicatorColor || '#9b1c2e'\n // requiredEditable + requiredEditableHint are PROVENANCE flags —\n // the host re-passes them on every construction (they describe\n // \"is this field's required-flag locked by an external schema?\").\n // Persisting them in the saved JSON would let stale lock-state\n // outlive the host's source of truth. So they're intentionally\n // omitted from getData() / parse().\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this;\n var controls = [];\n controls.push(new _FieldConfigControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_settings'), {\n fieldType: this.fieldType,\n fieldLabel: this.fieldLabel,\n fieldPlaceholder: this.fieldPlaceholder,\n fieldValue: this.fieldValue,\n required: this.required,\n errorMessage: this.errorMessage,\n emailErrorMessage: this.emailErrorMessage,\n showLabel: this.showLabel,\n requiredIndicator: this.requiredIndicator,\n requiredIndicatorColor: this.requiredIndicatorColor,\n requiredEditable: this.requiredEditable,\n requiredEditableHint: this.requiredEditableHint,\n requiredEditableHintActionText: this.requiredEditableHintActionText,\n requiredEditableHintActionUrl: this.requiredEditableHintActionUrl\n }, {\n setValues: function setValues(patch) {\n if ('fieldLabel' in patch) _this2.fieldLabel = patch.fieldLabel;\n if ('fieldPlaceholder' in patch) _this2.fieldPlaceholder = patch.fieldPlaceholder;\n if ('fieldValue' in patch) _this2.fieldValue = patch.fieldValue;\n if ('required' in patch) _this2.required = !!patch.required;\n if ('errorMessage' in patch) _this2.errorMessage = patch.errorMessage || '';\n if ('emailErrorMessage' in patch) _this2.emailErrorMessage = patch.emailErrorMessage || '';\n if ('showLabel' in patch) _this2.showLabel = !!patch.showLabel;\n if ('requiredIndicator' in patch) _this2.requiredIndicator = patch.requiredIndicator || '';\n if ('requiredIndicatorColor' in patch) _this2.requiredIndicatorColor = patch.requiredIndicatorColor || '#9b1c2e';\n _this2.render();\n }\n }));\n\n // Indicator-color picker — only meaningful when the field is\n // required, an indicator literal is set, AND the label is shown.\n // Built from the canonical `ColorPickerControl` primitive (same\n // panel chrome / popover UX as every other colour control in the\n // sidebar) instead of inventing a one-off picker. Sits as a sibling\n // control below the FieldConfigControl panel.\n if (this.required && this.requiredIndicator && this.showLabel) {\n controls.push(new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator_color'), this.requiredIndicatorColor, {\n setValue: function setValue(color) {\n _this2.requiredIndicatorColor = color || '#9b1c2e';\n _this2.render();\n }\n }));\n }\n return controls;\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n // Backwards-compat: legacy JSON pre-Phase-1 has no `required` /\n // `errorMessage` / `emailErrorMessage`; pre-Phase-5 has no\n // `showLabel` / `requiredIndicator`. Defaults preserve the\n // pre-feature visual: required gate off, label visible, no indicator.\n return new this(data.template, data.fieldType, data.fieldName, data.fieldValue, data.fieldLabel, data.fieldPlaceholder, data.fieldOptions, data.required !== undefined ? !!data.required : false, typeof data.errorMessage === 'string' ? data.errorMessage : '', typeof data.emailErrorMessage === 'string' ? data.emailErrorMessage : '', data.showLabel !== undefined ? !!data.showLabel : true, typeof data.requiredIndicator === 'string' ? data.requiredIndicator : '', typeof data.requiredIndicatorColor === 'string' && data.requiredIndicatorColor ? data.requiredIndicatorColor : '#9b1c2e'\n // requiredEditable / requiredEditableHint NOT read from data —\n // they're host-provided (see getData() comment).\n );\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FieldElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FieldElement.js?");
/***/ }),
/***/ "./src/includes/FontFamilyControl.js":
/*!*******************************************!*\
!*** ./src/includes/FontFamilyControl.js ***!
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * FontFamilyControl — sidebar + popover font-family picker.\n *\n * 2026-04-24 (W3.1) — optional 4th-arg `options = { bus, elementUid,\n * formatterKey }` adds bus subscribe/emit so this control dual-mounts\n * across sidebar AND the canvas FontPopoverOverlay. When the popover\n * writes a new font-family via `element.formatter.setFormat + emit\n * formatter:change`, every sidebar instance with matching elementUid +\n * formatterKey (and foreign `source`) silently mirrors the change —\n * UI flips, callback does NOT refire. Zero regression for legacy\n * 3-arg callers.\n */\nvar FontFamilyControl = /*#__PURE__*/function () {\n function FontFamilyControl(label, font_family, callback) {\n var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n _classCallCheck(this, FontFamilyControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.font_family = font_family || \"\";\n this.callback = callback;\n this._options = {\n bus: options.bus || null,\n elementUid: options.elementUid || null,\n formatterKey: options.formatterKey || null\n };\n this._busOff = null;\n this._busSource = 'font-family-control:' + this.id;\n this.domNode = document.createElement(\"div\");\n this.render();\n this._attachBusSubscription();\n }\n return _createClass(FontFamilyControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var fontList = [{\n name: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font.system_inherit'),\n value: \"inherit\"\n }, {\n name: \"Arial\",\n value: \"Arial, Helvetica, sans-serif\"\n }, {\n name: \"Verdana\",\n value: \"Verdana, Geneva, sans-serif\"\n }, {\n name: \"Times New Roman\",\n value: '\"Times New Roman\", Times, serif'\n }, {\n name: \"Georgia\",\n value: 'Georgia, \"Times New Roman\", serif'\n }, {\n name: \"Courier New\",\n value: '\"Courier New\", Courier, monospace'\n }, {\n name: \"Trebuchet MS\",\n value: '\"Trebuchet MS\", Helvetica, sans-serif'\n }, {\n name: \"Tahoma\",\n value: \"Tahoma, Geneva, sans-serif\"\n }, {\n name: \"Impact\",\n value: \"Impact, Charcoal, sans-serif\"\n }, {\n name: \"Inter\",\n value: '\"Inter\", system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif'\n }, {\n name: \"Roboto\",\n value: '\"Roboto\", Arial, sans-serif'\n }];\n var optionsHtml = [\"<option value=\\\"\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font.not_set'), \"</option>\")].concat(_toConsumableArray(fontList.map(function (font) {\n var selected = String(_this.font_family) === String(font.value) ? ' selected' : '';\n var escapedValue = font.value.replace(/\"/g, '"');\n var escapedStyle = font.value.replace(/\"/g, '"');\n return \"<option value=\\\"\".concat(escapedValue, \"\\\" style=\\\"font-family: \").concat(escapedStyle, \";\\\"\").concat(selected, \">\").concat(font.name, \"</option>\");\n }))).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-select\\\">\\n <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"\\\" name=\\\"font-family\\\">\").concat(optionsHtml, \"</select>\\n <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n </div>\\n </div>\\n </div>\\n \");\n this.selectEl = this.domNode.querySelector('select');\n this.selectEl.addEventListener('change', function (e) {\n var val = e.target.value;\n _this.font_family = val;\n _this._fireCallback(val);\n _this._emitBus();\n });\n }\n }, {\n key: \"_fireCallback\",\n value: function _fireCallback(val) {\n if (typeof this.callback === 'function') {\n this.callback(val);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(val);\n } else if (this.callback && typeof this.callback.setFontFamily === 'function') {\n this.callback.setFontFamily(val);\n }\n }\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$silent = _ref.silent,\n silent = _ref$silent === void 0 ? false : _ref$silent;\n this.font_family = newValue || \"\";\n if (this.selectEl) this.selectEl.value = this.font_family;\n if (silent) return;\n this._fireCallback(this.font_family);\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.font_family;\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n /** Control teardown — drops bus subscription. Called by\n * `Builder.renderElementControls` (SA I14) on sidebar rebuild. */\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this._busOff) {\n this._busOff();\n this._busOff = null;\n }\n }\n }, {\n key: \"_attachBusSubscription\",\n value: function _attachBusSubscription() {\n var _this2 = this;\n var _this$_options = this._options,\n bus = _this$_options.bus,\n elementUid = _this$_options.elementUid,\n formatterKey = _this$_options.formatterKey;\n if (!bus || !elementUid || !formatterKey) return;\n if (typeof bus.on !== 'function') return;\n this._busOff = bus.on('formatter:change', function (payload) {\n if (!payload) return;\n if (payload.elementUid !== elementUid) return;\n if (payload.key !== formatterKey) return;\n if (payload.source === _this2._busSource) return;\n _this2.setValue(payload.value, {\n silent: true\n });\n });\n }\n }, {\n key: \"_emitBus\",\n value: function _emitBus() {\n var _this$_options2 = this._options,\n bus = _this$_options2.bus,\n elementUid = _this$_options2.elementUid,\n formatterKey = _this$_options2.formatterKey;\n if (!bus || !elementUid || !formatterKey) return;\n if (typeof bus.emit !== 'function') return;\n bus.emit('formatter:change', {\n elementUid: elementUid,\n key: formatterKey,\n value: this.font_family,\n source: this._busSource\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FontFamilyControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FontFamilyControl.js?");
/***/ }),
/***/ "./src/includes/FontSizeControl.js":
/*!*****************************************!*\
!*** ./src/includes/FontSizeControl.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar FontSizeControl = /*#__PURE__*/function () {\n function FontSizeControl(label, value, callback) {\n _classCallCheck(this, FontSizeControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n // Initialize properties\n this.label = label; // Label for the text control\n this.value = value === null || value === undefined ? 16 : value; // Default to 16 if null\n this.callback = callback; // Callback function to handle input changes\n\n // Create the main container element\n this.domNode = document.createElement(\"div\");\n\n //\n this.render(); // Call the render method to create the UI\n }\n return _createClass(FontSizeControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n this.domNode.innerHTML = \"<div class=\\\"py-2 ps-3 pe-3 w-100 d-flex align-items-center justify-content-between\\\">\\n <label for=\\\"\".concat(this.id, \"\\\" class=\\\"form-label fw-semibold mb-0 me-3\\\">\").concat(this.label, \"</label>\\n\\n\\n <div class=\\\"input-group flex-nowrap w-25 \\\" role=\\\"group\\\" aria-label=\\\"\").concat(this.label, \"\\\" style=\\\"min-width:140px; height: 32px;\\\">\\n <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"reduction\\\" type=\\\"button\\\">-</button>\\n <input id=\\\"\").concat(this.id, \"\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-control text-center\\\" style=\\\"font-size: 0.875em;\\\" readonly>\\n <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"increment\\\" type=\\\"button\\\">+</button>\\n </div>\\n </div>\");\n var decrease = this.domNode.querySelector('[role=\"reduction\"]');\n var increase = this.domNode.querySelector('[role=\"increment\"]');\n var input = this.domNode.querySelector(\"#\".concat(this.id));\n var changeValue = function changeValue(delta) {\n var numeric = parseInt(_this.value, 10) || 0;\n numeric = Math.max(1, numeric + delta);\n _this.setValue(numeric);\n };\n if (decrease) {\n decrease.addEventListener('click', function (e) {\n e.preventDefault();\n changeValue(-1);\n });\n }\n if (increase) {\n increase.addEventListener('click', function (e) {\n e.preventDefault();\n changeValue(1);\n });\n }\n\n // allow direct programmatic update keeping UI in sync\n this._inputNode = input;\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n // Method to set value programmatically\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.value = newValue === null || newValue === undefined ? 16 : newValue;\n var input = this.domNode.querySelector('input');\n if (input) {\n input.value = this.value;\n }\n\n // Support both function and object with setValue\n if (typeof this.callback === 'function') {\n this.callback(this.value);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(this.value);\n }\n }\n\n // Method to get current value\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FontSizeControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FontSizeControl.js?");
/***/ }),
/***/ "./src/includes/FontWeightControl.js":
/*!*******************************************!*\
!*** ./src/includes/FontWeightControl.js ***!
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * FontWeightControl — sidebar + popover font-weight picker.\n *\n * 2026-04-24 (W3.1) — optional 4th-arg `options = { bus, elementUid,\n * formatterKey }` enables dual-mount bus sync. Same pattern as\n * AlignControl (W1.1b) / FontFamilyControl.\n */\nvar FontWeightControl = /*#__PURE__*/function () {\n function FontWeightControl(label, font_weight, callback) {\n var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n _classCallCheck(this, FontWeightControl);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.font_weight = font_weight === null || font_weight === undefined ? '' : String(font_weight);\n this.callback = callback;\n this._options = {\n bus: options.bus || null,\n elementUid: options.elementUid || null,\n formatterKey: options.formatterKey || null\n };\n this._busOff = null;\n this._busSource = 'font-weight-control:' + this.id;\n this.domNode = document.createElement('div');\n this.render();\n this._attachBusSubscription();\n }\n return _createClass(FontWeightControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var weightList = ['normal', 'bold', 'lighter', 'bolder', '100', '200', '300', '400', '500', '600', '700', '800', '900'];\n var optionsHtml = [\"<option value=\\\"\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_weight.not_set'), \"</option>\")].concat(_toConsumableArray(weightList.map(function (weight) {\n var selected = String(_this.font_weight) === String(weight) ? ' selected' : '';\n return \"<option value=\\\"\".concat(weight, \"\\\" style=\\\"font-weight: \").concat(weight, \";\\\"\").concat(selected, \">\").concat(weight, \"</option>\");\n }))).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-select\\\">\\n <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"\\\" name=\\\"font-weight\\\">\").concat(optionsHtml, \"</select>\\n <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n </div>\\n </div>\\n </div>\\n \");\n this.selectEl = this.domNode.querySelector('select');\n this.selectEl.addEventListener('change', function (e) {\n var val = e.target.value === '' ? null : e.target.value;\n _this.font_weight = val === null ? '' : val;\n _this._fireCallback(val);\n _this._emitBus();\n });\n }\n }, {\n key: \"_fireCallback\",\n value: function _fireCallback(val) {\n if (typeof this.callback === 'function') {\n this.callback(val);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(val);\n } else if (this.callback && typeof this.callback.setFontWeight === 'function') {\n this.callback.setFontWeight(val);\n }\n }\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$silent = _ref.silent,\n silent = _ref$silent === void 0 ? false : _ref$silent;\n this.font_weight = newValue === null || newValue === undefined ? '' : String(newValue);\n if (this.selectEl) this.selectEl.value = this.font_weight;\n if (silent) return;\n this._fireCallback(newValue);\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.font_weight === '' ? null : this.font_weight;\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this._busOff) {\n this._busOff();\n this._busOff = null;\n }\n }\n }, {\n key: \"_attachBusSubscription\",\n value: function _attachBusSubscription() {\n var _this2 = this;\n var _this$_options = this._options,\n bus = _this$_options.bus,\n elementUid = _this$_options.elementUid,\n formatterKey = _this$_options.formatterKey;\n if (!bus || !elementUid || !formatterKey) return;\n if (typeof bus.on !== 'function') return;\n this._busOff = bus.on('formatter:change', function (payload) {\n if (!payload) return;\n if (payload.elementUid !== elementUid) return;\n if (payload.key !== formatterKey) return;\n if (payload.source === _this2._busSource) return;\n _this2.setValue(payload.value, {\n silent: true\n });\n });\n }\n }, {\n key: \"_emitBus\",\n value: function _emitBus() {\n var _this$_options2 = this._options,\n bus = _this$_options2.bus,\n elementUid = _this$_options2.elementUid,\n formatterKey = _this$_options2.formatterKey;\n if (!bus || !elementUid || !formatterKey) return;\n if (typeof bus.emit !== 'function') return;\n bus.emit('formatter:change', {\n elementUid: elementUid,\n key: formatterKey,\n value: this.getValue(),\n source: this._busSource\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FontWeightControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FontWeightControl.js?");
/***/ }),
/***/ "./src/includes/FormContainerCell.js":
/*!*******************************************!*\
!*** ./src/includes/FormContainerCell.js ***!
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _CellElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CellElement.js */ \"./src/includes/CellElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n/**\n * FormContainerCell — a Cell that IS the form area.\n *\n * Differs from a plain CellElement in three ways:\n * 1. Template \"FormContainerCell\" renders children wrapped in\n * <form action={action} method={method}>…</form>. This is the single\n * <form> tag on the page — PageElement.template has moved to \"default\"\n * so there is no longer a top-level form wrapper. Scope of the form\n * element matches the area the user edits as \"form\", and no nested\n * <form> tags can appear in the DOM.\n * 2. Overrides renderEmptyPlaceholder() with a dashed call-to-action\n * that hints at the sidebar's \"Load list defaults\" button. This is\n * the only cell type whose empty state guides users to a specific\n * action instead of showing a generic \"drop blocks\" placeholder.\n * 3. Carries action + method fields directly (form POST target). Pre-\n * cleanup these used to live on a separate FormBlockElement marker\n * block; that legacy class was retired 2026-04-20 and all bundled\n * samples migrated to the FormContainerCell shape.\n */\nvar FormContainerCell = /*#__PURE__*/function (_CellElement) {\n function FormContainerCell(template, action, method) {\n var _this;\n _classCallCheck(this, FormContainerCell);\n _this = _callSuper(this, FormContainerCell, [template]);\n _this.action = action || '';\n _this.method = method || '';\n return _this;\n }\n\n // Explicit override — BaseElement.getClassName() uses `this.constructor.name`,\n // which webpack may mangle or reset in some builds. Hard-coding the class\n // name here guarantees getData() always writes `name: \"FormContainerCell\"`\n // and render() always tags the domNode as `builder-element=\"FormContainerCell\"`.\n _inherits(FormContainerCell, _CellElement);\n return _createClass(FormContainerCell, [{\n key: \"getClassName\",\n value: function getClassName() {\n return 'FormContainerCell';\n }\n }, {\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('form_container.name');\n }\n\n // Override the generic \"empty gallery\" SVG with a form-specific hint.\n // Styles are inline + icon is inline SVG so the placeholder renders\n // correctly inside the builder iframe — external class-based CSS and\n // icon-font URLs don't necessarily load in every theme's page template.\n // The SVG depicts three stacked form-input bars (clear domain signal for\n // \"this is where form fields go\", not the generic lock icon).\n }, {\n key: \"renderEmptyPlaceholder\",\n value: function renderEmptyPlaceholder() {\n var title = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('form_container.empty_title');\n var hint = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('form_container.empty_hint');\n // No inner border — the outer builder-helper ornament already draws\n // the dashed frame. Stacking two dashed borders looked noisy. Colour\n // palette is neutral grey / white (was blue) to match the greyed-out\n // \"FORM AREA\" pill + avoid colour-clashing with primary-blue themes.\n return \"\\n <div builder-no-select style=\\\"\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center;\\n gap: 10px;\\n min-height: 160px;\\n padding: 28px 20px;\\n margin: 0;\\n border-radius: 10px;\\n background: #fafafa;\\n color: #6b7280;\\n font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\\n text-align: center;\\n user-select: none;\\n pointer-events: none;\\n \\\">\\n <svg width=\\\"44\\\" height=\\\"32\\\" viewBox=\\\"0 0 44 32\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" style=\\\"opacity: 0.9;\\\">\\n <rect x=\\\"1\\\" y=\\\"1\\\" width=\\\"42\\\" height=\\\"8\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\" stroke-width=\\\"1.25\\\"/>\\n <rect x=\\\"5\\\" y=\\\"4.5\\\" width=\\\"14\\\" height=\\\"1.25\\\" rx=\\\"0.625\\\" fill=\\\"#9ca3af\\\"/>\\n <rect x=\\\"1\\\" y=\\\"13\\\" width=\\\"42\\\" height=\\\"8\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\" stroke-width=\\\"1.25\\\"/>\\n <rect x=\\\"5\\\" y=\\\"16.5\\\" width=\\\"22\\\" height=\\\"1.25\\\" rx=\\\"0.625\\\" fill=\\\"#9ca3af\\\"/>\\n <rect x=\\\"1\\\" y=\\\"25\\\" width=\\\"14\\\" height=\\\"5\\\" rx=\\\"1.5\\\" fill=\\\"#4b5563\\\"/>\\n </svg>\\n <div style=\\\"font-size: 14px; font-weight: 600; color: #1f2937; line-height: 1.3;\\\">\".concat(title, \"</div>\\n <div style=\\\"font-size: 12px; color: #6b7280; line-height: 1.5; max-width: 260px;\\\">\").concat(hint, \"</div>\\n </div>\\n \");\n }\n\n // Wrap child blocks in a real <form action method> so the exported HTML\n // has proper form semantics. CellElement.render() appends blocks as direct\n // children of domNode (a <div>); we relocate them into a <form> wrapper\n // without re-rendering, so event listeners + selection state stay intact.\n //\n // Also attaches the persistent \"Form Area\" ornament (dashed outline +\n // floating label) so authors always know where the form lives, whether\n // the FCC is empty or populated. The ornament is stripped from exported\n // HTML via the `data-control=\"builder-helper\"` filter in Builder.getHtml().\n }, {\n key: \"render\",\n value: function render() {\n var domNode = _superPropGet(FormContainerCell, \"render\", this, 3)([]);\n if (this.blocks.length > 0) {\n // Only wrap when we haven't already — super.render clears domNode\n // every call, so this is mostly defensive.\n var first = domNode.firstElementChild;\n if (!(first && first.tagName === 'FORM' && first.dataset.formContainerWrapper === '1')) {\n var form = document.createElement('form');\n form.setAttribute('action', this.action || '');\n form.setAttribute('method', this.method || 'post');\n form.dataset.formContainerWrapper = '1';\n while (domNode.firstChild) form.appendChild(domNode.firstChild);\n domNode.appendChild(form);\n }\n }\n this._attachBuilderOrnaments(domNode);\n return domNode;\n }\n\n // Always-visible \"Form Area\" decoration inside the builder canvas.\n // - outline (not border — no box-model impact, no layout shift)\n // - floating pill label top-left corner\n // Both elements are tagged `data-control=\"builder-helper\"` so\n // Builder.getHtml() strips them before export. Authors see the anchor,\n // end-users see clean HTML.\n }, {\n key: \"_attachBuilderOrnaments\",\n value: function _attachBuilderOrnaments(domNode) {\n // Position context for absolute children. Only style we touch on the\n // cell itself — has to stay so the builder-helper overlay anchors to\n // it. Browsers treat `position: relative` with no offset as a no-op\n // visually, so exported HTML renders the cell identically.\n if (domNode.style.position !== 'relative') domNode.style.position = 'relative';\n\n // Strip any legacy inline outline from a prior build — previous\n // implementations leaked `outline` directly onto domNode which then\n // appeared in the exported HTML that end-users see.\n domNode.style.outline = '';\n domNode.style.outlineOffset = '';\n domNode.style.paddingTop = '';\n\n // One shot of builder-only decoration: a single overlay element\n // carries the dashed border + the \"FORM AREA\" pill. Tagged with\n // data-control=\"builder-helper\" so Builder.getHtml() strips it\n // entirely from exported HTML. End-users see a clean form.\n var stale = domNode.querySelector('[data-form-area-helper]');\n if (stale) stale.remove();\n\n // Generous 14px outset so the outline sits clearly OUTSIDE field\n // labels — previously 4px which crossed through \"Email\", \"First\n // name\", etc. on typical form themes. The builder canvas has room\n // around each cell; the wider frame makes the \"this is the form\n // area\" grouping unambiguous.\n var helper = document.createElement('div');\n helper.setAttribute('data-control', 'builder-helper');\n helper.setAttribute('data-form-area-helper', '1');\n helper.setAttribute('builder-no-select', '');\n helper.style.cssText = ['position: absolute', 'top: -14px', 'left: -14px', 'right: -14px', 'bottom: -14px', 'border: 1.5px dashed rgba(55, 65, 81, 0.28)', 'border-radius: 10px', 'pointer-events: none', 'z-index: 0'].join('; ') + ';';\n var label = document.createElement('div');\n label.setAttribute('data-form-area-label', '1');\n // Pill height ≈ 18px (3px padding × 2 + 10px font-size + line-box).\n // Placing top at -9px (relative to helper, whose top IS the dashed\n // line) centres the pill ON the border — the line cuts through the\n // pill's vertical middle like a classic <fieldset>/<legend>. Reads\n // as \"this label names the outlined area\" at a glance.\n label.style.cssText = ['position: absolute', 'top: -9px', 'left: 10px', 'padding: 3px 10px', 'background: #1f2937', 'color: #fff', 'font-size: 10px', 'font-weight: 700', 'letter-spacing: 0.5px', 'text-transform: uppercase', 'border-radius: 999px', 'box-shadow: 0 1px 3px rgba(17, 24, 39, 0.25)', \"font-family: Inter, -apple-system, 'Segoe UI', Roboto, sans-serif\", 'pointer-events: none', 'user-select: none', 'white-space: nowrap'].join('; ') + ';';\n label.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('form_container.name');\n helper.appendChild(label);\n domNode.appendChild(helper);\n }\n }, {\n key: \"getData\",\n value: function getData() {\n // Serialise the same block-holding shape as CellElement, plus the\n // form-specific action/method so the next load restores the POST\n // target exactly as the user left it.\n var base = _superPropGet(FormContainerCell, \"getData\", this, 3)([]);\n base.action = this.action;\n base.method = this.method;\n return base;\n }\n }, {\n key: \"getControls\",\n value:\n // Same control set as CellElement plus two TextControls for the form\n // endpoint. The Settings panel surfaces action/method when the user\n // selects the form area — matching how other containers expose their\n // config.\n function getControls() {\n var _this2 = this;\n return [new _TextControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.action_url'), this.action, {\n setText: function setText(action) {\n _this2.action = action;\n _this2.render();\n }\n }), new _TextControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.method'), this.method, {\n setText: function setText(method) {\n _this2.method = method;\n _this2.render();\n }\n })].concat(_toConsumableArray(_superPropGet(FormContainerCell, \"getControls\", this, 3)([])));\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var cell = new this(data.template, data.action, data.method);\n var blocks = Array.isArray(data.blocks) ? data.blocks : [];\n blocks.forEach(function (blockData) {\n var block = _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(blockData);\n block.container = cell;\n cell.appendBlock(block);\n });\n cell.formatter.parseFormats(data.formats || {});\n cell.vertical_align = data.vertical_align || 'top';\n return cell;\n }\n }]);\n}(_CellElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FormContainerCell);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FormContainerCell.js?");
/***/ }),
/***/ "./src/includes/Formatter.js":
/*!***********************************!*\
!*** ./src/includes/Formatter.js ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction normalizeBackgroundAssetUrl(value, host) {\n if (typeof value !== 'string') {\n return value;\n }\n var normalizedValue = value.trim();\n var cssUrlMatch = normalizedValue.match(/^url\\((.*)\\)$/i);\n if (cssUrlMatch) {\n normalizedValue = cssUrlMatch[1].trim();\n }\n normalizedValue = normalizedValue.replace(/^['\"]|['\"]$/g, '');\n if (!normalizedValue || !host) {\n return normalizedValue;\n }\n if (typeof host.transferMediaAbsUrl === 'function') {\n return host.transferMediaAbsUrl(normalizedValue);\n }\n return normalizedValue;\n}\nvar Formatter = /*#__PURE__*/function () {\n // host-injection: owner-Element passes itself so background_image\n // url-resolution can route through host.transferMediaAbsUrl per\n // instance instead of the bare-`builder` global. Pre-existing\n // single-arg callers still work — host stays null and the URL is\n // returned verbatim (legacy behavior).\n function Formatter(formats) {\n var host = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n _classCallCheck(this, Formatter);\n this.formats = formats || {};\n this.host = host;\n }\n\n /** Late host injection — called by the owning element after host is\n * set on it (BaseElement._setFormatterHost helper). Lets us keep\n * the constructor signature back-compat for callers that don't\n * thread host through. */\n return _createClass(Formatter, [{\n key: \"_setHost\",\n value: function _setHost(host) {\n this.host = host;\n }\n }, {\n key: \"isKeyValid\",\n value: function isKeyValid(key) {\n return this.formats[key] !== undefined;\n }\n }, {\n key: \"validateKey\",\n value: function validateKey(key) {\n if (this.isKeyValid(key) === false) {\n throw new Error(\"Formatter: key \\\"\".concat(key, \"\\\" is not valid.\"));\n }\n }\n }, {\n key: \"getFormat\",\n value: function getFormat(key) {\n var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n if (!this.formats || _typeof(this.formats) !== 'object') return defaultValue;\n if (typeof this.formats[key] === 'undefined' || this.formats[key] === null) {\n return defaultValue;\n }\n return this.formats[key];\n }\n }, {\n key: \"setFormat\",\n value: function setFormat(key, value) {\n // validate key\n this.validateKey(key);\n this.formats[key] = value;\n }\n }, {\n key: \"toStyleString\",\n value: function toStyleString(key) {\n var value = this.getFormat(key);\n if (value === null || value === undefined || value === '') {\n return '';\n }\n\n // Convert camelCase to kebab-case\n var kebabKey = key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase().replace(/_/g, '-');\n\n // Properties that should never be treated as numeric (always strings)\n var stringOnlyProperties = ['font-family', 'text-align', 'direction', 'background-image', 'background-position', 'background-repeat', 'background-blend-mode', 'background-attachment', 'mix-blend-mode', 'filter', 'border-style', 'border-top-style', 'border-right-style', 'border-bottom-style', 'border-left-style', 'display', 'flex-direction', 'justify-content', 'align-items', 'color', 'background-color', 'border-color', 'border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color', 'text-decoration', 'white-space', 'box-shadow'];\n\n // Add 'px' for numeric values except for certain CSS properties\n var cssNumberProperties = ['opacity', 'z-index', 'flex-grow', 'flex-shrink', 'order', 'zoom', 'width', 'height', 'top', 'right', 'bottom', 'left', 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'border-width', 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width', 'border-radius', 'letter-spacing', 'word-spacing', 'text-indent', 'outline-width', 'gap', 'column-gap', 'row-gap', 'grid-gap', 'max-width', 'max-height', 'min-width', 'min-height', 'flex-basis', 'font-size', 'letter-spacing', 'text-indent'];\n\n // Unitless CSS properties — numbers passed through as-is (no px).\n // opacity accepts 0..1, z-index/order accept integers, flex-* accept floats, zoom accepts factor.\n var unitlessNumberProperties = ['opacity', 'z-index', 'flex-grow', 'flex-shrink', 'order', 'zoom'];\n if (unitlessNumberProperties.includes(kebabKey)) {\n if (typeof value === 'number') {\n value = \"\".concat(value, \" !important\");\n } else if (typeof value === 'string') {\n var trimmed = value.trim();\n if (trimmed !== '' && !isNaN(trimmed)) value = \"\".concat(trimmed, \" !important\");\n }\n } else if (!stringOnlyProperties.includes(kebabKey) && cssNumberProperties.includes(kebabKey)) {\n // Dimensional properties: preserve any pre-attached unit, otherwise append px.\n // Accepted forms:\n // 300 (number) -> \"300px !important\" (legacy)\n // \"300\" (numeric str)-> \"300px !important\" (legacy)\n // \"300px\" (with unit) -> \"300px !important\"\n // \"50%\" (percent) -> \"50% !important\"\n // \"1.5em\" (em/rem/...) -> \"1.5em !important\"\n // \"auto\" (keyword) -> \"auto\" (no !important — lets\n // children override)\n // \"inherit\"/\"initial\"/\"unset\"/\"revert\" -> bare keyword, no !important\n var cssKeywords = ['auto', 'inherit', 'initial', 'unset', 'revert', 'fit-content', 'max-content', 'min-content'];\n var hasUnitRegex = /^-?[\\d.]+(px|%|em|rem|vw|vh|ch|ex|cm|mm|in|pt|pc|fr)$/i;\n if (typeof value === 'number') {\n value = \"\".concat(value, \"px !important\");\n } else if (typeof value === 'string') {\n var _trimmed = value.trim();\n if (cssKeywords.includes(_trimmed.toLowerCase())) {\n value = _trimmed;\n } else if (hasUnitRegex.test(_trimmed)) {\n value = \"\".concat(_trimmed, \" !important\");\n } else if (!isNaN(_trimmed) && _trimmed !== '') {\n // numeric string with no unit — legacy — assume px\n value = \"\".concat(_trimmed, \"px !important\");\n }\n // else: pass through raw string (e.g. \"calc(100% - 20px)\")\n }\n }\n\n // special handling for background_image\n // Supports 3 input forms:\n // 1. Plain URL → wrap in url(...)\n // 2. Gradient string → pass through (linear-gradient / radial-gradient / conic-gradient)\n // 3. Composite string → already contains url(...) or gradient + url → pass through\n // (3) lets BackgroundControl stack \"gradient, url(image)\" into a single background-image value.\n if (key === 'background_image') {\n var raw = typeof value === 'string' ? value.trim() : '';\n var hasGradient = /^(linear|radial|conic)-gradient\\s*\\(/i.test(raw);\n var hasUrlFunc = /\\burl\\s*\\(/i.test(raw);\n if (hasGradient || hasUrlFunc) {\n value = raw;\n } else {\n value = \"url(\".concat(normalizeBackgroundAssetUrl(value, this.host), \")\");\n }\n }\n\n // translate specific keys\n if (key === 'text_direction') {\n kebabKey = 'direction';\n }\n if (key === 'paragraph_spacing') {\n kebabKey = 'margin-bottom';\n }\n if (key === 'text_color') {\n kebabKey = 'color';\n }\n\n // Normalize double-quotes to single-quotes in CSS values so the\n // emitted string is safe to drop into a double-quoted HTML attribute\n // (e.g. `style=\"...\"`). CSS treats '\"' and \"'\" identically for\n // string tokens like `font-family: \"Work Sans\"`. Without this,\n // font-family names with double-quotes break the style attribute\n // parser and every format after it silently fails to apply.\n if (typeof value === 'string' && value.indexOf('\"') !== -1) {\n value = value.replace(/\"/g, \"'\");\n }\n return \"\".concat(kebabKey, \": \").concat(value, \"; \");\n }\n }, {\n key: \"toStyleStringAll\",\n value: function toStyleStringAll() {\n var filters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n var styleString = '';\n for (var _i = 0, _Object$entries = Object.entries(this.formats); _i < _Object$entries.length; _i++) {\n var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),\n key = _Object$entries$_i[0],\n value = _Object$entries$_i[1];\n if (value !== null && value !== undefined && value !== '' && (filters === null || filters.includes(key))) {\n styleString += this.toStyleString(key);\n }\n }\n return styleString.trim();\n }\n }, {\n key: \"getFormats\",\n value: function getFormats() {\n // filter formats return only those with non-null/undefined/empty values\n var filteredFormats = {};\n for (var _i2 = 0, _Object$entries2 = Object.entries(this.formats); _i2 < _Object$entries2.length; _i2++) {\n var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),\n key = _Object$entries2$_i[0],\n value = _Object$entries2$_i[1];\n if (value !== null && value !== undefined && value !== '') {\n filteredFormats[key] = value;\n }\n }\n return filteredFormats;\n }\n }, {\n key: \"parseFormats\",\n value: function parseFormats(formats) {\n // Defensive: if formats is not an object, ignore it.\n if (!formats || _typeof(formats) !== 'object') return;\n for (var _i3 = 0, _Object$entries3 = Object.entries(formats); _i3 < _Object$entries3.length; _i3++) {\n var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i3], 2),\n key = _Object$entries3$_i[0],\n value = _Object$entries3$_i[1];\n if (this.isKeyValid(key)) {\n this.setFormat(key, value);\n }\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Formatter);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/Formatter.js?");
/***/ }),
/***/ "./src/includes/GridControl.js":
/*!*************************************!*\
!*** ./src/includes/GridControl.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PointerCaptureRegistry.js */ \"./src/includes/PointerCaptureRegistry.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n/**\n * GridControl — horizontal visual cell editor for a Grid element's cells.\n *\n * Renders `.bjs-cell-manager` (see builder.css §17 + docs/core/UI.md). Cards sit\n * in a flex row with widths proportional to their configured `width` format\n * so the control mirrors the canvas layout — WYSIWYG. Quick-apply layout\n * presets above the strip cover 90%+ of real grids (1 / 1·1 / 1·1·1 / 1·2 /\n * 2·1 / 1·2·1).\n *\n * Phase-3 W6.1 (2026-04-18) adds four \"pro\" affordances on top of the\n * baseline Phase-2 editor:\n *\n * 1. **Drag-reorder.** Pointer-based drag on the card handle (non-functional\n * in Phase-2) reorders cells. A vertical drop indicator tracks the\n * target slot; release commits via `callbacks.moveCell(from, to)`.\n * 2. **Bulk-select.** Shift-click extends selection from the primary cell;\n * Cmd/Ctrl-click toggles individual cells. A bulk toolbar surfaces\n * when ≥2 cells are selected and exposes a single-shot Delete.\n * 3. **Snap-ratios.** Thin resizer grips between adjacent cards adjust both\n * neighbor widths simultaneously. During drag, magnetic snap to 1/4,\n * 1/3, 1/2, 2/3, 3/4 of the combined (left+right) span — the same\n * ratios designers build around. Ratio tooltip hovers above the grip.\n * 4. **Pixel ruler.** A subtle tick strip above the cards shows 10% minor /\n * 25% major marks. During resize the active-ratio markers light up so\n * the author sees what percentage they're committing.\n *\n * Structure-preserving: when a caller only changes a cell's width, the\n * controller patches the existing card's `style.flex` via\n * `applyCardWidths()` — no full innerHTML rebuild. Full `render()` only\n * happens on cell count changes (add/remove/preset).\n */\n\n// One-click layout presets. `widths` is the format stored per cell.\n// Bare numbers mean grow-share (flex: N 1 0) — preferred for responsive.\nvar LAYOUT_PRESETS = [{\n id: '1',\n widths: ['auto'],\n titleKey: 'grid.preset_1col'\n}, {\n id: '1-1',\n widths: [1, 1],\n titleKey: 'grid.preset_1_1'\n}, {\n id: '1-1-1',\n widths: [1, 1, 1],\n titleKey: 'grid.preset_1_1_1'\n}, {\n id: '1-2',\n widths: [1, 2],\n titleKey: 'grid.preset_1_2'\n}, {\n id: '2-1',\n widths: [2, 1],\n titleKey: 'grid.preset_2_1'\n}, {\n id: '1-2-1',\n widths: [1, 2, 1],\n titleKey: 'grid.preset_1_2_1'\n}];\n\n// Magnetic snap points for resize drag, expressed as fractions of the combined\n// (left + right) cell span. Chosen to match the canonical design ratios every\n// preset above covers, so a user dragging into \"50/50\" gets help landing\n// exactly there. Ratios are symmetric — 0.25 on the left ≡ 0.75 on the right.\nvar SNAP_RATIOS = [{\n v: 0.25,\n label: '1 : 3'\n}, {\n v: 1 / 3,\n label: '1 : 2'\n}, {\n v: 0.5,\n label: '1 : 1'\n}, {\n v: 2 / 3,\n label: '2 : 1'\n}, {\n v: 0.75,\n label: '3 : 1'\n}];\nvar SNAP_TOLERANCE = 0.025; // ± percentage-of-combined at which snap engages\n\n// Pixel-ruler ticks. Major at 25% intervals, minor at 10% intervals. Both sets\n// are drawn; CSS differentiates thickness + label visibility.\nvar RULER_MINOR = [10, 20, 30, 40, 60, 70, 80, 90];\nvar RULER_MAJOR = [0, 25, 50, 75, 100];\nvar GridControl = /*#__PURE__*/function () {\n /**\n * @param {string} label Translated title (\"Cells\")\n * @param {object} values\n * @param {function} values.getItemCount\n * @param {function} [values.getCellWidths] Returns ['50%', 'auto', ...] — for preset detection + card layout\n * @param {function} [values.getSelectedIndex] Returns 0-based index of selected cell, or -1\n * @param {object} callbacks\n * @param {function} callbacks.addCell\n * @param {function} callbacks.addCellAt\n * @param {function} callbacks.removeCell\n * @param {function} [callbacks.selectCell] Optional: called when user clicks a card\n * @param {function} [callbacks.applyPreset] Optional: called with preset.widths array\n * @param {function} [callbacks.moveCell] Reorder: (from, to) — move source to slot\n * @param {function} [callbacks.resizeCellPair] Resize: (leftIdx, leftPct, rightPct)\n * @param {function} [callbacks.removeCells] Bulk-remove: indices[] (descending order)\n * @param {function} [callbacks.rebalanceProportional]\n * @param {function} [callbacks.equalize]\n */\n function GridControl(label, values, callbacks) {\n _classCallCheck(this, GridControl);\n this.label = label;\n this.getItemCount = values.getItemCount;\n this.getCellWidths = values.getCellWidths || function () {\n return [];\n };\n this.getSelectedIndex = values.getSelectedIndex || function () {\n return -1;\n };\n this.callback = callbacks;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-cell-manager');\n\n // Pro state (Phase-3 W6.1)\n this._dragState = null;\n this._resizeState = null;\n this._multiSelected = new Set();\n this.render();\n }\n return _createClass(GridControl, [{\n key: \"_t\",\n value: function _t(key, fallback) {\n try {\n var v = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key);\n return v && v !== key ? v : fallback;\n } catch (_e) {\n return fallback;\n }\n }\n\n /** Infer a card's flex-style from its width format. Mirrors the math in\n * Cell.template.html so the panel visually matches canvas. */\n }, {\n key: \"_cardFlexStyle\",\n value: function _cardFlexStyle(width) {\n if (width === 'auto' || width === null || width === '' || width === undefined) {\n return 'flex: 1 1 0;';\n }\n var str = String(width).trim();\n if (/%$/.test(str)) {\n var pct = parseFloat(str);\n if (!isNaN(pct) && pct > 0) return \"flex: 0 0 \".concat(pct, \"%;\");\n return 'flex: 1 1 0;';\n }\n if (/(px|em|rem|vw|vh|ch|ex)$/i.test(str)) {\n return \"flex: 0 0 \".concat(str, \";\");\n }\n var num = parseFloat(str);\n if (!isNaN(num) && num > 0) return \"flex: \".concat(num, \" 1 0;\");\n return 'flex: 1 1 0;';\n }\n\n /** Format a width for display on the card. */\n }, {\n key: \"_widthLabel\",\n value: function _widthLabel(width) {\n if (width === 'auto' || width === null || width === '' || width === undefined) {\n return 'auto';\n }\n var str = String(width).trim();\n if (/%$/.test(str) || /(px|em|rem|vw|vh|ch|ex)$/i.test(str)) return str;\n var num = parseFloat(str);\n if (!isNaN(num) && num > 0) return \"\".concat(num);\n return 'auto';\n }\n\n /** Identify which preset (if any) the current widths match — used to\n * highlight the active preset tile. Bare-number proportions are compared\n * via normalised ratios; explicit % cells map only to presets that use\n * the same values. */\n }, {\n key: \"_activePresetId\",\n value: function _activePresetId() {\n var widths = this.getCellWidths();\n if (!Array.isArray(widths) || widths.length === 0) return null;\n\n // One-column\n if (widths.length === 1) {\n var w = widths[0];\n if (w === 'auto' || w === null || w === undefined || w === '') return '1';\n return null;\n }\n\n // Multi-cell presets: check bare-number ratios\n var nums = widths.map(function (w) {\n if (typeof w === 'number') return w;\n var str = String(w).trim();\n if (/%$/.test(str)) return parseFloat(str);\n var n = parseFloat(str);\n return isNaN(n) ? null : n;\n });\n if (nums.some(function (n) {\n return n === null;\n })) return null;\n var _loop = function _loop() {\n var preset = _LAYOUT_PRESETS[_i];\n if (preset.widths.length !== widths.length) return 0; // continue\n var pNums = preset.widths.map(function (w) {\n return typeof w === 'number' ? w : 100 / preset.widths.length;\n });\n // Normalise both to sum=1 and compare element-wise with tolerance.\n var sum = nums.reduce(function (a, b) {\n return a + b;\n }, 0);\n var pSum = pNums.reduce(function (a, b) {\n return a + b;\n }, 0);\n if (sum === 0 || pSum === 0) return 0; // continue\n var nNorm = nums.map(function (n) {\n return n / sum;\n });\n var pNorm = pNums.map(function (n) {\n return n / pSum;\n });\n var match = nNorm.every(function (v, i) {\n return Math.abs(v - pNorm[i]) < 0.01;\n });\n if (match) return {\n v: preset.id\n };\n },\n _ret;\n for (var _i = 0, _LAYOUT_PRESETS = LAYOUT_PRESETS; _i < _LAYOUT_PRESETS.length; _i++) {\n _ret = _loop();\n if (_ret === 0) continue;\n if (_ret) return _ret.v;\n }\n return null;\n }\n }, {\n key: \"_renderPresets\",\n value: function _renderPresets() {\n var _this = this;\n var activeId = this._activePresetId();\n var html = LAYOUT_PRESETS.map(function (preset) {\n var active = preset.id === activeId ? ' is-active' : '';\n var pNums = preset.widths.map(function (w) {\n return typeof w === 'number' ? w : 1;\n });\n var segs = pNums.map(function (n) {\n return \"<span class=\\\"bjs-cell-manager-preset-seg\\\" style=\\\"flex: \".concat(n, \";\\\"></span>\");\n }).join('');\n var title = _this._t(preset.titleKey, preset.id.replace(/-/g, ' / ')) || preset.id;\n return \"<button type=\\\"button\\\" class=\\\"bjs-cell-manager-preset\".concat(active, \"\\\" data-preset=\\\"\").concat(preset.id, \"\\\" data-tooltip=\\\"\").concat(title, \"\\\" aria-label=\\\"\").concat(title, \"\\\"><span class=\\\"bjs-cell-manager-preset-icon\\\">\").concat(segs, \"</span></button>\");\n }).join('');\n return \"<div class=\\\"bjs-cell-manager-presets\\\" role=\\\"toolbar\\\" aria-label=\\\"\".concat(this._t('grid.layout_presets', 'Layout presets'), \"\\\">\").concat(html, \"</div>\");\n }\n\n /** Ruler strip above the cards — tick marks at 10% minor / 25% major.\n * Ticks are percent-positioned so the ruler stays aligned with the strip\n * regardless of panel width. The active-ratio helpers (`is-active` class\n * applied during resize drag) are handled by _updateRulerSnap. */\n }, {\n key: \"_renderRuler\",\n value: function _renderRuler() {\n var label = this._t('grid.ruler', 'Row ruler');\n var majors = RULER_MAJOR.map(function (v) {\n return \"<span class=\\\"bjs-cell-manager-ruler-tick bjs-cell-manager-ruler-tick--major\\\" data-ruler=\\\"\".concat(v, \"\\\" style=\\\"left: \").concat(v, \"%;\\\"><span class=\\\"bjs-cell-manager-ruler-label\\\">\").concat(v === 0 || v === 100 ? '' : v + '%', \"</span></span>\");\n }).join('');\n var minors = RULER_MINOR.map(function (v) {\n return \"<span class=\\\"bjs-cell-manager-ruler-tick bjs-cell-manager-ruler-tick--minor\\\" data-ruler=\\\"\".concat(v, \"\\\" style=\\\"left: \").concat(v, \"%;\\\"></span>\");\n }).join('');\n return \"<div class=\\\"bjs-cell-manager-ruler\\\" role=\\\"presentation\\\" aria-label=\\\"\".concat(label, \"\\\"><div class=\\\"bjs-cell-manager-ruler-track\\\">\").concat(majors).concat(minors, \"</div></div>\");\n }\n }, {\n key: \"_renderCard\",\n value: function _renderCard(index, total, width, isSelected) {\n var flex = this._cardFlexStyle(width);\n var label = this._widthLabel(width);\n var removable = total > 1;\n var sel = isSelected ? ' is-selected' : '';\n var multi = this._multiSelected.has(index) ? ' is-multi-selected' : '';\n var selAttr = isSelected ? 'aria-selected=\"true\"' : '';\n var removeDisabled = removable ? '' : 'data-removable=\"false\"';\n var handleTitle = this._t('grid.drag_cell', 'Drag to reorder');\n return \"\\n <article class=\\\"bjs-cell-card\".concat(sel).concat(multi, \"\\\" role=\\\"option\\\" \").concat(selAttr, \" \").concat(removeDisabled, \" data-cell-index=\\\"\").concat(index, \"\\\" style=\\\"\").concat(flex, \"\\\">\\n <header class=\\\"bjs-cell-card-head\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-cell-card-handle\\\" aria-label=\\\"\").concat(handleTitle, \"\\\" data-tooltip=\\\"\").concat(handleTitle, \"\\\" tabindex=\\\"0\\\">\\n <span class=\\\"material-symbols-rounded\\\">drag_indicator</span>\\n </button>\\n <span class=\\\"bjs-cell-card-index\\\">#\").concat(index + 1, \"</span>\\n </header>\\n <div class=\\\"bjs-cell-card-body\\\">\\n <span>\\n <span class=\\\"bjs-cell-card-width\\\">\").concat(label, \"</span>\\n </span>\\n </div>\\n <footer class=\\\"bjs-cell-card-foot\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-cell-card-remove\\\" data-control=\\\"remove-cell\\\" data-index=\\\"\").concat(index, \"\\\" aria-label=\\\"\").concat(this._t('grid.remove_cell', 'Remove cell'), \" \").concat(index + 1, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">delete</span>\\n </button>\\n </footer>\\n </article>\\n \");\n }\n }, {\n key: \"_renderSlots\",\n value: function _renderSlots(count) {\n /* Initial `left:` values are a reasonable first paint placeholder — the\n real position is written in px by `_positionSlots()` after the cards\n measure. Slot N+1 edge slots (0% / 100%) would land at the strip's\n outer edges here, but `_positionSlots()` overrides every slot. */\n var out = [];\n for (var i = 0; i <= count; i++) {\n var pct = i / count * 100;\n out.push(\"\\n <div class=\\\"bjs-cell-manager-slot\\\" data-slot-index=\\\"\".concat(i, \"\\\" style=\\\"left: \").concat(pct, \"%;\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-cell-manager-slot-btn\\\" data-control=\\\"add-cell-at\\\" data-index=\\\"\").concat(i, \"\\\" aria-label=\\\"\").concat(this._t('grid.insert_cell_at', 'Insert cell at'), \" \").concat(i + 1, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">add</span>\\n </button>\\n </div>\\n \"));\n }\n return out.join('');\n }\n\n /** Resizer grips — narrow vertical grips in the gap between adjacent cards.\n * Each grip targets the pair (i, i+1) and lets the user drag to rebalance\n * their widths without leaving the panel. Only rendered when BOTH cells in\n * the pair are percent-based (bare / auto pairs fall back to the numeric\n * DimensionControl below — we can't do math without a numeric %). */\n }, {\n key: \"_renderResizers\",\n value: function _renderResizers(count) {\n if (count < 2) return '';\n var widths = this.getCellWidths();\n var out = [];\n for (var i = 0; i < count - 1; i++) {\n var wL = widths[i];\n var wR = widths[i + 1];\n var bothPct = this._asPct(wL) !== null && this._asPct(wR) !== null;\n if (!bothPct) continue;\n var label = this._t('grid.resize_between', 'Resize cell');\n out.push(\"\\n <div class=\\\"bjs-cell-manager-resizer\\\" data-resizer-left=\\\"\".concat(i, \"\\\" data-resizer-right=\\\"\").concat(i + 1, \"\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-cell-manager-resizer-grip\\\" aria-label=\\\"\").concat(label, \" \").concat(i + 1, \"/\").concat(i + 2, \"\\\" data-tooltip=\\\"\").concat(label, \" \").concat(i + 1, \"/\").concat(i + 2, \"\\\" tabindex=\\\"-1\\\">\\n <span class=\\\"material-symbols-rounded\\\">drag_indicator</span>\\n </button>\\n <div class=\\\"bjs-cell-manager-resizer-tip\\\" role=\\\"status\\\" aria-hidden=\\\"true\\\"><span class=\\\"bjs-cell-manager-resizer-tip-value\\\"></span></div>\\n </div>\\n \"));\n }\n return out.join('');\n }\n\n /** Return a numeric percent for a width format that's a %, or null. */\n }, {\n key: \"_asPct\",\n value: function _asPct(w) {\n if (typeof w === 'string' && /%$/.test(w.trim())) {\n var n = parseFloat(w);\n return isNaN(n) ? null : n;\n }\n return null;\n }\n\n /** Position the resizer grips on the real gap midpoints between card pairs.\n * Similar math to _positionSlots but only for inner gaps (not outer edges)\n * and only for pairs we actually rendered (bothPct). Accepts the list of\n * rendered grip DOM elements in order and matches them to their card pair\n * via data-resizer-left. */\n }, {\n key: \"_positionResizers\",\n value: function _positionResizers() {\n if (!this.domNode) return;\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n if (!strip) return;\n var cards = Array.from(strip.querySelectorAll(':scope > .bjs-cell-card'));\n var grips = Array.from(strip.querySelectorAll(':scope > .bjs-cell-manager-resizer'));\n if (!cards.length || !grips.length) return;\n var stripRect = strip.getBoundingClientRect();\n if (stripRect.width === 0) return;\n grips.forEach(function (grip) {\n var i = parseInt(grip.getAttribute('data-resizer-left'), 10);\n if (isNaN(i) || !cards[i] || !cards[i + 1]) return;\n var prev = cards[i].getBoundingClientRect();\n var next = cards[i + 1].getBoundingClientRect();\n var xPx = (prev.right - stripRect.left + (next.left - stripRect.left)) / 2;\n grip.style.left = \"\".concat(xPx, \"px\");\n });\n }\n\n /**\n * Re-position every `+` insert slot at the actual gap midpoint between\n * cards (in px, not percentages). Cells can have arbitrary widths\n * (%, px, bare-number flex-grow, `auto`) so the equal-fraction placement\n * that `_renderSlots` emits on first paint is wrong for any non-uniform\n * row. We measure rendered card boundaries instead — the single source of\n * truth that reflects whatever the browser's flex solver actually did.\n */\n }, {\n key: \"_positionSlots\",\n value: function _positionSlots() {\n if (!this.domNode) return;\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n if (!strip) return;\n var cards = Array.from(strip.querySelectorAll(':scope > .bjs-cell-card'));\n var slots = Array.from(strip.querySelectorAll(':scope > .bjs-cell-manager-slot'));\n if (!cards.length || slots.length !== cards.length + 1) return;\n var stripRect = strip.getBoundingClientRect();\n if (stripRect.width === 0) return; /* panel hidden — skip */\n\n slots.forEach(function (slot, i) {\n var xPx;\n if (i === 0) {\n /* Leftmost edge slot — midpoint between strip edge and card 0 left */\n var card = cards[0];\n var left = card.getBoundingClientRect().left - stripRect.left;\n xPx = left / 2;\n } else if (i === cards.length) {\n /* Rightmost edge slot — midpoint between last card right and strip edge */\n var _card = cards[cards.length - 1];\n var right = _card.getBoundingClientRect().right - stripRect.left;\n xPx = (right + stripRect.width) / 2;\n } else {\n /* Between cards — midpoint of the gap */\n var prev = cards[i - 1].getBoundingClientRect();\n var next = cards[i].getBoundingClientRect();\n xPx = (prev.right - stripRect.left + (next.left - stripRect.left)) / 2;\n }\n slot.style.left = \"\".concat(xPx, \"px\");\n });\n this._positionResizers();\n }\n\n /**\n * Watch the strip for size changes (panel resize, cell width edits,\n * add / remove cell) and reposition slots when layout shifts. One observer\n * per control instance, torn down + recreated on each render().\n */\n }, {\n key: \"_observeStripResize\",\n value: function _observeStripResize() {\n var _this2 = this;\n if (this._resizeObserver) {\n try {\n this._resizeObserver.disconnect();\n } catch (_e) {}\n this._resizeObserver = null;\n }\n if (typeof ResizeObserver === 'undefined' || !this.domNode) return;\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n if (!strip) return;\n this._resizeObserver = new ResizeObserver(function () {\n return _this2._positionSlots();\n });\n this._resizeObserver.observe(strip);\n /* Also observe each card — a `width: 33.33%` → `width: 50%` edit via the\n DimensionControl below changes a card's flex without changing strip's\n own bounding box, and ResizeObserver on strip alone may miss it. */\n strip.querySelectorAll(':scope > .bjs-cell-card').forEach(function (c) {\n return _this2._resizeObserver.observe(c);\n });\n }\n\n /** Compute percentage-sum when every cell is a percent — otherwise null.\n * Used to decide whether the \"row overflow\" rebalance banner should show\n * (only makes sense when the row IS an all-% row). Mixed rows with\n * `fill`/`auto`/`px` don't have a meaningful \"sum\" and never show the\n * banner. */\n }, {\n key: \"_percentSum\",\n value: function _percentSum() {\n var widths = this.getCellWidths();\n if (!widths.length) return null;\n var allPct = widths.every(function (w) {\n return typeof w === 'string' && /%$/.test(String(w).trim());\n });\n if (!allPct) return null;\n var sum = widths.reduce(function (acc, w) {\n return acc + (parseFloat(w) || 0);\n }, 0);\n return Math.round(sum * 100) / 100;\n }\n }, {\n key: \"_renderRebalanceAlert\",\n value: function _renderRebalanceAlert() {\n var sum = this._percentSum();\n // Tolerance: rounding residue from the migration can leave sums at\n // 99.99 or 100.01. Only surface the banner when > 1% off.\n if (sum === null || Math.abs(sum - 100) <= 1) return '';\n var over = sum > 100;\n var msg = over ? this._t('grid.alert_overflow', \"Cells sum to \".concat(sum, \"% \\u2014 row will overflow. Rebalance to fit, or equalize?\")) : this._t('grid.alert_underfill', \"Cells sum to \".concat(sum, \"% \\u2014 row has \").concat(Math.round(100 - sum), \"% empty space. Rebalance to fill, or equalize?\"));\n return \"\\n <div class=\\\"bjs-cell-manager-alert\\\" role=\\\"status\\\" data-sum=\\\"\".concat(sum, \"\\\" data-state=\\\"\").concat(over ? 'overflow' : 'underfill', \"\\\">\\n <span class=\\\"bjs-cell-manager-alert-icon material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\").concat(over ? 'warning' : 'info', \"</span>\\n <span class=\\\"bjs-cell-manager-alert-body\\\">\").concat(msg.replace(/\\n/g, ' '), \"</span>\\n <span class=\\\"bjs-cell-manager-alert-actions\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-cell-manager-alert-btn\\\" data-control=\\\"alert-rebalance\\\" data-tooltip=\\\"\").concat(this._t('grid.alert_rebalance_title', 'Scale existing widths proportionally so the row sums to 100%'), \"\\\">\").concat(this._t('grid.alert_rebalance', 'Rebalance'), \"</button>\\n <button type=\\\"button\\\" class=\\\"bjs-cell-manager-alert-btn\\\" data-control=\\\"alert-equalize\\\" data-tooltip=\\\"\").concat(this._t('grid.alert_equalize_title', 'Set every cell to 100 / N percent'), \"\\\">\").concat(this._t('grid.alert_equalize', 'Equalize'), \"</button>\\n <button type=\\\"button\\\" class=\\\"bjs-cell-manager-alert-btn bjs-cell-manager-alert-dismiss\\\" data-control=\\\"alert-dismiss\\\" aria-label=\\\"\").concat(this._t('grid.alert_dismiss', 'Dismiss'), \"\\\" data-tooltip=\\\"\").concat(this._t('grid.alert_dismiss', 'Dismiss'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">close</span>\\n </button>\\n </span>\\n </div>\\n \");\n }\n\n /** Bulk-action toolbar (Phase-3 W6.1). Surfaces only when ≥1 cell is in the\n * multi-select set (a Shift/Cmd-click extension beyond the primary\n * selection). Cells marked via `.is-multi-selected`. */\n }, {\n key: \"_renderBulkBar\",\n value: function _renderBulkBar() {\n var n = this._multiSelected.size;\n if (n < 1) return '';\n var label = this._t('grid.bulk_selected', '{n} selected').replace('{n}', String(n));\n var delLabel = this._t('grid.bulk_delete', 'Delete');\n var clearLabel = this._t('grid.bulk_clear', 'Clear');\n return \"\\n <div class=\\\"bjs-cell-manager-bulk\\\" role=\\\"status\\\" data-count=\\\"\".concat(n, \"\\\">\\n <span class=\\\"bjs-cell-manager-bulk-count\\\">\").concat(label, \"</span>\\n <span class=\\\"bjs-cell-manager-bulk-actions\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-cell-manager-bulk-btn\\\" data-control=\\\"bulk-delete\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">delete</span>\\n <span>\").concat(delLabel, \"</span>\\n </button>\\n <button type=\\\"button\\\" class=\\\"bjs-cell-manager-bulk-btn bjs-cell-manager-bulk-btn--ghost\\\" data-control=\\\"bulk-clear\\\">\").concat(clearLabel, \"</button>\\n </span>\\n </div>\\n \");\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this3 = this;\n var total = this.getItemCount();\n var widths = this.getCellWidths();\n var selected = this.getSelectedIndex();\n var safeWidths = Array.from({\n length: total\n }, function (_, i) {\n return widths[i];\n });\n\n // Prune stale multi-select indices (cells removed since the set was built)\n if (this._multiSelected.size) {\n this._multiSelected = new Set(Array.from(this._multiSelected).filter(function (i) {\n return i < total && i >= 0;\n }));\n }\n var cards = safeWidths.map(function (w, i) {\n return _this3._renderCard(i, total, w, i === selected);\n }).join('');\n var slots = total > 0 ? this._renderSlots(total) : '';\n var resizers = total > 1 ? this._renderResizers(total) : '';\n var alert = this._dismissed ? '' : this._renderRebalanceAlert();\n var bulk = this._renderBulkBar();\n this.domNode.innerHTML = \"\\n <header class=\\\"bjs-cell-manager-header\\\">\\n <div class=\\\"bjs-cell-manager-title\\\">\\n <span>\".concat(this.label, \"</span>\\n <span class=\\\"bjs-cell-manager-count\\\" aria-label=\\\"\").concat(total, \" \").concat(total === 1 ? 'cell' : 'cells', \"\\\">\").concat(total, \"</span>\\n </div>\\n <button type=\\\"button\\\" class=\\\"bjs-cell-manager-add\\\" data-control=\\\"add-cell\\\">\\n <span class=\\\"material-symbols-rounded\\\">add</span>\\n <span>\").concat(this._t('grid.add_cell', 'Add cell'), \"</span>\\n </button>\\n </header>\\n\\n \").concat(this._renderPresets(), \"\\n\\n \").concat(total > 0 ? this._renderRuler() : '', \"\\n\\n <div class=\\\"bjs-cell-manager-strip\\\" role=\\\"listbox\\\" aria-multiselectable=\\\"true\\\" aria-label=\\\"\").concat(this._t('grid.cells', 'Cells'), \"\\\" style=\\\"--bjs-cell-manager-gap: 8px;\\\">\\n \").concat(cards, \"\\n \").concat(resizers, \"\\n \").concat(slots, \"\\n </div>\\n\\n \").concat(bulk, \"\\n\\n \").concat(alert, \"\\n\\n <div class=\\\"bjs-cell-manager-hint\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">lightbulb</span>\\n <span>\").concat(this._t('grid.manager_hint', 'Card widths mirror the live grid layout. Click a card to edit its width below.'), \"</span>\\n </div>\\n \");\n this._bindEvents();\n\n /* After innerHTML lands, measure card rects and position insert slots\n at the actual gap midpoints. Double-rAF — cards need one frame for\n layout, then slots can read the resolved getBoundingClientRect. */\n requestAnimationFrame(function () {\n requestAnimationFrame(function () {\n _this3._positionSlots();\n _this3._observeStripResize();\n });\n });\n }\n\n /** Structure-preserving update: only patches `style.flex` + width label on\n * existing cards (no innerHTML swap). Used when CELL WIDTHS section\n * emits a width change — keeps focus + avoids flicker. */\n }, {\n key: \"applyCardWidths\",\n value: function applyCardWidths() {\n var _this4 = this;\n var widths = this.getCellWidths();\n var cards = this.domNode.querySelectorAll('.bjs-cell-card');\n cards.forEach(function (card, i) {\n var w = widths[i];\n card.style.cssText = _this4._cardFlexStyle(w);\n var label = card.querySelector('.bjs-cell-card-width');\n if (label) label.textContent = _this4._widthLabel(w);\n });\n // Preset highlight may change\n this._refreshPresetActive();\n /* Widths changed → cards re-flex → slot gap positions drift. Re-measure. */\n requestAnimationFrame(function () {\n return _this4._positionSlots();\n });\n }\n\n /** Update `is-selected` state without a full re-render. */\n }, {\n key: \"applySelection\",\n value: function applySelection() {\n var selected = this.getSelectedIndex();\n this.domNode.querySelectorAll('.bjs-cell-card').forEach(function (card, i) {\n card.classList.toggle('is-selected', i === selected);\n if (i === selected) card.setAttribute('aria-selected', 'true');else card.removeAttribute('aria-selected');\n });\n }\n }, {\n key: \"_refreshPresetActive\",\n value: function _refreshPresetActive() {\n var activeId = this._activePresetId();\n this.domNode.querySelectorAll('.bjs-cell-manager-preset').forEach(function (btn) {\n btn.classList.toggle('is-active', btn.getAttribute('data-preset') === activeId);\n });\n }\n }, {\n key: \"_refreshMultiSelectClasses\",\n value: function _refreshMultiSelectClasses() {\n var _this5 = this;\n this.domNode.querySelectorAll('.bjs-cell-card').forEach(function (card, i) {\n card.classList.toggle('is-multi-selected', _this5._multiSelected.has(i));\n });\n /* Toggle the bulk bar via full re-render of that block only. Cheap — the\n bulk bar DOM is ~3 elements, and multi-select state is infrequent. */\n var host = this.domNode.querySelector('.bjs-cell-manager-bulk');\n var fresh = this._renderBulkBar();\n if (host && fresh) {\n host.outerHTML = fresh;\n this._bindBulkEvents();\n } else if (host && !fresh) {\n host.remove();\n } else if (!host && fresh) {\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n if (strip) strip.insertAdjacentHTML('afterend', fresh);\n this._bindBulkEvents();\n }\n }\n }, {\n key: \"_bindBulkEvents\",\n value: function _bindBulkEvents() {\n var _this6 = this;\n var del = this.domNode.querySelector('[data-control=\"bulk-delete\"]');\n var clear = this.domNode.querySelector('[data-control=\"bulk-clear\"]');\n if (del) {\n del.addEventListener('click', function () {\n return _this6._bulkDelete();\n });\n }\n if (clear) {\n clear.addEventListener('click', function () {\n _this6._multiSelected.clear();\n _this6._refreshMultiSelectClasses();\n });\n }\n }\n }, {\n key: \"_bulkDelete\",\n value: function _bulkDelete() {\n var _this7 = this;\n var total = this.getItemCount();\n if (total <= 1) return; // never delete the last cell\n // Include the primary selection in the bulk set (so Shift-select + Delete\n // behaves the way users expect — \"these + my current one\").\n var primary = this.getSelectedIndex();\n var set = new Set(this._multiSelected);\n if (primary >= 0) set.add(primary);\n // Never delete ALL cells — leave at least one standing.\n if (set.size >= total) {\n // Drop the highest index so the surviving cell is \"cell #1\".\n var sorted = Array.from(set).sort(function (a, b) {\n return b - a;\n });\n set[\"delete\"](sorted[0]);\n }\n if (!set.size) return;\n var descending = Array.from(set).sort(function (a, b) {\n return b - a;\n });\n this._multiSelected.clear();\n if (this.callback && typeof this.callback.removeCells === 'function') {\n this.callback.removeCells(descending);\n } else if (this.callback && typeof this.callback.removeCell === 'function') {\n descending.forEach(function (i) {\n return _this7.callback.removeCell(i);\n });\n }\n this.render();\n }\n\n /** Pointer-based drag-reorder on a card handle. Uses PointerCaptureRegistry\n * so lost-pointer cleanup happens automatically if the panel is torn down\n * mid-drag. A drop indicator line follows the pointer and snaps to the\n * nearest gap midpoint (between cards or at the outer edge).\n */\n }, {\n key: \"_startHandleDrag\",\n value: function _startHandleDrag(handle, card, ev) {\n var _this8 = this;\n if (ev.button !== undefined && ev.button !== 0) return;\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n if (!strip) return;\n var sourceIdx = parseInt(card.getAttribute('data-cell-index'), 10);\n if (isNaN(sourceIdx)) return;\n ev.preventDefault();\n ev.stopPropagation();\n\n // Create drop indicator lazily — once per drag.\n var indicator = strip.querySelector('.bjs-cell-manager-drop-indicator');\n if (!indicator) {\n indicator = document.createElement('div');\n indicator.className = 'bjs-cell-manager-drop-indicator';\n strip.appendChild(indicator);\n }\n indicator.classList.add('is-visible');\n card.classList.add('is-dragging');\n strip.classList.add('is-dragging');\n _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].acquire(handle, ev.pointerId);\n var onMove = function onMove(e) {\n var slot = _this8._hitTestDropSlot(e.clientX);\n _this8._dragState.dropSlot = slot;\n _this8._paintDropIndicator(indicator, slot);\n };\n var onUp = function onUp() {\n var dest = _this8._dragState ? _this8._dragState.dropSlot : null;\n _this8._endHandleDrag(handle, card, indicator);\n if (dest !== null && _this8.callback && typeof _this8.callback.moveCell === 'function') {\n _this8.callback.moveCell(sourceIdx, dest);\n }\n // Re-render the panel so card indices + preset highlight reflect the\n // new order. Use the existing render path so ResizeObserver + slot\n // positioning re-attach cleanly.\n _this8.render();\n };\n var onCancel = function onCancel() {\n return _this8._endHandleDrag(handle, card, indicator);\n };\n this._dragState = {\n sourceIdx: sourceIdx,\n pointerId: ev.pointerId,\n dropSlot: null,\n handle: handle,\n onMove: onMove,\n onUp: onUp,\n onCancel: onCancel\n };\n handle.addEventListener('pointermove', onMove);\n handle.addEventListener('pointerup', onUp);\n handle.addEventListener('pointercancel', onCancel);\n handle.addEventListener('lostpointercapture', onCancel);\n\n // First paint — show the indicator at the drag source so the UI confirms\n // the interaction started. hitTest may return null if pointer is inside\n // the source card itself (no valid move), which _paintDropIndicator\n // handles by hiding the indicator.\n var slot0 = this._hitTestDropSlot(ev.clientX);\n this._dragState.dropSlot = slot0;\n this._paintDropIndicator(indicator, slot0);\n }\n }, {\n key: \"_endHandleDrag\",\n value: function _endHandleDrag(handle, card, indicator) {\n var st = this._dragState;\n this._dragState = null;\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n if (strip) strip.classList.remove('is-dragging');\n if (card) card.classList.remove('is-dragging');\n if (indicator) indicator.classList.remove('is-visible');\n if (st) {\n try {\n handle.removeEventListener('pointermove', st.onMove);\n } catch (_e) {}\n try {\n handle.removeEventListener('pointerup', st.onUp);\n } catch (_e) {}\n try {\n handle.removeEventListener('pointercancel', st.onCancel);\n } catch (_e) {}\n try {\n handle.removeEventListener('lostpointercapture', st.onCancel);\n } catch (_e) {}\n try {\n _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].release(handle, st.pointerId);\n } catch (_e) {}\n }\n }\n\n /** Given a pointer X (clientX), find the nearest drop slot (0..N). Returns\n * null when the pointer is over the source card itself OR the immediately\n * adjacent slots — those are no-op moves (the cell stays where it is). */\n }, {\n key: \"_hitTestDropSlot\",\n value: function _hitTestDropSlot(clientX) {\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n if (!strip) return null;\n var cards = Array.from(strip.querySelectorAll(':scope > .bjs-cell-card'));\n if (!cards.length) return null;\n var stripRect = strip.getBoundingClientRect();\n var relX = clientX - stripRect.left;\n\n // Build gap-midpoint candidates: slot 0 at left edge, slot N at right edge,\n // slot i (0<i<N) between card[i-1] and card[i].\n var midpoints = [];\n midpoints.push(cards[0].getBoundingClientRect().left - stripRect.left - 8);\n for (var i = 1; i < cards.length; i++) {\n var a = cards[i - 1].getBoundingClientRect().right - stripRect.left;\n var b = cards[i].getBoundingClientRect().left - stripRect.left;\n midpoints.push((a + b) / 2);\n }\n midpoints.push(cards[cards.length - 1].getBoundingClientRect().right - stripRect.left + 8);\n var bestI = 0;\n var bestDist = Infinity;\n midpoints.forEach(function (x, i) {\n var d = Math.abs(x - relX);\n if (d < bestDist) {\n bestDist = d;\n bestI = i;\n }\n });\n\n // Reject no-op slots (source and source+1 both resolve back to same cell).\n var src = this._dragState ? this._dragState.sourceIdx : -1;\n if (src === bestI || src + 1 === bestI) return null;\n return bestI;\n }\n }, {\n key: \"_paintDropIndicator\",\n value: function _paintDropIndicator(indicator, slot) {\n if (!indicator) return;\n if (slot === null || slot === undefined) {\n indicator.classList.remove('is-visible');\n return;\n }\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n if (!strip) return;\n var cards = Array.from(strip.querySelectorAll(':scope > .bjs-cell-card'));\n var stripRect = strip.getBoundingClientRect();\n var xPx;\n if (slot === 0) {\n xPx = Math.max(0, cards[0].getBoundingClientRect().left - stripRect.left - 4);\n } else if (slot >= cards.length) {\n xPx = Math.min(stripRect.width, cards[cards.length - 1].getBoundingClientRect().right - stripRect.left + 4);\n } else {\n var a = cards[slot - 1].getBoundingClientRect().right - stripRect.left;\n var b = cards[slot].getBoundingClientRect().left - stripRect.left;\n xPx = (a + b) / 2;\n }\n indicator.style.left = \"\".concat(xPx, \"px\");\n indicator.classList.add('is-visible');\n }\n\n /** Pointer-based resize between two adjacent cells. Computes new left/right\n * percent of their combined span as the pointer moves; snap magnets engage\n * near the canonical ratios (see SNAP_RATIOS). Preview-only until pointerup\n * — final widths are committed in a single `resizeCellPair` call so the\n * rebalance banner doesn't flicker. */\n }, {\n key: \"_startResizeDrag\",\n value: function _startResizeDrag(grip, ev) {\n var _this9 = this;\n if (ev.button !== undefined && ev.button !== 0) return;\n var leftIdx = parseInt(grip.parentElement.getAttribute('data-resizer-left'), 10);\n if (isNaN(leftIdx)) return;\n var widths = this.getCellWidths();\n var lPct = this._asPct(widths[leftIdx]);\n var rPct = this._asPct(widths[leftIdx + 1]);\n if (lPct === null || rPct === null) return;\n ev.preventDefault();\n ev.stopPropagation();\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n var combined = lPct + rPct; // the \"budget\" for this pair\n\n var leftCard = strip.querySelectorAll(':scope > .bjs-cell-card')[leftIdx];\n var rightCard = strip.querySelectorAll(':scope > .bjs-cell-card')[leftIdx + 1];\n var leftRect = leftCard.getBoundingClientRect();\n var rightRect = rightCard.getBoundingClientRect();\n var pxLeft = leftRect.left;\n var pxRight = rightRect.right;\n var pxSpan = pxRight - pxLeft;\n this._resizeState = {\n grip: grip,\n pointerId: ev.pointerId,\n leftIdx: leftIdx,\n startL: lPct,\n startR: rPct,\n combined: combined,\n pxLeft: pxLeft,\n pxSpan: pxSpan,\n currL: lPct,\n currR: rPct\n };\n strip.parentElement.classList.add('is-resizing');\n this.domNode.classList.add('is-measuring');\n grip.parentElement.classList.add('is-dragging');\n _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].acquire(grip, ev.pointerId);\n var onMove = function onMove(e) {\n return _this9._applyResizePreview(e.clientX);\n };\n var onUp = function onUp() {\n return _this9._finishResize(false);\n };\n var onCancel = function onCancel() {\n return _this9._finishResize(true);\n };\n this._resizeState.onMove = onMove;\n this._resizeState.onUp = onUp;\n this._resizeState.onCancel = onCancel;\n grip.addEventListener('pointermove', onMove);\n grip.addEventListener('pointerup', onUp);\n grip.addEventListener('pointercancel', onCancel);\n grip.addEventListener('lostpointercapture', onCancel);\n }\n\n /** Update card DOM + tooltip during resize drag. Does NOT call setFormat —\n * that fires on pointerup so undo stack stays single-entry per drag. */\n }, {\n key: \"_applyResizePreview\",\n value: function _applyResizePreview(clientX) {\n var st = this._resizeState;\n if (!st) return;\n var rel = Math.max(0, Math.min(st.pxSpan, clientX - st.pxLeft));\n var ratio = rel / st.pxSpan; // 0..1 — fraction of combined given to LEFT cell\n\n // Snap check — if ratio is within tolerance of a canonical snap, lock it.\n var snapLabel = null;\n for (var _i2 = 0, _SNAP_RATIOS = SNAP_RATIOS; _i2 < _SNAP_RATIOS.length; _i2++) {\n var s = _SNAP_RATIOS[_i2];\n if (Math.abs(ratio - s.v) <= SNAP_TOLERANCE) {\n ratio = s.v;\n snapLabel = s.label;\n break;\n }\n }\n var l = Math.max(1, Math.min(99, ratio * st.combined));\n var r = Math.max(1, st.combined - l);\n st.currL = l;\n st.currR = r;\n st.snapLabel = snapLabel;\n\n // Paint neighbors' flex in place (no full re-render).\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n var leftCard = strip.querySelectorAll(':scope > .bjs-cell-card')[st.leftIdx];\n var rightCard = strip.querySelectorAll(':scope > .bjs-cell-card')[st.leftIdx + 1];\n if (leftCard) {\n leftCard.style.cssText = \"flex: 0 0 \".concat(l, \"%;\");\n var lbl = leftCard.querySelector('.bjs-cell-card-width');\n if (lbl) lbl.textContent = \"\".concat(Math.round(l * 100) / 100, \"%\");\n }\n if (rightCard) {\n rightCard.style.cssText = \"flex: 0 0 \".concat(r, \"%;\");\n var _lbl = rightCard.querySelector('.bjs-cell-card-width');\n if (_lbl) _lbl.textContent = \"\".concat(Math.round(r * 100) / 100, \"%\");\n }\n\n // Tooltip\n var tip = st.grip.parentElement.querySelector('.bjs-cell-manager-resizer-tip');\n if (tip) {\n var val = tip.querySelector('.bjs-cell-manager-resizer-tip-value');\n if (val) val.innerHTML = snapLabel ? \"<strong>\".concat(snapLabel, \"</strong> <span class=\\\"bjs-cell-manager-resizer-tip-pct\\\">\").concat(Math.round(l), \"% / \").concat(Math.round(r), \"%</span>\") : \"\".concat(Math.round(l * 100) / 100, \"% / \").concat(Math.round(r * 100) / 100, \"%\");\n tip.classList.add('is-visible');\n tip.classList.toggle('is-snapped', !!snapLabel);\n }\n\n // Ruler active-tick highlight — light up the major ticks nearest the\n // preview value so the author sees alignment opportunities.\n this._updateRulerSnap(l);\n\n // Slot positions + sibling resizers depend on flex widths → re-measure.\n this._positionSlots();\n }\n }, {\n key: \"_updateRulerSnap\",\n value: function _updateRulerSnap(leftPct) {\n if (!this.domNode) return;\n var ticks = this.domNode.querySelectorAll('.bjs-cell-manager-ruler-tick');\n ticks.forEach(function (t) {\n var v = parseFloat(t.getAttribute('data-ruler'));\n t.classList.toggle('is-active', !isNaN(v) && Math.abs(v - leftPct) < 2);\n });\n }\n }, {\n key: \"_finishResize\",\n value: function _finishResize(cancelled) {\n var st = this._resizeState;\n this._resizeState = null;\n if (!st) return;\n var grip = st.grip;\n var resizerEl = grip.parentElement;\n var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n if (strip && strip.parentElement) strip.parentElement.classList.remove('is-resizing');\n this.domNode.classList.remove('is-measuring');\n if (resizerEl) resizerEl.classList.remove('is-dragging');\n var tip = resizerEl ? resizerEl.querySelector('.bjs-cell-manager-resizer-tip') : null;\n if (tip) {\n tip.classList.remove('is-visible');\n tip.classList.remove('is-snapped');\n }\n try {\n grip.removeEventListener('pointermove', st.onMove);\n } catch (_e) {}\n try {\n grip.removeEventListener('pointerup', st.onUp);\n } catch (_e) {}\n try {\n grip.removeEventListener('pointercancel', st.onCancel);\n } catch (_e) {}\n try {\n grip.removeEventListener('lostpointercapture', st.onCancel);\n } catch (_e) {}\n try {\n _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].release(grip, st.pointerId);\n } catch (_e) {}\n\n // Clear ruler snap highlight.\n this.domNode.querySelectorAll('.bjs-cell-manager-ruler-tick.is-active').forEach(function (t) {\n return t.classList.remove('is-active');\n });\n if (cancelled) {\n // Restore starting widths via callback — NOT just CSS — so the underlying\n // formatter doesn't drift. Cheaper than a full render().\n if (this.callback && typeof this.callback.resizeCellPair === 'function') {\n this.callback.resizeCellPair(st.leftIdx, st.startL, st.startR);\n }\n this.applyCardWidths();\n return;\n }\n\n // Commit final widths via callback — single formatter tick.\n if (this.callback && typeof this.callback.resizeCellPair === 'function') {\n this.callback.resizeCellPair(st.leftIdx, st.currL, st.currR);\n }\n this._dismissed = false;\n this.applyCardWidths();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this10 = this;\n // GridElement now does incremental DOM updates (no full re-render on\n // add/remove), so the settings panel is NOT torn down. Our panel\n // repaint can therefore be synchronous — reflects the latest cell\n // count immediately.\n //\n // Add cell (end)\n this.domNode.querySelectorAll('[data-control=\"add-cell\"]').forEach(function (btn) {\n btn.addEventListener('click', function () {\n if (_this10.callback && typeof _this10.callback.addCell === 'function') {\n _this10.callback.addCell();\n _this10.render();\n }\n });\n });\n\n // Add at specific index (inline insert slots)\n this.domNode.querySelectorAll('[data-control=\"add-cell-at\"]').forEach(function (btn) {\n btn.addEventListener('click', function () {\n var idx = parseInt(btn.getAttribute('data-index'), 10);\n if (_this10.callback && typeof _this10.callback.addCellAt === 'function') {\n _this10.callback.addCellAt(idx);\n _this10.render();\n }\n });\n });\n\n // Remove cell\n this.domNode.querySelectorAll('[data-control=\"remove-cell\"]').forEach(function (btn) {\n btn.addEventListener('click', function (e) {\n e.stopPropagation(); // don't also trigger card selection\n var idx = parseInt(btn.getAttribute('data-index'), 10);\n if (_this10.callback && typeof _this10.callback.removeCell === 'function') {\n _this10.callback.removeCell(idx);\n _this10.render();\n }\n });\n });\n\n // Card click — primary select OR bulk toggle (Shift/Cmd)\n this.domNode.querySelectorAll('.bjs-cell-card').forEach(function (card) {\n card.addEventListener('click', function (e) {\n var idx = parseInt(card.getAttribute('data-cell-index'), 10);\n if (isNaN(idx)) return;\n\n // Ignore clicks that landed on a button child (those already handled\n // their own event); click on handle also bails — handle is a drag\n // affordance, not a select affordance.\n if (e.target.closest('.bjs-cell-card-remove, .bjs-cell-card-handle')) return;\n if (e.shiftKey) {\n // Range select from primary selection to clicked idx\n var primary = _this10.getSelectedIndex();\n if (primary >= 0 && primary !== idx) {\n var _ref = primary < idx ? [primary, idx] : [idx, primary],\n _ref2 = _slicedToArray(_ref, 2),\n lo = _ref2[0],\n hi = _ref2[1];\n for (var i = lo; i <= hi; i++) if (i !== primary) _this10._multiSelected.add(i);\n } else {\n _this10._multiSelected.add(idx);\n }\n _this10._refreshMultiSelectClasses();\n return;\n }\n if (e.ctrlKey || e.metaKey) {\n if (_this10._multiSelected.has(idx)) _this10._multiSelected[\"delete\"](idx);else _this10._multiSelected.add(idx);\n _this10._refreshMultiSelectClasses();\n return;\n }\n\n // Plain click → primary select + clear multi-selection\n if (_this10._multiSelected.size) {\n _this10._multiSelected.clear();\n _this10._refreshMultiSelectClasses();\n }\n if (_this10.callback && typeof _this10.callback.selectCell === 'function') {\n _this10.callback.selectCell(idx);\n }\n });\n });\n\n // Drag handle — pointer-based drag-reorder (Phase-3 W6.1)\n this.domNode.querySelectorAll('.bjs-cell-card-handle').forEach(function (handle) {\n var card = handle.closest('.bjs-cell-card');\n if (!card) return;\n // Block the browser's native drag on the icon span inside the handle —\n // we use pointer events, not HTML5 DnD.\n handle.addEventListener('dragstart', function (e) {\n return e.preventDefault();\n });\n handle.addEventListener('pointerdown', function (e) {\n return _this10._startHandleDrag(handle, card, e);\n });\n // Keyboard reorder — ArrowLeft / ArrowRight while the handle has focus\n // moves the cell one slot in the chosen direction. Accessibility parity\n // with pointer drag.\n handle.addEventListener('keydown', function (e) {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;\n var idx = parseInt(card.getAttribute('data-cell-index'), 10);\n if (isNaN(idx)) return;\n var total = _this10.getItemCount();\n var target = e.key === 'ArrowLeft' ? idx - 1 : idx + 2; // slot semantics\n if (target < 0 || target > total) return;\n if (!_this10.callback || typeof _this10.callback.moveCell !== 'function') return;\n e.preventDefault();\n _this10.callback.moveCell(idx, target);\n _this10.render();\n // Re-focus the handle on the new card so the user can keep arrowing.\n requestAnimationFrame(function () {\n var newIdx = e.key === 'ArrowLeft' ? idx - 1 : idx + 1;\n var newCard = _this10.domNode.querySelector(\".bjs-cell-card[data-cell-index=\\\"\".concat(newIdx, \"\\\"] .bjs-cell-card-handle\"));\n if (newCard && typeof newCard.focus === 'function') newCard.focus();\n });\n });\n });\n\n // Layout presets\n this.domNode.querySelectorAll('.bjs-cell-manager-preset').forEach(function (btn) {\n btn.addEventListener('click', function () {\n var id = btn.getAttribute('data-preset');\n var preset = LAYOUT_PRESETS.find(function (p) {\n return p.id === id;\n });\n if (!preset) return;\n if (_this10.callback && typeof _this10.callback.applyPreset === 'function') {\n // A fresh preset resets the \"user has dismissed the alert\" flag —\n // the banner should appear again if the new preset over/under-fills.\n _this10._dismissed = false;\n _this10._multiSelected.clear();\n _this10.callback.applyPreset(preset.widths.slice());\n _this10.render();\n }\n });\n });\n\n // Rebalance alert actions (only present when the row sums != 100%).\n var alertRebalance = this.domNode.querySelector('[data-control=\"alert-rebalance\"]');\n if (alertRebalance) {\n alertRebalance.addEventListener('click', function () {\n if (_this10.callback && typeof _this10.callback.rebalanceProportional === 'function') {\n _this10.callback.rebalanceProportional();\n _this10._dismissed = false;\n _this10.render();\n }\n });\n }\n var alertEqualize = this.domNode.querySelector('[data-control=\"alert-equalize\"]');\n if (alertEqualize) {\n alertEqualize.addEventListener('click', function () {\n if (_this10.callback && typeof _this10.callback.equalize === 'function') {\n _this10.callback.equalize();\n _this10._dismissed = false;\n _this10.render();\n }\n });\n }\n var alertDismiss = this.domNode.querySelector('[data-control=\"alert-dismiss\"]');\n if (alertDismiss) {\n alertDismiss.addEventListener('click', function () {\n _this10._dismissed = true;\n _this10.render();\n });\n }\n\n // Resizer grips — pointer-based snap-resize (Phase-3 W6.1)\n this.domNode.querySelectorAll('.bjs-cell-manager-resizer-grip').forEach(function (grip) {\n grip.addEventListener('dragstart', function (e) {\n return e.preventDefault();\n });\n grip.addEventListener('pointerdown', function (e) {\n return _this10._startResizeDrag(grip, e);\n });\n });\n this._bindBulkEvents();\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/GridControl.js?");
/***/ }),
/***/ "./src/includes/GridElement.js":
/*!*************************************!*\
!*** ./src/includes/GridElement.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _CellElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CellElement.js */ \"./src/includes/CellElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _DimensionControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./DimensionControl.js */ \"./src/includes/DimensionControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _GridControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./GridControl.js */ \"./src/includes/GridControl.js\");\n/* harmony import */ var _RangeControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./RangeControl.js */ \"./src/includes/RangeControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _overlays_GridStructureOverlay_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./overlays/GridStructureOverlay.js */ \"./src/includes/overlays/GridStructureOverlay.js\");\n/* harmony import */ var _overlays_GridColumnResizeOverlay_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./overlays/GridColumnResizeOverlay.js */ \"./src/includes/overlays/GridColumnResizeOverlay.js\");\n/* harmony import */ var _overlays_GridInsertColumnOverlay_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./overlays/GridInsertColumnOverlay.js */ \"./src/includes/overlays/GridInsertColumnOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar GridElement = /*#__PURE__*/function (_BaseElement) {\n function GridElement(template) {\n var _this;\n _classCallCheck(this, GridElement);\n _this = _callSuper(this, GridElement);\n _this.template = template;\n _this.cells = [];\n _this.domNode = null;\n _this.requiredTemplateKeys = ['cells'];\n _this.cell_gap = 0;\n\n // `align_items` controls cell HEIGHT (stretch = equal, others = auto\n // with vertical positioning). Default 'stretch' matches Webflow /\n // Figma / Tailwind / CSS flex default — coloring a cell background\n // fills the cell edge-to-edge without leaving a gap under shorter\n // content. Existing samples with staggered heights can opt into\n // 'flex-start' via the Cell Alignment control.\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"]({\n background_color: null,\n background_image: null,\n background_position: null,\n background_size: null,\n background_repeat: null,\n background_blend_mode: null,\n opacity: null,\n filter: null,\n align_items: 'stretch'\n });\n return _this;\n }\n _inherits(GridElement, _BaseElement);\n return _createClass(GridElement, [{\n key: \"getName\",\n value: function getName() {\n return 'Grid';\n }\n }, {\n key: \"isHoverable\",\n value: function isHoverable() {\n return false;\n }\n\n /**\n * Canvas overlays:\n * - GridStructureOverlay (Phase 1.3) — dashed cell boundaries\n * - n-1 × GridColumnResizeOverlay (Phase 1.3) — drag separators\n * - n+1 × GridInsertColumnOverlay (Phase 1.5) — \"+\" insert buttons,\n * one before cell 0, then one after each cell\n *\n * Total instances for n cells: 1 + (n-1) + (n+1) = 2n+1.\n *\n * Trigger: 'select' (isHoverable() === false — SA invariant I7).\n * Mount path: user selects grid via breadcrumb or GridControl card.\n * See docs/core/OVERLAY.md §7.1 + docs/archived/OVERLAY_PLAN.md §3.4 + §3.6.\n */\n }, {\n key: \"getOverlays\",\n value: function getOverlays() {\n var overlays = [new _overlays_GridStructureOverlay_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](this)];\n var n = Array.isArray(this.cells) ? this.cells.length : 0;\n for (var i = 0; i < n - 1; i++) {\n overlays.push(new _overlays_GridColumnResizeOverlay_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](this, {\n boundaryIndex: i\n }));\n }\n // Insert buttons: one per insertion boundary. Skip when grid is\n // empty (no boundaries yet — addCell flow is via the sidebar\n // GridControl in that state).\n if (n > 0) {\n for (var _i = 0; _i <= n; _i++) {\n overlays.push(new _overlays_GridInsertColumnOverlay_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"](this, {\n insertAt: _i,\n boundary: _i === 0 ? 'before' : 'after'\n }));\n }\n }\n return overlays;\n }\n\n /** Host-injection recursion hook — returns this grid's cells so\n * Builder._adopt() can walk down the tree. See BUILDER.md \"Host\n * Injection\" lesson. */\n }, {\n key: \"getChildren\",\n value: function getChildren() {\n return this.cells || [];\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n var _this2 = this;\n while (this.domNode.firstChild) {\n this.domNode.removeChild(this.domNode.firstChild);\n }\n\n // 2026-04-18 refactor — drop the cell-anchor text-placeholder pattern.\n // Previously each cell was represented in the template as\n // `<div cell-anchor=\"ID\">ID</div>` and the JS loop swapped the\n // anchor for the real cell DOM. If any step failed (or rendered\n // on a stale DOM snapshot), the anchor's text content — the raw\n // cell ID like `_0xrafirbu` — leaked through visibly on canvas\n // (user report 2026-04-18 after add-cell action). Fix: render the\n // Grid wrapper EMPTY, then DOM-append each cell's domNode directly.\n // No text placeholders → nothing to leak.\n // formatter auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n cells: [],\n // wrapper only — cells attach below\n cell_gap: this.cell_gap,\n align_items: this.formatter.getFormat('align_items') || 'stretch'\n });\n var wrapper = this.domNode.firstElementChild;\n if (!wrapper) return;\n this.cells.forEach(function (cell) {\n var cellDom = cell.render();\n wrapper.appendChild(cellDom);\n _this2.host.uiManager.addElement(cell);\n });\n }\n }, {\n key: \"addCell\",\n value: function addCell() {\n var cell = this.newCell();\n cell.formatter.setFormat('width', this._defaultWidthForNewCell());\n this.append(cell);\n // 2026-04-18 auto-distribute on add: proportionally scale all %-cells\n // (including the new one) so the row sums to exactly 100%. Prevents\n // the \"new cell overflows canvas\" UX issue the user flagged. Keeps\n // authored ratios between existing cells. The explicit Rebalance\n // button (`.bjs-cell-manager-alert`) still fires for MANUAL width\n // edits that break the 100% invariant — this block only handles the\n // structural add/remove path.\n //\n // Incremental DOM append — DON'T full-re-render. A full render()\n // was tearing down the settings panel (selection events cascade\n // through uiManager.addElement for EVERY cell) while the\n // GridControl was mid-repaint, so the cell-manager ended up on a\n // detached DOM and never reflected the new count (2026-04-18\n // regression).\n this.rebalanceCellsProportional();\n this._appendCellDom(cell);\n }\n\n /** Pick a reasonable width for a newly-added cell so it actually\n * appears on canvas. Mirrors existing cells' semantic:\n * - all cells bare-number grow-share → new cell gets the mean of\n * existing ratios (e.g. [50, 50] → new cell = 50, ratio 1:1:1)\n * - all cells % → new cell = 100 / (n + 1) as a % (auto-rebalance on\n * the new-cell side only; existing cells keep their values so the\n * user's carefully-set ratios aren't destroyed)\n * - cells in px/em/rem → new cell copies the last cell's width\n * - mixed / auto → new cell = 'auto' (grow-share 1 — safe default)\n *\n * Does NOT mutate other cells. If the author later wants full\n * re-normalisation they use a layout preset.\n */\n }, {\n key: \"_defaultWidthForNewCell\",\n value: function _defaultWidthForNewCell() {\n if (this.cells.length === 0) return 'auto';\n var widths = this.cells.map(function (c) {\n return c.formatter.getFormat('width', 'auto');\n });\n\n // All-% (post-legacy-upgrade normal case): pick 100/(n+1)% so the\n // row sums > 100% (overflow). GridControl surfaces this via the\n // rebalance alert banner — the user sees the overflow and chooses\n // an action (see Lesson 22). We deliberately don't silently shrink\n // existing cells — destroying authored ratios is worse UX than a\n // visible banner.\n var allPct = widths.every(function (w) {\n return typeof w === 'string' && /%$/.test(String(w).trim());\n });\n if (allPct) {\n var next = Math.floor(10000 / (this.cells.length + 1)) / 100;\n return \"\".concat(next, \"%\");\n }\n\n // All grow-share bare (legacy 3rd-party data that escaped the\n // GridElement.parse upgrade — possible for in-memory widgets built\n // without going through parse()). Emit a % for the new cell so it\n // stays visible.\n var allBare = widths.every(function (w) {\n return typeof w === 'number' || typeof w === 'string' && /^-?[\\d.]+$/.test(String(w).trim());\n });\n if (allBare) {\n var nums = widths.map(function (w) {\n return parseFloat(w);\n });\n var sum = nums.reduce(function (a, b) {\n return a + b;\n }, 0);\n if (sum > 0) {\n var mean = Math.round(sum / nums.length / sum * 10000) / 100;\n return \"\".concat(mean, \"%\");\n }\n return '50%';\n }\n\n // All fixed-unit (px/em/rem/vw/vh): copy the last cell's width —\n // author is in a pixel-grid mode and probably wants consistency.\n var lastW = widths[widths.length - 1];\n if (typeof lastW === 'string' && /(px|em|rem|vw|vh)$/i.test(lastW)) {\n return lastW;\n }\n\n // Mixed (auto + something else) — new cell = 'auto' to avoid\n // disturbing the other cells' implicit sizing assumptions.\n return 'auto';\n }\n }, {\n key: \"append\",\n value: function append(cell) {\n cell.container = this;\n // Host injection — propagate this grid's host onto the new cell\n // (and its subtree). Safe before the grid itself is adopted: in\n // that case `this.host` is null and `_adopt` is a no-op; the\n // caller's later `_adopt(grid)` will recurse and reach the cell.\n if (this.host && typeof this.host._adopt === 'function') {\n this.host._adopt(cell);\n }\n this.cells.push(cell);\n }\n }, {\n key: \"removeCellByIndex\",\n value: function removeCellByIndex(index) {\n var cell = this.cells[index];\n this.cells.splice(index, 1);\n if (cell && cell.domNode && cell.domNode.parentNode) {\n cell.domNode.parentNode.removeChild(cell.domNode);\n }\n // Auto-refill — remaining %-cells scale up so the row sums back to\n // 100%. Example: [25%, 25%, 25%, 25%] delete #3 → [33.33%, 33.33%,\n // 33.34%]. Manual Rebalance button still exists for when the user\n // drags sliders into an invalid sum.\n this.rebalanceCellsProportional();\n }\n }, {\n key: \"appendCells\",\n value: function appendCells(cells) {\n var _this3 = this;\n cells.forEach(function (cell) {\n _this3.append(cell);\n });\n }\n }, {\n key: \"removeElement\",\n value: function removeElement(element) {\n var _this4 = this;\n this.cells.forEach(function (currentElement) {\n if (currentElement == element) {\n _this4.cells = _this4.cells.filter(function (el) {\n return el !== element;\n });\n _this4.render();\n if (!_this4.cells.length) {\n _this4.remove();\n _this4.host.unselect();\n }\n }\n });\n }\n }, {\n key: \"insertElementAfter\",\n value: function insertElementAfter(element, newElement) {\n var _this5 = this;\n newElement.container = this;\n this.cells.forEach(function (currentElement, i) {\n if (currentElement === element) {\n _this5.cells.splice(i + 1, 0, newElement);\n _this5.render();\n return;\n }\n });\n }\n }, {\n key: \"newCell\",\n value: function newCell() {\n // Pre-existing bug surfaced 2026-04-18 when addCell() started calling\n // cell.render() incrementally: `this.template` here is the GRID's\n // template (e.g. 'Grid'), NOT the cell template. Rendering the Grid\n // template as a cell threw `align_items is not defined`. The old flow\n // never hit this because `addCell()` didn't render the new cell — it\n // just pushed to this.cells. Fix: mirror existing cells' template,\n // or fall back to 'Cell' (the canonical name used by GridWidget +\n // every sample JSON's cell data).\n var cellTemplate = this.cells.length > 0 ? this.cells[0].template : 'Cell';\n var cell = new _CellElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](cellTemplate);\n cell.container = this;\n return cell;\n }\n }, {\n key: \"addCellAt\",\n value: function addCellAt(index) {\n var newCell = this.newCell();\n // Host injection — newCell is a fresh `new CellElement(...)` with\n // no host yet. Adopt before insert so its overlays/controls can\n // reach the bus + flags from first render.\n if (this.host && typeof this.host._adopt === 'function') {\n this.host._adopt(newCell);\n }\n newCell.formatter.setFormat('width', this._defaultWidthForNewCell());\n newCell.container = this;\n if (index === 0) {\n this.cells.unshift(newCell);\n } else if (index >= this.cells.length) {\n this.cells.push(newCell);\n } else {\n this.cells.splice(index, 0, newCell);\n }\n // Auto-distribute on insert — see addCell() for rationale.\n this.rebalanceCellsProportional();\n this._appendCellDom(newCell, index);\n return newCell;\n }\n\n /** DOM-append (or insert at index) a single cell without triggering\n * full GridElement.render(). Preserves the existing cell DOM nodes\n * and their canvas selection state. */\n }, {\n key: \"_appendCellDom\",\n value: function _appendCellDom(cell, index) {\n if (!this.domNode) {\n // No DOM yet — caller should invoke render() instead.\n this.render();\n return;\n }\n var wrapper = this.domNode.firstElementChild;\n if (!wrapper) {\n this.render();\n return;\n }\n var cellDom = cell.render();\n if (typeof index === 'number') {\n var siblings = wrapper.querySelectorAll(':scope > [builder-element=\"CellElement\"]');\n if (index >= siblings.length) {\n wrapper.appendChild(cellDom);\n } else {\n wrapper.insertBefore(cellDom, siblings[index]);\n }\n } else {\n wrapper.appendChild(cellDom);\n }\n this.host.uiManager.addElement(cell);\n }\n\n /** Apply a layout preset — overwrite cell count + per-cell widths in one\n * atomic change. Added cells get a default formatter; removed cells are\n * dropped wholesale. */\n }, {\n key: \"applyLayoutPreset\",\n value: function applyLayoutPreset(widths) {\n var target = widths.length;\n while (this.cells.length < target) {\n this.append(this.newCell());\n }\n while (this.cells.length > target) {\n this.cells.pop();\n }\n // LAYOUT_PRESETS carries grow-share ratios (e.g. [1, 1] or [1, 2]).\n // We convert those to explicit percents summing to 100% so the\n // stored format matches the \"all-% authoring\" convention (2026-04-18).\n // Mixed patterns like ['auto'] pass through unchanged.\n var normalized = widths.map(function (w) {\n if (w === 'auto' || w === null || w === undefined || w === '') return 'auto';\n if (typeof w === 'string' && /%$/.test(w)) return w;\n return w;\n });\n var barePattern = normalized.every(function (w) {\n return typeof w === 'number' || typeof w === 'string' && /^-?\\d+(\\.\\d+)?$/.test(w.trim());\n });\n var finalWidths = normalized;\n if (barePattern) {\n var nums = normalized.map(function (w) {\n return parseFloat(w);\n });\n var sum = nums.reduce(function (a, b) {\n return a + b;\n }, 0);\n if (sum > 0) {\n var pcts = nums.map(function (n) {\n return Math.round(n / sum * 10000) / 100;\n });\n var residue = Math.round((100 - pcts.reduce(function (a, b) {\n return a + b;\n }, 0)) * 100) / 100;\n if (Math.abs(residue) >= 0.01) pcts[pcts.length - 1] = Math.round((pcts[pcts.length - 1] + residue) * 100) / 100;\n finalWidths = pcts.map(function (v) {\n return \"\".concat(v, \"%\");\n });\n }\n }\n this.cells.forEach(function (cell, i) {\n cell.formatter.setFormat('width', finalWidths[i]);\n });\n this.render();\n }\n\n /** Programmatic cell selection — called by GridControl when user clicks\n * a card. Routes through the host (per-instance) which handles the\n * highlight + settings panel rebuild. */\n }, {\n key: \"selectCellAt\",\n value: function selectCellAt(index) {\n var _this$host;\n var cell = this.cells[index];\n if (cell && typeof ((_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.selectElement) === 'function') {\n this.host.selectElement(cell);\n }\n }\n }, {\n key: \"getSelectedCellIndex\",\n value: function getSelectedCellIndex() {\n if (!this.host || !this.host.selectedElement) return -1;\n var sel = this.host.selectedElement;\n for (var i = 0; i < this.cells.length; i++) {\n if (this.cells[i] === sel) return i;\n }\n return -1;\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(GridElement, \"getData\", this, 3)([])), {}, {\n cells: this.cells.map(function (cell) {\n return cell.getData();\n }),\n cell_gap: this.cell_gap\n });\n }\n }, {\n key: \"rebalanceCellsProportional\",\n value:\n /** Rebalance percent cells so the row sums to exactly 100%. Proportional:\n * each cell's percent is scaled by `(100 / currentSum)`. Non-percent\n * cells are left untouched (nothing to scale — `auto`/`fill`/`px` don't\n * participate in the 100% budget). Used by the cell-manager alert banner\n * \"Rebalance\" action. */\n function rebalanceCellsProportional() {\n var _this6 = this;\n var pcts = this.cells.map(function (c) {\n var w = c.formatter.getFormat('width');\n if (typeof w === 'string' && /%$/.test(w.trim())) return parseFloat(w);\n return null;\n });\n var pctCells = pcts.map(function (v, i) {\n return v !== null ? {\n v: v,\n i: i\n } : null;\n }).filter(Boolean);\n var sum = pctCells.reduce(function (a, b) {\n return a + b.v;\n }, 0);\n if (sum <= 0 || pctCells.length === 0) return;\n var scaled = pctCells.map(function (_ref) {\n var v = _ref.v,\n i = _ref.i;\n return {\n i: i,\n v: Math.round(v * 100 / sum * 100) / 100\n };\n });\n // Distribute rounding residue to the last % cell so the total lands\n // exactly on 100.\n var residue = Math.round((100 - scaled.reduce(function (a, b) {\n return a + b.v;\n }, 0)) * 100) / 100;\n if (Math.abs(residue) >= 0.01) scaled[scaled.length - 1].v = Math.round((scaled[scaled.length - 1].v + residue) * 100) / 100;\n scaled.forEach(function (_ref2) {\n var i = _ref2.i,\n v = _ref2.v;\n _this6.cells[i].formatter.setFormat('width', \"\".concat(v, \"%\"));\n _this6.cells[i].render();\n });\n }\n\n /** Equalize: every cell becomes 100/N percent. Replaces ALL widths\n * (including auto/fill/px) — the user has opted into a uniform row.\n * Used by the cell-manager alert \"Equalize\" action. */\n }, {\n key: \"equalizeCells\",\n value: function equalizeCells() {\n var n = this.cells.length;\n if (n === 0) return;\n var each = Math.floor(10000 / n) / 100; // 2 decimal places\n var residue = Math.round((100 - each * n) * 100) / 100;\n this.cells.forEach(function (cell, i) {\n var v = i === n - 1 ? Math.round((each + residue) * 100) / 100 : each;\n cell.formatter.setFormat('width', \"\".concat(v, \"%\"));\n cell.render();\n });\n }\n\n /** Move a cell from index `from` to index `to` (Phase-3 W6.1 drag-reorder).\n * `to` is the target SLOT index (0..cells.length), so the interpretation\n * mirrors the `+` insert slots: slot N means \"land at position N after\n * removing the source\". Identity moves and out-of-range args are no-ops.\n * DOM is reparented incrementally (no full GridElement.render()) so the\n * selected cell's canvas state + the sidebar panel structure survive. */\n }, {\n key: \"moveCell\",\n value: function moveCell(from, to) {\n if (!Array.isArray(this.cells)) return;\n var n = this.cells.length;\n if (n < 2) return;\n if (from < 0 || from >= n) return;\n var target = to;\n if (target < 0) target = 0;\n if (target > n) target = n;\n // After removing `from`, adjacent `to` values collapse onto the same\n // final position — skip those so we don't trigger a useless repaint.\n if (target === from || target === from + 1) return;\n var _this$cells$splice = this.cells.splice(from, 1),\n _this$cells$splice2 = _slicedToArray(_this$cells$splice, 1),\n cell = _this$cells$splice2[0];\n var adjusted = target > from ? target - 1 : target;\n this.cells.splice(adjusted, 0, cell);\n\n // DOM reparent — find the wrapper the same way _appendCellDom does.\n if (this.domNode) {\n var wrapper = this.domNode.firstElementChild;\n if (wrapper && cell.domNode && cell.domNode.parentNode === wrapper) {\n var siblings = Array.from(wrapper.querySelectorAll(':scope > [builder-element=\"CellElement\"]'));\n // Remove first, then insert at the new position.\n wrapper.removeChild(cell.domNode);\n var refSiblings = siblings.filter(function (s) {\n return s !== cell.domNode;\n });\n if (adjusted >= refSiblings.length) {\n wrapper.appendChild(cell.domNode);\n } else {\n wrapper.insertBefore(cell.domNode, refSiblings[adjusted]);\n }\n }\n }\n }\n\n /** Resize a pair of adjacent cells atomically (Phase-3 W6.1 snap-ratios).\n * Used by the cell-manager edge-resizer grip. Writes both widths in the\n * same tick so there's no intermediate \"sum > 100%\" flash that could\n * trigger the rebalance banner. Values are % numbers (e.g. 33.33).\n * Clamps to [1, 99] to keep both cells visible — below 1% the cell is\n * unclickable and the grip disappears. */\n }, {\n key: \"resizeCellPair\",\n value: function resizeCellPair(leftIdx, leftPct, rightPct) {\n var n = this.cells.length;\n if (leftIdx < 0 || leftIdx + 1 >= n) return;\n var clamp = function clamp(v) {\n return Math.max(1, Math.min(99, Math.round(v * 100) / 100));\n };\n var l = clamp(leftPct);\n var r = clamp(rightPct);\n this.cells[leftIdx].formatter.setFormat('width', \"\".concat(l, \"%\"));\n this.cells[leftIdx + 1].formatter.setFormat('width', \"\".concat(r, \"%\"));\n this.cells[leftIdx].render();\n this.cells[leftIdx + 1].render();\n }\n\n /** Upgrade a pure-bare grid's cell widths to explicit percents summing\n * to 100%. Idempotent (already-% grids are untouched). Mixed grids\n * are left alone. Called from `parse()` + after `applyLayoutPreset()`. */\n }, {\n key: \"_upgradeLegacyBareWidths\",\n value: function _upgradeLegacyBareWidths() {\n if (!Array.isArray(this.cells) || this.cells.length === 0) return;\n var kinds = this.cells.map(function (cell) {\n var w = cell.formatter.getFormat('width');\n if (w === null || w === undefined || w === '' || w === 'auto') return 'auto';\n if (typeof w === 'number') return 'bare';\n if (typeof w === 'string') {\n var s = w.trim();\n if (/^-?\\d+(\\.\\d+)?$/.test(s)) return 'bare';\n if (/%$/.test(s)) return 'pct';\n if (/(px|em|rem|vw|vh)$/i.test(s)) return 'unit';\n }\n return 'other';\n });\n var allBare = kinds.every(function (k) {\n return k === 'bare';\n });\n if (!allBare) return;\n var nums = this.cells.map(function (cell) {\n return parseFloat(cell.formatter.getFormat('width'));\n });\n var sum = nums.reduce(function (a, b) {\n return a + b;\n }, 0);\n if (sum <= 0 || !isFinite(sum)) return;\n\n // Rescale so SUM = 100. Round to 2 decimal places; last cell absorbs\n // rounding residue so the total stays exactly 100.\n var pcts = nums.map(function (n) {\n return Math.round(n / sum * 10000) / 100;\n });\n var residue = Math.round((100 - pcts.reduce(function (a, b) {\n return a + b;\n }, 0)) * 100) / 100;\n if (Math.abs(residue) >= 0.01) pcts[pcts.length - 1] = Math.round((pcts[pcts.length - 1] + residue) * 100) / 100;\n this.cells.forEach(function (cell, i) {\n var v = pcts[i];\n var str = Number.isInteger(v) ? \"\".concat(v, \"%\") : \"\".concat(v, \"%\");\n cell.formatter.setFormat('width', str);\n });\n }\n }, {\n key: \"isAutoFormat\",\n value: function isAutoFormat(key) {\n var value = this.formatter.getFormat(key);\n return value === null || value === undefined || value === '' || value === 'auto';\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this7 = this;\n // ─────────────────────────────────────────────────────────────\n // Grid panel — 2026-04-18 Phase 2.12 audit\n // ─────────────────────────────────────────────────────────────\n // Ordered by user priority: cells first (what people came to edit),\n // then cell widths, then spacing + alignment, then background. All\n // controls emit .bjs-* / DimensionControl — no Bootstrap fallbacks.\n\n var controls = [];\n\n // 1. Cell manager (visual editor + layout presets + click-to-select)\n controls.push(new _GridControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cells'), {\n getItemCount: function getItemCount() {\n return _this7.cells.length;\n },\n getCellWidths: function getCellWidths() {\n return _this7.cells.map(function (c) {\n return c.formatter.getFormat('width', 'auto');\n });\n },\n getSelectedIndex: function getSelectedIndex() {\n return _this7.getSelectedCellIndex();\n }\n }, {\n addCell: function addCell() {\n return _this7.addCell();\n },\n addCellAt: function addCellAt(index) {\n return _this7.addCellAt(index);\n },\n removeCell: function removeCell(index) {\n _this7.removeCellByIndex(index);\n // removeCellByIndex already detaches the cell DOM\n // incrementally — no full render needed.\n },\n selectCell: function selectCell(index) {\n return _this7.selectCellAt(index);\n },\n applyPreset: function applyPreset(widths) {\n return _this7.applyLayoutPreset(widths);\n },\n rebalanceProportional: function rebalanceProportional() {\n return _this7.rebalanceCellsProportional();\n },\n equalize: function equalize() {\n return _this7.equalizeCells();\n },\n moveCell: function moveCell(from, to) {\n return _this7.moveCell(from, to);\n },\n resizeCellPair: function resizeCellPair(leftIdx, leftPct, rightPct) {\n return _this7.resizeCellPair(leftIdx, leftPct, rightPct);\n },\n removeCells: function removeCells(indices) {\n // Bulk-remove — indices must be in descending order so\n // later splices don't shift earlier ones. Caller guarantees\n // this (GridControl.bulk handler sorts high→low).\n indices.forEach(function (i) {\n return _this7.removeCellByIndex(i);\n });\n }\n }));\n\n // 2. Cell widths section — one DimensionControl per cell, supports\n // %, px, em, rem, vw, auto. Canonical list view so user can scan\n // all widths at a glance.\n controls.push(new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.cell_widths'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.cell_widths_desc')));\n this.cells.forEach(function (cell, index) {\n controls.push(new _DimensionControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](\"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_n', 'Cell'), \" #\").concat(index + 1), cell.formatter.getFormat('width', 'auto'), {\n units: ['%', 'px', 'em', 'rem', 'vw', 'fill', 'auto'],\n onChange: function onChange(value) {\n cell.formatter.setFormat('width', value === null ? 'auto' : value);\n cell.render();\n }\n }));\n });\n\n // 3. Spacing & alignment section\n controls.push(new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.grid_spacing'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.grid_spacing_desc')));\n\n // Cell gap — slider with common-value presets (0/8/16/24 = design-\n // system multiples-of-8).\n controls.push(new _RangeControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_gap'), this.cell_gap, 0, 200, 'px', 1, function (value) {\n _this7.cell_gap = parseFloat(value) || 0;\n _this7.render();\n }, {\n presets: [0, 8, 16, 24],\n description: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_gap_desc')\n }));\n\n // Cell alignment — Option 3 escape hatch. Default `stretch` gives\n // equal heights; user can override to Top/Center/Bottom for\n // staggered layouts.\n controls.push(new _AlignControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_alignment'), this.formatter.getFormat('align_items', 'stretch'), function (value) {\n _this7.formatter.setFormat('align_items', value);\n _this7.render();\n }, [{\n value: 'stretch',\n icon: 'height'\n }, {\n value: 'flex-start',\n icon: 'vertical_align_top'\n }, {\n value: 'center',\n icon: 'vertical_align_center'\n }, {\n value: 'flex-end',\n icon: 'vertical_align_bottom'\n }]));\n\n // 4. Grid background — BackgroundControl renders its own header\n // so we don't duplicate with a SectionLabelControl.\n controls.push(new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.grid_background'), {\n color: this.formatter.getFormat('background_color', '#ffffff'),\n image: this.formatter.getFormat('background_image', ''),\n position: this.formatter.getFormat('background_position', 'center'),\n size: this.formatter.getFormat('background_size', '100'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat'),\n blendMode: this.formatter.getFormat('background_blend_mode', 'normal'),\n opacity: Math.round((parseFloat(this.formatter.getFormat('opacity', 1)) || 1) * 100),\n filter: this.formatter.getFormat('filter', '')\n }, {\n setBackground: function setBackground(values) {\n _this7.formatter.setFormat('background_color', values.color);\n _this7.formatter.setFormat('background_image', values.image);\n _this7.formatter.setFormat('background_position', values.position);\n _this7.formatter.setFormat('background_size', values.size);\n _this7.formatter.setFormat('background_repeat', values.repeat);\n _this7.formatter.setFormat('background_blend_mode', values.blendMode === 'normal' ? null : values.blendMode);\n _this7.formatter.setFormat('opacity', values.opacity === 1 ? null : values.opacity);\n _this7.formatter.setFormat('filter', values.filter || null);\n _this7.render();\n }\n }));\n return controls;\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var gridElement = new this(data.template);\n // Route through ElementFactory so specialised cell subclasses\n // (FormContainerCell, future PricingCell, etc.) get instantiated\n // based on the `name` field in JSON. Legacy data with missing\n // `name` falls back to CellElement.\n var cells = Array.isArray(data.cells) ? data.cells.map(function (cellData) {\n if (cellData && cellData.name && cellData.name !== 'CellElement') {\n try {\n return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(cellData);\n } catch (e) {\n // Unknown cell subclass → degrade to CellElement so the\n // canvas still renders instead of throwing on load.\n return _CellElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].parse(cellData);\n }\n }\n return _CellElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].parse(cellData);\n }) : [];\n gridElement.appendCells(cells);\n gridElement.cell_gap = data.cell_gap || 0;\n // W0.2c: parseFormats helper handles the typeof check + null guard\n this.parseFormats(gridElement, data);\n // 2026-04-18 legacy-width upgrade — bare numbers (\"50\") were the\n // historical way to express grow-share ratios, but 90%+ of sample\n // authors used them to mean percents. DimensionControl's bare\n // fallback is now '%' (not 'px'), so if a pure-bare grid reaches\n // the panel un-migrated, the displayed unit ('%') would not match\n // the rendered semantic (grow-share). We upgrade at load time:\n // every pure-bare grid's widths are rescaled so they SUM to 100%\n // and serialized as explicit \"N%\" strings. The rescaling preserves\n // the exact visual: flex grow-share at ratio a:b:c renders identical\n // to explicit percents (a/sum*100)%, (b/sum*100)%, (c/sum*100)%\n // when the row has a gap (percent branch in Cell.template.html\n // subtracts its gap share, grow-share does so implicitly through\n // flexbox math — the output pixels match to <1 sub-pixel).\n //\n // Mixed grids (auto + bare, or pct + bare) keep their bare values\n // intact — grow-share remains a valid runtime primitive for the\n // \"content-left + fill-right\" layout pattern that can't be\n // expressed in pure percents. Samples we ship have all 22 such\n // grids reviewed individually (docs/BUILDER.md §Lesson 22).\n gridElement._upgradeLegacyBareWidths();\n return gridElement;\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/GridElement.js?");
/***/ }),
/***/ "./src/includes/GridWidget.js":
/*!************************************!*\
!*** ./src/includes/GridWidget.js ***!
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _GridElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./GridElement.js */ \"./src/includes/GridElement.js\");\n/* harmony import */ var _CellElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./CellElement.js */ \"./src/includes/CellElement.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\nvar GridWidget = /*#__PURE__*/function (_BaseWidget) {\n function GridWidget() {\n var _this;\n _classCallCheck(this, GridWidget);\n _this = _callSuper(this, GridWidget); // Call the parent class constructor\n\n // Add a GridElement to the widget\n var grid = new _GridElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Grid');\n var cell_1 = new _CellElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Cell');\n cell_1.formatter.setFormat('width', '50');\n var cell_2 = new _CellElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Cell');\n cell_2.formatter.setFormat('width', '50');\n grid.cells = [cell_1, cell_2];\n\n //\n _this.block.appendElements([grid]);\n return _this;\n }\n _inherits(GridWidget, _BaseWidget);\n return _createClass(GridWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.grid');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'grid_view';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/GridWidget.js?");
/***/ }),
/***/ "./src/includes/H1Element.js":
/*!***********************************!*\
!*** ./src/includes/H1Element.js ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LegacyHeadingAliasElement.js */ \"./src/includes/LegacyHeadingAliasElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar H1Element = /*#__PURE__*/function (_LegacyHeadingAliasEl) {\n function H1Element() {\n _classCallCheck(this, H1Element);\n return _callSuper(this, H1Element, arguments);\n }\n _inherits(H1Element, _LegacyHeadingAliasEl);\n return _createClass(H1Element);\n}(_LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\nH1Element.headingType = 'h1';\nH1Element.headingLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading_1');\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (H1Element);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/H1Element.js?");
/***/ }),
/***/ "./src/includes/H2Element.js":
/*!***********************************!*\
!*** ./src/includes/H2Element.js ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LegacyHeadingAliasElement.js */ \"./src/includes/LegacyHeadingAliasElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar H2Element = /*#__PURE__*/function (_LegacyHeadingAliasEl) {\n function H2Element() {\n _classCallCheck(this, H2Element);\n return _callSuper(this, H2Element, arguments);\n }\n _inherits(H2Element, _LegacyHeadingAliasEl);\n return _createClass(H2Element);\n}(_LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\nH2Element.headingType = 'h2';\nH2Element.headingLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading_2');\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (H2Element);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/H2Element.js?");
/***/ }),
/***/ "./src/includes/H3Element.js":
/*!***********************************!*\
!*** ./src/includes/H3Element.js ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LegacyHeadingAliasElement.js */ \"./src/includes/LegacyHeadingAliasElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar H3Element = /*#__PURE__*/function (_LegacyHeadingAliasEl) {\n function H3Element() {\n _classCallCheck(this, H3Element);\n return _callSuper(this, H3Element, arguments);\n }\n _inherits(H3Element, _LegacyHeadingAliasEl);\n return _createClass(H3Element);\n}(_LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\nH3Element.headingType = 'h3';\nH3Element.headingLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading_3');\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (H3Element);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/H3Element.js?");
/***/ }),
/***/ "./src/includes/H4Element.js":
/*!***********************************!*\
!*** ./src/includes/H4Element.js ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LegacyHeadingAliasElement.js */ \"./src/includes/LegacyHeadingAliasElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar H4Element = /*#__PURE__*/function (_LegacyHeadingAliasEl) {\n function H4Element() {\n _classCallCheck(this, H4Element);\n return _callSuper(this, H4Element, arguments);\n }\n _inherits(H4Element, _LegacyHeadingAliasEl);\n return _createClass(H4Element);\n}(_LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\nH4Element.headingType = 'h4';\nH4Element.headingLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading_4');\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (H4Element);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/H4Element.js?");
/***/ }),
/***/ "./src/includes/H5Element.js":
/*!***********************************!*\
!*** ./src/includes/H5Element.js ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LegacyHeadingAliasElement.js */ \"./src/includes/LegacyHeadingAliasElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar H5Element = /*#__PURE__*/function (_LegacyHeadingAliasEl) {\n function H5Element() {\n _classCallCheck(this, H5Element);\n return _callSuper(this, H5Element, arguments);\n }\n _inherits(H5Element, _LegacyHeadingAliasEl);\n return _createClass(H5Element);\n}(_LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\nH5Element.headingType = 'h5';\nH5Element.headingLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading_5');\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (H5Element);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/H5Element.js?");
/***/ }),
/***/ "./src/includes/HTMLElement.js":
/*!*************************************!*\
!*** ./src/includes/HTMLElement.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar HTMLElement = /*#__PURE__*/function (_BaseElement) {\n function HTMLElement(template, html) {\n var _this;\n _classCallCheck(this, HTMLElement);\n _this = _callSuper(this, HTMLElement); // Call the parent class constructor\n _this.template = template;\n _this.html = html;\n\n // Node\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['html'];\n\n // Formatter\n _this.formatter = new Formatter({\n // background\n background_color: null,\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n // spacing\n padding_top: 0,\n padding_right: 0,\n padding_bottom: 0,\n padding_left: 0,\n // border\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_width: null,\n border_left_style: null,\n border_left_color: null,\n // border radius\n border_radius: 0\n });\n return _this;\n }\n _inherits(HTMLElement, _BaseElement);\n return _createClass(HTMLElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.html');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n html: this.html\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(HTMLElement, \"getData\", this, 3)([])), {}, {\n html: this.html\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this;\n return [new BackgroundControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n color: this.formatter.getFormat('background_color'),\n image: this.formatter.getFormat('background_image'),\n position: this.formatter.getFormat('background_position'),\n size: this.formatter.getFormat('background_size'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n }, {\n setBackground: function setBackground(values) {\n _this2.formatter.setFormat('background_color', values.color);\n _this2.formatter.setFormat('background_image', values.image);\n _this2.formatter.setFormat('background_position', values.position);\n _this2.formatter.setFormat('background_size', values.size);\n _this2.formatter.setFormat('background_repeat', values.repeat);\n _this2.render();\n }\n }, {\n features: ['color', 'image', 'size', 'repeat', 'gradient']\n }), new BorderControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style'),\n border_top_width: this.formatter.getFormat('border_top_width'),\n border_top_color: this.formatter.getFormat('border_top_color'),\n border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n border_left_style: this.formatter.getFormat('border_left_style'),\n border_left_width: this.formatter.getFormat('border_left_width'),\n border_left_color: this.formatter.getFormat('border_left_color'),\n border_right_style: this.formatter.getFormat('border_right_style'),\n border_right_width: this.formatter.getFormat('border_right_width'),\n border_right_color: this.formatter.getFormat('border_right_color')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this2.formatter.setFormat('border_top_style', border_top_style);\n _this2.formatter.setFormat('border_top_width', border_top_width);\n _this2.formatter.setFormat('border_top_color', border_top_color);\n _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this2.formatter.setFormat('border_left_style', border_left_style);\n _this2.formatter.setFormat('border_left_width', border_left_width);\n _this2.formatter.setFormat('border_left_color', border_left_color);\n _this2.formatter.setFormat('border_right_style', border_right_style);\n _this2.formatter.setFormat('border_right_width', border_right_width);\n _this2.formatter.setFormat('border_right_color', border_right_color);\n\n // re-render\n _this2.render();\n }\n }), new BorderRadiusControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n setRadius: function setRadius(v) {\n _this2.formatter.setFormat('border_radius', v);\n _this2.render();\n }\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.html), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HTMLElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HTMLElement.js?");
/***/ }),
/***/ "./src/includes/HeadingControl.js":
/*!****************************************!*\
!*** ./src/includes/HeadingControl.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar HeadingControl = /*#__PURE__*/function () {\n /**\n * Heading-tag selector (h1–h6). Emits a direct callback (`setType(value)`),\n * not the usual `{setValue}` shape, because HeadingElement pairs the type\n * change with a font-size reset + panel re-render — the caller wants the\n * raw new type value immediately.\n */\n function HeadingControl(label, type, setType) {\n _classCallCheck(this, HeadingControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.type = type || 'h1';\n this.setType = setType;\n this.domNode = document.createElement(\"div\");\n this.render();\n }\n return _createClass(HeadingControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var types = [{\n value: 'h1',\n labelKey: 'controls.h1_main_title'\n }, {\n value: 'h2',\n labelKey: 'controls.h2_section_title'\n }, {\n value: 'h3',\n labelKey: 'controls.h3_subsection_title'\n }, {\n value: 'h4',\n labelKey: 'controls.h4_smaller_title'\n }, {\n value: 'h5',\n labelKey: 'controls.h5_even_smaller_title'\n }, {\n value: 'h6',\n labelKey: 'controls.h6_smallest_title'\n }];\n var optionsHtml = types.map(function (t) {\n var selected = _this.type === t.value ? ' selected' : '';\n return \"<option value=\\\"\".concat(t.value, \"\\\"\").concat(selected, \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(t.labelKey), \"</option>\");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-select\\\">\\n <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"\\\" data-control=\\\"type-select\\\">\").concat(optionsHtml, \"</select>\\n <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n </div>\\n </div>\\n </div>\\n \");\n this.selectEl = this.domNode.querySelector('select');\n this.selectEl.addEventListener('change', function (e) {\n var val = e.target.value;\n _this.type = val;\n if (typeof _this.setType === 'function') {\n _this.setType(val);\n }\n });\n }\n }, {\n key: \"getTypeSelector\",\n value: function getTypeSelector() {\n return this.selectEl;\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.type = newValue;\n if (this.selectEl) this.selectEl.value = newValue;\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.type;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HeadingControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HeadingControl.js?");
/***/ }),
/***/ "./src/includes/HeadingElement.js":
/*!****************************************!*\
!*** ./src/includes/HeadingElement.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _HeadingControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingControl.js */ \"./src/includes/HeadingControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar HeadingElement = /*#__PURE__*/function (_BaseElement) {\n function HeadingElement(template, type, text) {\n var _this;\n _classCallCheck(this, HeadingElement);\n _this = _callSuper(this, HeadingElement);\n _this.template = template;\n _this.type = type; // h1, h2, h3, ...\n _this.text = text;\n _this.domNode = null;\n _this.requiredTemplateKeys = ['text'];\n\n // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n _this.registerInlineEdit('text');\n\n // Formatter. `text_decoration` and `font_style` exist because the\n // template emits all formats via `toStyleStringAll()`, but they are\n // managed by RichTextControl's inline tags — same reasoning as\n // PElement (§2.7). No border_* declared — headings don't typically\n // carry their own borders.\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n font_family: null,\n font_weight: null,\n font_size: null,\n text_color: null,\n link_color: null,\n paragraph_spacing: null,\n text_align: null,\n line_height: null,\n letter_spacing: null,\n text_direction: null,\n text_decoration: null,\n font_style: null,\n padding_top: null,\n padding_right: null,\n padding_bottom: null,\n padding_left: null\n });\n return _this;\n }\n _inherits(HeadingElement, _BaseElement);\n return _createClass(HeadingElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading');\n }\n\n /**\n * Full render. Used when `type` (h1…h6) or `text` changes — both require\n * swapping the tag itself. Format-only changes go through\n * `applyFormatStyles()` so the contenteditable cursor survives.\n * Inline-edit wiring is auto-fired by BaseElement.afterRender() (W0.2b).\n */\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter + text auto-merged (W0.2c); type is heading-specific\n this.domNode.innerHTML = this.renderTemplate({\n type: this.type\n });\n }\n\n /**\n * Structure-preserving format update (§2.8 E). Patches the existing\n * heading tag's inline style in place — no innerHTML swap, no tag\n * re-creation. Contenteditable cursor, text selection, and focus state\n * all survive typography tweaks.\n */\n }, {\n key: \"applyFormatStyles\",\n value: function applyFormatStyles() {\n if (!this.domNode) {\n this.render();\n return;\n }\n var target = this.domNode.querySelector('[inline-edit=\"text\"]');\n if (!target) {\n this.render();\n return;\n }\n target.setAttribute('style', this.formatter.toStyleStringAll());\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(HeadingElement, \"getData\", this, 3)([])), {}, {\n type: this.type,\n text: this.text\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this,\n _this$host;\n var setFmt = function setFmt(key) {\n return function (value) {\n _this2.formatter.setFormat(key, value);\n _this2.applyFormatStyles();\n };\n };\n // W3.1 — bus wiring for dual-view sync between sidebar and the\n // canvas FontPopoverOverlay. Reads the bus off `this.host` so two\n // Builders on the same page never share an EventEmitter.\n var busOpts = function busOpts(key) {\n var _this2$host;\n return {\n bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n elementUid: _this2.id,\n formatterKey: key\n };\n };\n return [\n // Heading tag selector — type change is STRUCTURAL (swap <h1>↔<h2>),\n // so it uses full render(). Also resets font_size so the new tag\n // renders at its browser-default size.\n new _HeadingControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.heading_type'), this.type, function (type) {\n var _this2$host2;\n _this2.type = type;\n _this2.formatter.setFormat('font_size', null);\n _this2.render();\n (_this2$host2 = _this2.host) === null || _this2$host2 === void 0 || _this2$host2.renderElementControls(_this2);\n }),\n // TEXT_INLINE_PLAN W8 (2026-04-24) — RichTextControl retired.\n // Canvas inline-edit = text surface; sidebar = config panel only.\n new FontFamilyControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n setValue: setFmt('font_family')\n }, busOpts('font_family')), new FontWeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n setValue: setFmt('font_weight')\n }, busOpts('font_weight')), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n setValue: setFmt('font_size')\n }, _objectSpread({\n defaultValue: 16,\n minValue: 8,\n maxValue: 72,\n suffix: 'px',\n allowZero: false\n }, busOpts('font_size'))), new ColorPickerControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n setValue: setFmt('text_color')\n }), new ColorPickerControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n setValue: setFmt('link_color')\n }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('text_align'), {\n setValue: setFmt('text_align')\n }, ['left', 'justify', 'center', 'right'], {\n bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n elementUid: this.id,\n formatterKey: 'text_align'\n }), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n setValue: setFmt('paragraph_spacing')\n }, {\n defaultValue: 0,\n minValue: 0,\n maxValue: 50,\n suffix: 'px',\n allowZero: true\n }), new LineHeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n setValue: setFmt('line_height')\n }), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n setValue: setFmt('letter_spacing')\n }, {\n defaultValue: 0,\n minValue: -5,\n maxValue: 10,\n step: 0.1,\n suffix: 'px',\n allowZero: true,\n allowNegative: true\n }), new TextDirectionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n setValue: setFmt('text_direction')\n })\n\n // W3.8b — PaddingMarginControl removed. Padding is a\n // container-only concern (Block/Cell/Page). Formatter keys\n // remain so legacy JSON renders identically.\n ];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.type, data.text), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HeadingElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HeadingElement.js?");
/***/ }),
/***/ "./src/includes/HeadingWidget.js":
/*!***************************************!*\
!*** ./src/includes/HeadingWidget.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar HeadingWidget = /*#__PURE__*/function (_BaseWidget) {\n function HeadingWidget() {\n var _this;\n _classCallCheck(this, HeadingWidget);\n _this = _callSuper(this, HeadingWidget); // Call the parent class constructor\n _this.elements = [];\n\n // Add an H1Element to the widget\n var h1 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Heading', 'h1', 'Heading');\n\n // Append the new element to the block\n _this.block.appendElements([h1]);\n return _this;\n }\n _inherits(HeadingWidget, _BaseWidget);\n return _createClass(HeadingWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.heading');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'title';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HeadingWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HeadingWidget.js?");
/***/ }),
/***/ "./src/includes/HistoryManager.js":
/*!****************************************!*\
!*** ./src/includes/HistoryManager.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * HistoryManager — undo/redo state machine for BuilderJS.\n *\n * See docs/plans/PLAN_UNDO_REDO.md for the full spec.\n *\n * Usage (internal — Builder instantiates this in load()):\n *\n * this.history = new HistoryManager(this, {\n * maxSize: 50,\n * debounceMs: 400,\n * coalesceMs: 600,\n * autoCloseTxMs: 5000,\n * });\n *\n * // Mutation sites call:\n * builder.history.commit('history.format_text_color', {\n * elementUid, elementType, change, source, oldValue, newValue,\n * });\n *\n * // Transaction (grouped mutations):\n * builder.history.beginTransaction('history.structure_move', { ... });\n * // ... multiple mutations ...\n * builder.history.endTransaction();\n *\n * Events fired on `builder.events` bus:\n * - 'history:commit' { entry }\n * - 'history:change' { canUndo, canRedo, size, currentIndex, currentEntry }\n * - 'history:before-apply' { direction, entry }\n * - 'history:after-apply' { direction, entry }\n *\n * CD-3 (AIBuilder Wave 4) — derived host-facing signals fired alongside the\n * 'history:commit' chokepoint so save.ts + SavedTicker subscribe to a single\n * canonical doc-mutation source instead of polling history.length:\n * - 'document:changed' {} — debounced inside the bus (default 120ms);\n * collapses typing bursts into ONE host fire.\n * - 'element:added' { elementUid, elementType } — when commit's\n * meta.change === 'structure:add'.\n * - 'element:removed' { elementUid, elementType } — when meta.change\n * === 'structure:remove'.\n */\nvar HistoryManager = /*#__PURE__*/function () {\n function HistoryManager(builder) {\n var _opts$maxSize, _opts$debounceMs, _opts$coalesceMs, _opts$autoCloseTxMs;\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, HistoryManager);\n this.builder = builder;\n this.maxSize = (_opts$maxSize = opts.maxSize) !== null && _opts$maxSize !== void 0 ? _opts$maxSize : 50;\n this.debounceMs = (_opts$debounceMs = opts.debounceMs) !== null && _opts$debounceMs !== void 0 ? _opts$debounceMs : 400;\n this.coalesceMs = (_opts$coalesceMs = opts.coalesceMs) !== null && _opts$coalesceMs !== void 0 ? _opts$coalesceMs : 600;\n this.autoCloseTxMs = (_opts$autoCloseTxMs = opts.autoCloseTxMs) !== null && _opts$autoCloseTxMs !== void 0 ? _opts$autoCloseTxMs : 5000;\n this._stack = [];\n this._pointer = -1;\n this._seq = 0;\n this._applying = false;\n this._tx = null;\n this._debounceTimer = null;\n this._iframeDoc = null;\n\n // PLAN_UNDO_REDO — smart debounce enrichment. When a Control emits\n // `region:focus` (e.g. PaddingMarginControl on its 4-side inputs,\n // TextControl on its text field), we snapshot { elementUid, regionKey }\n // here so the next debounce-fallback commit can attach rich meta:\n // \"Adjust padding-top on Block\" instead of generic \"Edit\".\n this._lastFocusedRegion = null;\n this._regionDisposers = [];\n }\n\n // ──────────────────────────────────────────────────────────────────\n // Lifecycle — called from Builder._historyInit()\n // ──────────────────────────────────────────────────────────────────\n\n /** Push the baseline snapshot. Labelled 'history.initial' — HistoryWidget\n * hides baseline from the dropdown list but keeps it in the stack as the\n * undo floor. Idempotent. */\n return _createClass(HistoryManager, [{\n key: \"pushBaseline\",\n value: function pushBaseline() {\n if (this._stack.length > 0) return;\n this._pushEntry(this._buildEntry('history.initial', {\n source: 'init'\n }));\n }\n\n /** Subscribe to region:focus / region:blur on builder.events so the next\n * debounce commit carries { elementUid, regionKey } context. Controls\n * that don't emit region events simply produce a bare-ish \"Edit :type\"\n * label, which is still more informative than \"Edit\". */\n }, {\n key: \"bindRegionFocusTracking\",\n value: function bindRegionFocusTracking() {\n var _this = this;\n if (!this.builder.events || typeof this.builder.events.on !== 'function') return;\n var d1 = this.builder.events.on('region:focus', function (payload) {\n _this._lastFocusedRegion = payload || null;\n });\n var d2 = this.builder.events.on('region:blur', function () {\n _this._lastFocusedRegion = null;\n });\n this._regionDisposers.push(d1, d2);\n }\n\n /** Attach debounce-fallback listeners to iframe + settings. */\n }, {\n key: \"bindDebounceFallback\",\n value: function bindDebounceFallback() {\n var _this$builder$iframe$,\n _this2 = this;\n var iframeDoc = this.builder.iframe && (this.builder.iframe.contentDocument || ((_this$builder$iframe$ = this.builder.iframe.contentWindow) === null || _this$builder$iframe$ === void 0 ? void 0 : _this$builder$iframe$.document));\n if (!iframeDoc) return;\n this._iframeDoc = iframeDoc;\n var deb = function deb() {\n return _this2._scheduleDebouncedCommit();\n };\n iframeDoc.addEventListener('mouseup', deb);\n iframeDoc.addEventListener('keyup', deb);\n iframeDoc.addEventListener('drop', deb);\n var settings = this.builder.settingsContainer;\n if (settings) {\n settings.addEventListener('mouseup', deb);\n settings.addEventListener('change', deb);\n }\n }\n }, {\n key: \"_scheduleDebouncedCommit\",\n value: function _scheduleDebouncedCommit() {\n var _this$_tx,\n _this3 = this;\n if (this._applying || (_this$_tx = this._tx) !== null && _this$_tx !== void 0 && _this$_tx.active) return;\n clearTimeout(this._debounceTimer);\n this._debounceTimer = setTimeout(function () {\n // PLAN_UNDO_REDO — rich meta: { elementUid, elementType, change,\n // regionKey }. HistoryWidget renders the label via i18n using\n // whichever key we pick. Priority:\n // 1. regionKey known → try specific 'history.format_<key>'\n // (e.g. history.format_padding_top = \"Adjust padding\")\n // 2. elementType known → 'history.edit_type' = \"Edit :type\"\n // 3. Bare → 'history.edit' = \"Edit\"\n var el = _this3.builder.selectedElement;\n var region = _this3._lastFocusedRegion;\n var meta = {\n source: 'debounce'\n };\n if (el) {\n var _el$constructor;\n meta.elementUid = el.id;\n meta.elementType = typeof el.getName === 'function' ? el.getName() : (_el$constructor = el.constructor) === null || _el$constructor === void 0 ? void 0 : _el$constructor.name;\n }\n var labelKey = 'history.edit';\n if (region !== null && region !== void 0 && region.regionKey) {\n meta.change = \"format:\".concat(region.regionKey);\n meta.regionKey = region.regionKey;\n // regionKey uses dashes ('padding-top') but i18n keys use\n // underscores ('format_padding_top'). Normalize.\n var normalized = String(region.regionKey).replace(/-/g, '_');\n labelKey = \"history.format_\".concat(normalized);\n } else if (el) {\n labelKey = 'history.edit_type';\n }\n _this3.commit(labelKey, meta);\n }, this.debounceMs);\n }\n\n // ──────────────────────────────────────────────────────────────────\n // Public API — commit + transaction\n // ──────────────────────────────────────────────────────────────────\n }, {\n key: \"commit\",\n value: function commit(labelKey) {\n var _this$_tx2;\n var meta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n if (this._applying) return;\n if ((_this$_tx2 = this._tx) !== null && _this$_tx2 !== void 0 && _this$_tx2.active) {\n this._tx.queuedCount++;\n return;\n }\n var entry = this._buildEntry(labelKey, meta);\n this._pushWithDedupe(entry);\n }\n\n /**\n * Run `fn` with all `commit()` calls suppressed — for programmatic\n * mass-mutation paths that would otherwise leak many low-level entries\n * into the history dropdown (e.g. theme swap, AI replace-page, bulk\n * delete, page clear). Caller should follow up with a single\n * `commit('history.<summary>')` so the operation remains undo-able as\n * one atomic step. Reentrant — nested `silent()` preserves the prior\n * state, so calling silent() inside `_apply` (which already sets\n * `_applying`) doesn't accidentally re-enable commits when the inner\n * fn returns.\n */\n }, {\n key: \"silent\",\n value: function silent(fn) {\n var prev = this._applying;\n this._applying = true;\n try {\n return fn();\n } finally {\n this._applying = prev;\n }\n }\n }, {\n key: \"beginTransaction\",\n value: function beginTransaction(labelKey) {\n var _this$_tx3,\n _this4 = this;\n var meta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n if (this._applying) return;\n if ((_this$_tx3 = this._tx) !== null && _this$_tx3 !== void 0 && _this$_tx3.active) this.endTransaction(); // nested → close prev\n this._tx = {\n active: true,\n labelKey: labelKey,\n meta: meta,\n startedAt: Date.now(),\n queuedCount: 0,\n autoCloseTimer: setTimeout(function () {\n return _this4._autoCloseTransaction();\n }, this.autoCloseTxMs)\n };\n }\n }, {\n key: \"endTransaction\",\n value: function endTransaction() {\n var tx = this._tx;\n if (!(tx !== null && tx !== void 0 && tx.active)) return;\n clearTimeout(tx.autoCloseTimer);\n this._tx = null;\n var meta = Object.assign({}, tx.meta, {\n childCount: tx.queuedCount\n });\n this._pushWithDedupe(this._buildEntry(tx.labelKey, meta));\n }\n }, {\n key: \"abortTransaction\",\n value: function abortTransaction() {\n var tx = this._tx;\n if (!(tx !== null && tx !== void 0 && tx.active)) return;\n clearTimeout(tx.autoCloseTimer);\n this._tx = null;\n }\n }, {\n key: \"_autoCloseTransaction\",\n value: function _autoCloseTransaction() {\n var _this$_tx4;\n if (!((_this$_tx4 = this._tx) !== null && _this$_tx4 !== void 0 && _this$_tx4.active)) return;\n this.endTransaction();\n }\n\n // ──────────────────────────────────────────────────────────────────\n // Public API — undo / redo / jumpTo / clear\n // ──────────────────────────────────────────────────────────────────\n }, {\n key: \"canUndo\",\n value: function canUndo() {\n return this._pointer > 0;\n }\n }, {\n key: \"canRedo\",\n value: function canRedo() {\n return this._pointer < this._stack.length - 1;\n }\n }, {\n key: \"size\",\n value: function size() {\n return this._stack.length;\n }\n }, {\n key: \"getCurrentIndex\",\n value: function getCurrentIndex() {\n return this._pointer;\n }\n }, {\n key: \"getEntries\",\n value: function getEntries() {\n return this._stack.map(function (e) {\n return _objectSpread(_objectSpread({}, e), {}, {\n data: null\n });\n });\n }\n }, {\n key: \"undo\",\n value: function () {\n var _undo = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (this.canUndo()) {\n _context.next = 2;\n break;\n }\n return _context.abrupt(\"return\", false);\n case 2:\n this._pointer--;\n _context.next = 5;\n return this._apply(this._stack[this._pointer], 'undo');\n case 5:\n return _context.abrupt(\"return\", true);\n case 6:\n case \"end\":\n return _context.stop();\n }\n }, _callee, this);\n }));\n function undo() {\n return _undo.apply(this, arguments);\n }\n return undo;\n }()\n }, {\n key: \"redo\",\n value: function () {\n var _redo = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n if (this.canRedo()) {\n _context2.next = 2;\n break;\n }\n return _context2.abrupt(\"return\", false);\n case 2:\n this._pointer++;\n _context2.next = 5;\n return this._apply(this._stack[this._pointer], 'redo');\n case 5:\n return _context2.abrupt(\"return\", true);\n case 6:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, this);\n }));\n function redo() {\n return _redo.apply(this, arguments);\n }\n return redo;\n }()\n }, {\n key: \"jumpTo\",\n value: function () {\n var _jumpTo = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(id) {\n var idx, direction;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n idx = this._stack.findIndex(function (e) {\n return e.id === id;\n });\n if (!(idx < 0 || idx === this._pointer)) {\n _context3.next = 3;\n break;\n }\n return _context3.abrupt(\"return\", false);\n case 3:\n direction = idx > this._pointer ? 'redo' : 'undo';\n this._pointer = idx;\n _context3.next = 7;\n return this._apply(this._stack[this._pointer], direction);\n case 7:\n return _context3.abrupt(\"return\", true);\n case 8:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, this);\n }));\n function jumpTo(_x) {\n return _jumpTo.apply(this, arguments);\n }\n return jumpTo;\n }()\n }, {\n key: \"clear\",\n value: function clear() {\n if (this._stack.length <= 1) return;\n this._stack = [this._stack[this._pointer]];\n this._pointer = 0;\n this._notifyChange();\n }\n\n // ──────────────────────────────────────────────────────────────────\n // Internals\n // ──────────────────────────────────────────────────────────────────\n }, {\n key: \"_buildEntry\",\n value: function _buildEntry(labelKey) {\n var _this$builder$selecte, _this$builder$selecte2;\n var meta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var data = this.builder.getData();\n return {\n id: \"h_\".concat(Date.now(), \"_\").concat(this._seq++),\n data: JSON.parse(JSON.stringify(data)),\n timestamp: Date.now(),\n labelKey: labelKey || 'history.default_label',\n labelParams: this._buildLabelParams(meta),\n selectionUid: (_this$builder$selecte = (_this$builder$selecte2 = this.builder.selectedElement) === null || _this$builder$selecte2 === void 0 ? void 0 : _this$builder$selecte2.id) !== null && _this$builder$selecte !== void 0 ? _this$builder$selecte : null,\n scrollTop: this._captureScrollTop(),\n meta: meta\n };\n }\n }, {\n key: \"_buildLabelParams\",\n value: function _buildLabelParams(meta) {\n var params = {};\n // meta.elementType should be the human-readable display name from\n // element.getName() (e.g. \"Image\"), not the raw class name.\n if (meta.elementType) params.type = meta.elementType;\n if (meta.regionKey) params.region = String(meta.regionKey).replace(/[-_]/g, ' ');\n if (meta.prompt) params.prompt = meta.prompt;\n if (meta.oldValue !== undefined) params.oldValue = String(meta.oldValue);\n if (meta.newValue !== undefined) params.newValue = String(meta.newValue);\n return params;\n }\n }, {\n key: \"_captureScrollTop\",\n value: function _captureScrollTop() {\n var _doc$documentElement, _doc$body;\n var doc = this._iframeDoc;\n if (!doc) return 0;\n return ((_doc$documentElement = doc.documentElement) === null || _doc$documentElement === void 0 ? void 0 : _doc$documentElement.scrollTop) || ((_doc$body = doc.body) === null || _doc$body === void 0 ? void 0 : _doc$body.scrollTop) || 0;\n }\n }, {\n key: \"_restoreScrollTop\",\n value: function _restoreScrollTop(top) {\n var doc = this._iframeDoc;\n if (!doc || top == null) return;\n if (doc.documentElement) doc.documentElement.scrollTop = top;\n if (doc.body) doc.body.scrollTop = top;\n }\n }, {\n key: \"_pushEntry\",\n value: function _pushEntry(entry) {\n this._pushWithDedupe(entry);\n }\n }, {\n key: \"_pushWithDedupe\",\n value: function _pushWithDedupe(entry) {\n var _top$meta, _entry$meta, _entry$meta2;\n var top = this._pointer >= 0 ? this._stack[this._pointer] : null;\n if (top && this._dataEqual(top.data, entry.data)) return;\n\n // Coalesce — same element + same change within window → merge\n if (top && (_top$meta = top.meta) !== null && _top$meta !== void 0 && _top$meta.elementUid && top.meta.elementUid === ((_entry$meta = entry.meta) === null || _entry$meta === void 0 ? void 0 : _entry$meta.elementUid) && top.meta.change && top.meta.change === ((_entry$meta2 = entry.meta) === null || _entry$meta2 === void 0 ? void 0 : _entry$meta2.change) && entry.timestamp - top.timestamp < this.coalesceMs && this._pointer === this._stack.length - 1) {\n top.data = entry.data;\n top.timestamp = entry.timestamp;\n top.meta.newValue = entry.meta.newValue;\n top.meta.count = (top.meta.count || 1) + 1;\n this._notifyChange();\n this._emit('history:commit', {\n entry: top\n });\n this._emitDocumentSignals(top);\n return;\n }\n this._stack.length = this._pointer + 1;\n this._stack.push(entry);\n this._pointer = this._stack.length - 1;\n if (this._stack.length > this.maxSize) {\n var excess = this._stack.length - this.maxSize;\n this._stack.splice(0, excess);\n this._pointer -= excess;\n }\n this._notifyChange();\n this._emit('history:commit', {\n entry: entry\n });\n this._emitDocumentSignals(entry);\n }\n\n /**\n * CD-3 (AIBuilder Wave 4) — fire `document:changed` (debounced inside the\n * bus, default 120ms) for every committed mutation. Host listeners\n * (Wave 4 SavedTicker, autosave) react to a SINGLE canonical signal\n * instead of polling history.length.\n *\n * `element:added` / `element:removed` are NOT derived here on purpose:\n * the history layer dedupes identical-data commits, but a Layers tree\n * (Wave 14) needs to see every add/remove regardless of whether the\n * resulting JSON is byte-equal to a prior state. Those events fire at\n * the actual structure-mutation chokepoints (UIManager._commitStructureAdd\n * + BaseElement.remove fadeOut callback + Builder.removeElement direct\n * call) — see CD-3 wiring in those files.\n */\n }, {\n key: \"_emitDocumentSignals\",\n value: function _emitDocumentSignals(_entry) {\n this._emit('document:changed', {});\n }\n }, {\n key: \"_dataEqual\",\n value: function _dataEqual(a, b) {\n if (a === b) return true;\n try {\n return JSON.stringify(a) === JSON.stringify(b);\n } catch (_) {\n return false;\n }\n }\n }, {\n key: \"_apply\",\n value: function () {\n var _apply2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(entry, direction) {\n var _this$builder$iframe$2;\n var iframeDoc, iframeBody, win, raf;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n this._applying = true;\n\n // PLAN_UNDO_REDO — suppress ALL iframe transitions/animations during\n // the apply window. Matching CSS in Builder._getDebugCss:\n // body.bjs-history-applying * { transition: none !important;\n // animation: none !important; }\n // Removed via 2x rAF AFTER render settles so real user interactions\n // post-apply resume with full motion. Standard batch-update pattern\n // (React flushSync, Vue nextTick + class-gated CSS). NOT a hack —\n // it's the explicit \"don't animate frame-to-frame batches\" contract.\n iframeDoc = this._iframeDoc || this.builder.iframe && (this.builder.iframe.contentDocument || ((_this$builder$iframe$2 = this.builder.iframe.contentWindow) === null || _this$builder$iframe$2 === void 0 ? void 0 : _this$builder$iframe$2.document));\n iframeBody = iframeDoc === null || iframeDoc === void 0 ? void 0 : iframeDoc.body;\n if (iframeBody) iframeBody.classList.add('bjs-history-applying');\n _context4.prev = 4;\n this._emit('history:before-apply', {\n direction: direction,\n entry: entry\n });\n this.builder.data = JSON.parse(JSON.stringify(entry.data));\n if (!(typeof this.builder.render === 'function')) {\n _context4.next = 10;\n break;\n }\n _context4.next = 10;\n return this.builder.render();\n case 10:\n if (entry.selectionUid && typeof this.builder.selectElementByUid === 'function') {\n this.builder.selectElementByUid(entry.selectionUid);\n } else if (typeof this.builder.unselect === 'function') {\n this.builder.unselect();\n }\n this._restoreScrollTop(entry.scrollTop);\n this._emit('history:after-apply', {\n direction: direction,\n entry: entry\n });\n case 13:\n _context4.prev = 13;\n this._applying = false;\n if (iframeBody) {\n win = iframeDoc.defaultView || window;\n raf = win.requestAnimationFrame || requestAnimationFrame;\n raf(function () {\n return raf(function () {\n iframeBody.classList.remove('bjs-history-applying');\n });\n });\n }\n return _context4.finish(13);\n case 17:\n this._notifyChange();\n case 18:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4, this, [[4,, 13, 17]]);\n }));\n function _apply(_x2, _x3) {\n return _apply2.apply(this, arguments);\n }\n return _apply;\n }()\n }, {\n key: \"_emit\",\n value: function _emit(event, payload) {\n if (this.builder.events && typeof this.builder.events.emit === 'function') {\n this.builder.events.emit(event, payload);\n }\n }\n }, {\n key: \"_notifyChange\",\n value: function _notifyChange() {\n var currentEntry = this._pointer >= 0 ? this._stack[this._pointer] : null;\n this._emit('history:change', {\n canUndo: this.canUndo(),\n canRedo: this.canRedo(),\n size: this.size(),\n currentIndex: this._pointer,\n currentEntry: currentEntry ? _objectSpread(_objectSpread({}, currentEntry), {}, {\n data: null\n }) : null\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HistoryManager);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HistoryManager.js?");
/***/ }),
/***/ "./src/includes/HistoryWidget.js":
/*!***************************************!*\
!*** ./src/includes/HistoryWidget.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * HistoryWidget — floating undo/redo pill + expandable history dropdown.\n *\n * Mounts INSIDE the builder's `mainContainer` (host DOM), NOT inside the iframe.\n * Subscribes to `builder.events` for 'history:change' updates.\n *\n * Default position: bottom-left. Configurable via `options.historyUIPosition`.\n * Opt-out: pass `options.historyUI: false` on Builder constructor.\n *\n * See docs/plans/PLAN_UNDO_REDO.md §8.6 for the full design spec.\n */\n\n// ════════════════════════════════════════════════════════════════════════════\n// Icon mapping — Material Symbols Rounded (host page loads the font)\n// ════════════════════════════════════════════════════════════════════════════\nvar ICON_FOR_CHANGE = {\n 'format:text_color': 'format_color_text',\n 'format:background': 'format_color_fill',\n 'format:padding_top': 'padding',\n 'format:padding_bottom': 'padding',\n 'format:padding_left': 'padding',\n 'format:padding_right': 'padding',\n 'format:font_size': 'format_size',\n 'format:font_family': 'font_download',\n 'format:border': 'border_style',\n 'format:align': 'format_align_left',\n 'format:size': 'crop_free',\n 'format:filter_brightness': 'brightness_6',\n 'format:filter_contrast': 'contrast',\n 'content:text': 'title',\n 'content:src': 'image',\n 'content:url': 'link',\n 'content:html': 'code',\n 'structure:add': 'add',\n 'structure:remove': 'delete',\n 'structure:move': 'swap_vert',\n 'structure:duplicate': 'content_copy',\n 'page:title': 'text_fields',\n 'page:theme': 'palette',\n 'page:block_gap': 'space_bar',\n 'page:clear': 'delete_sweep',\n 'ai:generate': 'auto_awesome',\n 'ai:rewrite': 'auto_fix_high',\n 'ai:inline_rewrite': 'auto_fix_normal'\n};\nvar ICON_DEFAULT = 'edit';\nvar ICON_INIT = 'flag';\nfunction iconForEntry(entry) {\n var _entry$meta, _entry$meta2;\n if ((entry === null || entry === void 0 || (_entry$meta = entry.meta) === null || _entry$meta === void 0 ? void 0 : _entry$meta.source) === 'init') return ICON_INIT;\n return ICON_FOR_CHANGE[entry === null || entry === void 0 || (_entry$meta2 = entry.meta) === null || _entry$meta2 === void 0 ? void 0 : _entry$meta2.change] || ICON_DEFAULT;\n}\n\n// ════════════════════════════════════════════════════════════════════════════\n// Relative time\n// ════════════════════════════════════════════════════════════════════════════\nfunction formatRelativeTime(ts) {\n var s = Math.max(0, Math.floor((Date.now() - ts) / 1000));\n if (s < 2) return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.relative_time.just_now');\n if (s < 60) return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.relative_time.seconds_ago').replace(':n', String(s));\n if (s < 3600) return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.relative_time.minutes_ago').replace(':n', String(Math.floor(s / 60)));\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.relative_time.hours_ago').replace(':n', String(Math.floor(s / 3600)));\n}\nfunction escapeHtml(s) {\n return String(s !== null && s !== void 0 ? s : '').replace(/[&<>\"']/g, function (c) {\n return {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n }[c];\n });\n}\n\n// Platform shortcut label\nvar IS_MAC = typeof navigator !== 'undefined' && /Mac|iPhone|iPad|iPod/i.test(navigator.platform || navigator.userAgent || '');\nvar KBD_MOD = IS_MAC ? '⌘' : 'Ctrl';\nvar KBD_SHIFT = IS_MAC ? '⇧' : 'Shift';\nvar TIP_UNDO = IS_MAC ? '⌘Z' : 'Ctrl+Z';\nvar TIP_REDO = IS_MAC ? '⌘⇧Z' : 'Ctrl+Shift+Z';\n\n// ════════════════════════════════════════════════════════════════════════════\n// Widget class\n// ════════════════════════════════════════════════════════════════════════════\nvar HistoryWidget = /*#__PURE__*/function () {\n // host-injection: `host` is the owning Builder instance — passed\n // explicitly so multi-instance setups don't share state via a global.\n // Stored as `this.host` (and `this.builder` alias for back-compat).\n function HistoryWidget(host) {\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, HistoryWidget);\n this.host = host;\n this.builder = host;\n this.history = host.history;\n this.position = opts.position || 'bottom-left'; // 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'\n this.minimal = !!opts.minimal; // no dropdown caret if true\n this.extraClass = opts.className || '';\n this.root = null;\n this.pill = null;\n this.btnUndo = null;\n this.btnRedo = null;\n this.btnToggle = null;\n this.dropdown = null;\n this.list = null;\n this.count = null;\n this.btnClear = null;\n this._disposers = [];\n this._outsideHandler = null;\n this._refreshTimer = null;\n }\n\n // ────────────────────────────────────────────────────────────────────\n // Mount\n // ────────────────────────────────────────────────────────────────────\n return _createClass(HistoryWidget, [{\n key: \"mount\",\n value: function mount() {\n var _this = this;\n if (this.root) return;\n var container = this.builder.mainContainer;\n if (!container) return;\n\n // Ensure the mainContainer can host an absolutely-positioned child.\n // Only set if not already positioned (don't stomp host styles).\n var cs = window.getComputedStyle(container);\n if (cs.position === 'static') container.style.position = 'relative';\n this.root = document.createElement('div');\n this.root.className = 'bjs-history-widget' + (this.extraClass ? ' ' + this.extraClass : '');\n this.root.setAttribute('data-bjs-history', 'true');\n this._applyPositionAttrs();\n this.root.innerHTML = this._buildHtml();\n container.appendChild(this.root);\n this._cacheRefs();\n this._wireEvents();\n this._renderState();\n\n // Refresh relative time every 30s while dropdown is open\n this._refreshTimer = setInterval(function () {\n var _this$root;\n if ((_this$root = _this.root) !== null && _this$root !== void 0 && _this$root.classList.contains('is-open')) _this._renderList();\n }, 30000);\n }\n }, {\n key: \"destroy\",\n value: function destroy() {\n var _this$root2;\n clearInterval(this._refreshTimer);\n this._disposers.forEach(function (d) {\n try {\n d();\n } catch (_) {}\n });\n this._disposers.length = 0;\n if (this._outsideHandler) {\n document.removeEventListener('click', this._outsideHandler, true);\n this._outsideHandler = null;\n }\n if ((_this$root2 = this.root) !== null && _this$root2 !== void 0 && _this$root2.parentNode) this.root.parentNode.removeChild(this.root);\n this.root = null;\n }\n\n // ────────────────────────────────────────────────────────────────────\n // DOM\n // ────────────────────────────────────────────────────────────────────\n }, {\n key: \"_applyPositionAttrs\",\n value: function _applyPositionAttrs() {\n // CSS reads data-align / data-flip to pick dropdown direction.\n var right = this.position.endsWith('right');\n var top = this.position.startsWith('top');\n this.root.setAttribute('data-bjs-history-position', this.position);\n if (right) this.root.setAttribute('data-align', 'right');\n if (top) this.root.setAttribute('data-flip', 'down');\n }\n }, {\n key: \"_buildHtml\",\n value: function _buildHtml() {\n var caret = this.minimal ? '' : \"\\n <span class=\\\"bjs-history-pill-divider\\\" aria-hidden=\\\"true\\\"></span>\\n <button type=\\\"button\\\" class=\\\"bjs-history-btn\\\" data-bjs-history-action=\\\"toggle\\\"\\n data-tooltip=\\\"\".concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.title')), \"\\\"\\n aria-label=\\\"\").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.title')), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">expand_more</span>\\n </button>\");\n return \"\\n <div class=\\\"bjs-history-pill\\\" role=\\\"toolbar\\\" aria-label=\\\"\".concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.title')), \"\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-history-btn\\\" data-bjs-history-action=\\\"undo\\\"\\n data-tooltip=\\\"\").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.undo')), \" (\").concat(TIP_UNDO, \")\\\"\\n aria-label=\\\"\").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.undo')), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">undo</span>\\n </button>\\n <button type=\\\"button\\\" class=\\\"bjs-history-btn\\\" data-bjs-history-action=\\\"redo\\\"\\n data-tooltip=\\\"\").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.redo')), \" (\").concat(TIP_REDO, \")\\\"\\n aria-label=\\\"\").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.redo')), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">redo</span>\\n </button>\\n \").concat(caret, \"\\n </div>\\n \").concat(this.minimal ? '' : \"\\n <div class=\\\"bjs-history-dropdown\\\" role=\\\"dialog\\\" aria-label=\\\"\".concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.title')), \"\\\">\\n <div class=\\\"bjs-history-header\\\">\\n <span class=\\\"bjs-history-header-title\\\">\\n <span class=\\\"material-symbols-rounded\\\">history</span>\\n \").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.title')), \"\\n </span>\\n <span class=\\\"bjs-history-header-count\\\" data-bjs-history-count>0</span>\\n </div>\\n <ul class=\\\"bjs-history-list\\\" data-bjs-history-list></ul>\\n <div class=\\\"bjs-history-footer\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-history-clear\\\" data-bjs-history-action=\\\"clear\\\">\\n <span class=\\\"material-symbols-rounded\\\">delete_sweep</span>\\n \").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.clear')), \"\\n </button>\\n <span class=\\\"bjs-history-footer-hint\\\">\\n <kbd>\").concat(KBD_MOD, \"</kbd><kbd>Z</kbd>\\n </span>\\n </div>\\n </div>\"), \"\\n \");\n }\n }, {\n key: \"_cacheRefs\",\n value: function _cacheRefs() {\n var _this2 = this;\n var q = function q(sel) {\n return _this2.root.querySelector(sel);\n };\n this.pill = q('.bjs-history-pill');\n this.btnUndo = q('[data-bjs-history-action=\"undo\"]');\n this.btnRedo = q('[data-bjs-history-action=\"redo\"]');\n this.btnToggle = q('[data-bjs-history-action=\"toggle\"]');\n this.dropdown = q('.bjs-history-dropdown');\n this.list = q('[data-bjs-history-list]');\n this.count = q('[data-bjs-history-count]');\n this.btnClear = q('[data-bjs-history-action=\"clear\"]');\n }\n }, {\n key: \"_wireEvents\",\n value: function _wireEvents() {\n var _this$btnUndo,\n _this3 = this,\n _this$btnRedo,\n _this$btnClear,\n _this$btnToggle,\n _this$builder$events,\n _this$list;\n // Buttons\n (_this$btnUndo = this.btnUndo) === null || _this$btnUndo === void 0 || _this$btnUndo.addEventListener('click', function () {\n return _this3.builder.undo();\n });\n (_this$btnRedo = this.btnRedo) === null || _this$btnRedo === void 0 || _this$btnRedo.addEventListener('click', function () {\n return _this3.builder.redo();\n });\n (_this$btnClear = this.btnClear) === null || _this$btnClear === void 0 || _this$btnClear.addEventListener('click', function () {\n return _this3.history.clear();\n });\n (_this$btnToggle = this.btnToggle) === null || _this$btnToggle === void 0 || _this$btnToggle.addEventListener('click', function (e) {\n e.stopPropagation();\n _this3._toggle();\n });\n\n // Subscribe to history:change\n if ((_this$builder$events = this.builder.events) !== null && _this$builder$events !== void 0 && _this$builder$events.on) {\n var disp1 = this.builder.events.on('history:change', function () {\n return _this3._renderState();\n });\n var disp2 = this.builder.events.on('history:commit', function () {\n var _this3$root;\n if ((_this3$root = _this3.root) !== null && _this3$root !== void 0 && _this3$root.classList.contains('is-open')) _this3._renderList();\n });\n this._disposers.push(disp1, disp2);\n }\n\n // Outside click → close\n this._outsideHandler = function (e) {\n if (!_this3.root) return;\n if (!_this3.root.contains(e.target)) _this3._close();\n };\n document.addEventListener('click', this._outsideHandler, true);\n\n // Entry click → jumpTo\n (_this$list = this.list) === null || _this$list === void 0 || _this$list.addEventListener('click', function (e) {\n var li = e.target.closest('[data-bjs-history-entry-id]');\n if (!li) return;\n var id = li.getAttribute('data-bjs-history-entry-id');\n if (id) _this3.history.jumpTo(id);\n });\n }\n }, {\n key: \"_toggle\",\n value: function _toggle() {\n if (this.root.classList.contains('is-open')) this._close();else this._open();\n }\n }, {\n key: \"_open\",\n value: function _open() {\n this.root.classList.add('is-open');\n this._renderList();\n if (this.btnToggle) this.btnToggle.classList.add('is-active');\n }\n }, {\n key: \"_close\",\n value: function _close() {\n this.root.classList.remove('is-open');\n if (this.btnToggle) this.btnToggle.classList.remove('is-active');\n }\n\n // ────────────────────────────────────────────────────────────────────\n // Render\n // ────────────────────────────────────────────────────────────────────\n }, {\n key: \"_renderState\",\n value: function _renderState() {\n if (!this.root) return;\n var canUndo = this.history.canUndo();\n var canRedo = this.history.canRedo();\n if (this.btnUndo) this.btnUndo.disabled = !canUndo;\n if (this.btnRedo) this.btnRedo.disabled = !canRedo;\n if (this.btnClear) this.btnClear.disabled = this.history.size() <= 1;\n\n // User-facing count excludes the baseline snapshot at index 0 —\n // baseline is the \"before any edit\" floor, not a user-visible entry.\n var visibleCount = Math.max(0, this.history.size() - 1);\n if (this.count) {\n this.count.textContent = visibleCount === 1 ? _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.entries_count_one').replace(':n', String(visibleCount)) : _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.entries_count').replace(':n', String(visibleCount));\n }\n if (this.root.classList.contains('is-open')) this._renderList();\n }\n }, {\n key: \"_renderList\",\n value: function _renderList() {\n if (!this.list) return;\n var entries = this.history._stack;\n var ptr = this.history._pointer;\n\n // Hide baseline (index 0) from the visible list — it's the implicit\n // \"before-any-edit\" floor. When only baseline exists → empty state.\n var hasRealEntries = entries.length > 1;\n if (!hasRealEntries) {\n this.list.innerHTML = this._emptyStateHtml();\n return;\n }\n var html = '';\n // Iterate only real entries (skip baseline at i=0). Newest first.\n for (var i = entries.length - 1; i >= 1; i--) {\n var _e$labelParams, _e$meta, _e$meta2;\n var e = entries[i];\n var cls = i === ptr ? 'is-current' : i > ptr ? 'is-future' : '';\n var label = escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(e.labelKey || 'history.default_label', e.labelParams));\n var meta = escapeHtml(((_e$labelParams = e.labelParams) === null || _e$labelParams === void 0 ? void 0 : _e$labelParams.type) || '');\n var icon = iconForEntry(e);\n var badge = (_e$meta = e.meta) !== null && _e$meta !== void 0 && _e$meta.count && e.meta.count > 1 ? \"<span class=\\\"bjs-history-entry-badge\\\">\\xD7\".concat(e.meta.count, \"</span>\") : (_e$meta2 = e.meta) !== null && _e$meta2 !== void 0 && _e$meta2.childCount && e.meta.childCount > 0 ? \"<span class=\\\"bjs-history-entry-badge is-tx\\\">\".concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.tx')), \"</span>\") : '';\n html += \"\\n <li class=\\\"bjs-history-entry \".concat(cls, \"\\\" data-bjs-history-entry-id=\\\"\").concat(escapeHtml(e.id), \"\\\">\\n <span class=\\\"bjs-history-entry-icon\\\"><span class=\\\"material-symbols-rounded\\\">\").concat(icon, \"</span></span>\\n <span class=\\\"bjs-history-entry-label\\\">\").concat(label, \"</span>\\n <span class=\\\"bjs-history-entry-meta\\\">\").concat(meta).concat(badge ? ' ' + badge : '', \"</span>\\n <span class=\\\"bjs-history-entry-time\\\">\").concat(escapeHtml(formatRelativeTime(e.timestamp)), \"</span>\\n </li>\");\n }\n this.list.innerHTML = html;\n }\n }, {\n key: \"_emptyStateHtml\",\n value: function _emptyStateHtml() {\n return \"\\n <div class=\\\"bjs-history-empty\\\">\\n <svg class=\\\"bjs-history-empty-illust\\\" viewBox=\\\"0 0 100 100\\\" fill=\\\"none\\\" aria-hidden=\\\"true\\\">\\n <circle cx=\\\"50\\\" cy=\\\"50\\\" r=\\\"38\\\" stroke=\\\"var(--bjs-border)\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"3 4\\\"/>\\n <rect x=\\\"34\\\" y=\\\"28\\\" width=\\\"32\\\" height=\\\"44\\\" rx=\\\"3\\\" fill=\\\"var(--bjs-bg)\\\" stroke=\\\"var(--bjs-border)\\\" stroke-width=\\\"1.5\\\"/>\\n <path d=\\\"M40 40 h20 M40 48 h20 M40 56 h14\\\" stroke=\\\"var(--bjs-text-disabled)\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/>\\n <path d=\\\"M30 78 q-8 0 -8 -10\\\" stroke=\\\"var(--bjs-primary)\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" fill=\\\"none\\\"/>\\n <path d=\\\"M18 72 l4 -4 l4 4\\\" stroke=\\\"var(--bjs-primary)\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" fill=\\\"none\\\"/>\\n </svg>\\n <div class=\\\"bjs-history-empty-title\\\">\".concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.empty_title')), \"</div>\\n <div class=\\\"bjs-history-empty-note\\\">\\n \").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.empty_note')), \"\\n <span class=\\\"bjs-history-empty-kbd\\\"><kbd>\").concat(KBD_MOD, \"</kbd><kbd>Z</kbd></span>\\n </div>\\n </div>\");\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HistoryWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HistoryWidget.js?");
/***/ }),
/***/ "./src/includes/HorizonAlignmentControl.js":
/*!*************************************************!*\
!*** ./src/includes/HorizonAlignmentControl.js ***!
\*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n// includes/HorizonAlignmentControl.js\nvar HorizonAlignmentControl = /*#__PURE__*/function () {\n function HorizonAlignmentControl(label, value, callback) {\n var cssProperty = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'align_items';\n _classCallCheck(this, HorizonAlignmentControl);\n this.id = '_' + Math.random().toString(36).slice(2, 9);\n this.label = label || 'Horizon Alignment';\n this.value = value || 'flex-start'; // flex-start | center | flex-end\n this.callback = callback;\n this.cssProperty = cssProperty;\n this.options = [{\n css: 'flex-start',\n icon: 'vertical_align_top'\n }, {\n css: 'center',\n icon: 'vertical_align_center'\n }, {\n css: 'flex-end',\n icon: 'vertical_align_bottom'\n }];\n this.domNode = document.createElement('div');\n HorizonAlignmentControl.injectStyles();\n this.render();\n }\n return _createClass(HorizonAlignmentControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var radios = this.options.map(function (opt, i) {\n var id = \"hz_\".concat(_this.id, \"_\").concat(i);\n return \"\\n <input type=\\\"radio\\\" class=\\\"btn-check\\\" name=\\\"hz_group_\".concat(_this.id, \"\\\"\\n id=\\\"\").concat(id, \"\\\" value=\\\"\").concat(opt.css, \"\\\" \").concat(_this.value === opt.css ? 'checked' : '', \">\\n <label class=\\\"btn builder-radio-btn builder-radio-option fw-bold\\\" for=\\\"\").concat(id, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">\").concat(opt.icon, \"</span>\\n </label>\\n \");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"py-2 px-3 builder-radio-container\\\">\\n <label class=\\\"form-label fw-semibold builder-radio-label\\\">\".concat(this.label, \"</label>\\n <div class=\\\"btn-group builder-radio-group\\\" role=\\\"group\\\" aria-label=\\\"\").concat(this.label, \"\\\">\\n \").concat(radios, \"\\n </div>\\n </div>\\n \");\n this.domNode.querySelectorAll(\"input[name=\\\"hz_group_\".concat(this.id, \"\\\"]\")).forEach(function (r) {\n r.addEventListener('change', function (e) {\n _this.value = e.target.value; // css value\n if (_this.callback && typeof _this.callback.setValue === 'function') {\n _this.callback.setValue(_this.value, _this.cssProperty);\n }\n });\n });\n }\n }, {\n key: \"setValue\",\n value: function setValue(cssValue) {\n this.value = cssValue;\n var radio = this.domNode.querySelector(\"input[value=\\\"\".concat(cssValue, \"\\\"]\"));\n if (radio) radio.checked = true;\n if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(this.value, this.cssProperty);\n }\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }], [{\n key: \"injectStyles\",\n value: function injectStyles() {\n if (document.getElementById('hz-align-control-styles')) return;\n var css = \"\\n /* ===== \\u041E\\u0431\\u0449\\u0438\\u0439 \\u0432\\u0438\\u0434 \\u043A\\u0430\\u043A \\u0443 AlignControl ===== */\\n .builder-radio-container{\\n display:flex; align-items:center; justify-content:space-between;\\n gap:12px; padding:8px 12px;\\n }\\n .builder-radio-label{ margin:0; font-weight:600; }\\n .builder-radio-group{\\n display:inline-flex; border-radius:8px; overflow:hidden;\\n border:1px solid var(--bs-border-color,#dee2e6);\\n height:32px; flex-shrink:0; width:180px;\\n }\\n .builder-radio-btn{\\n display:flex; align-items:center; justify-content:center;\\n width:60px; height:32px; border:0;\\n border-right:1px solid var(--bs-border-color,#dee2e6);\\n background:#fff; color:#212529;\\n }\\n .builder-radio-btn:last-of-type{ border-right:0; }\\n .builder-radio-btn .material-symbols-rounded{ font-size:18px; line-height:1; }\\n .btn-check:checked + .builder-radio-btn{ background:#495057; color:#fff; }\\n\\n /* ===== \\u0421\\u043F\\u0440\\u044F\\u0442\\u0430\\u0442\\u044C \\xAB\\u0447\\u0438\\u043F/\\u0437\\u043D\\u0430\\u0447\\u0435\\u043D\\u0438\\u0435\\xBB, \\u043A\\u043E\\u0442\\u043E\\u0440\\u043E\\u0435 \\u0434\\u0432\\u0438\\u0436\\u043E\\u043A \\u043F\\u043E\\u0434\\u043C\\u0435\\u0448\\u0438\\u0432\\u0430\\u0435\\u0442 \\u043F\\u043E\\u0441\\u043B\\u0435 \\u0433\\u0440\\u0443\\u043F\\u043F\\u044B ===== */\\n .builder-radio-container .builder-radio-group + *,\\n .builder-radio-container .builder-radio-group ~ .badge,\\n .builder-radio-container .builder-radio-group ~ .form-control,\\n .builder-radio-container .builder-radio-group ~ .form-select {\\n display:none !important;\\n }\\n \";\n var style = document.createElement('style');\n style.id = 'hz-align-control-styles';\n style.textContent = css;\n document.head.appendChild(style);\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HorizonAlignmentControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HorizonAlignmentControl.js?");
/***/ }),
/***/ "./src/includes/I18n.js":
/*!******************************!*\
!*** ./src/includes/I18n.js ***!
\******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _lang_en_json__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../lang/en.json */ \"./src/lang/en.json\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar I18n = /*#__PURE__*/function () {\n function I18n() {\n _classCallCheck(this, I18n);\n }\n return _createClass(I18n, null, [{\n key: \"init\",\n value: function init(translations) {\n I18n._messages = translations || {};\n }\n }, {\n key: \"t\",\n value: function t(key, params) {\n var text = I18n._messages[key] || I18n._defaults[key] || key;\n if (params) {\n Object.keys(params).forEach(function (k) {\n text = text.replace(new RegExp(':' + k, 'g'), params[k]);\n });\n }\n return text;\n }\n }]);\n}();\n_defineProperty(I18n, \"_messages\", {});\n_defineProperty(I18n, \"_defaults\", _lang_en_json__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (I18n);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/I18n.js?");
/***/ }),
/***/ "./src/includes/IconPickerControl.js":
/*!*******************************************!*\
!*** ./src/includes/IconPickerControl.js ***!
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n/**\n * IconPickerControl — compact trigger + popover icon picker.\n *\n * Renders as a .bjs-control-row with a trigger button showing the current\n * icon glyph + label + chevron. Click opens a popover with the full icon\n * grid (defaults to the pricingCardIcons registry) plus \"None\" and\n * \"Custom emoji\" options. Choosing \"Custom\" reveals an inline text input\n * inside the popover so the user can paste any emoji or glyph — the\n * trigger updates live as they type.\n *\n * Keyboard: Enter/Space opens the popover, arrows navigate, Enter selects,\n * Esc closes. ARIA: trigger=button w/ aria-haspopup, popover=radiogroup.\n *\n * Callback contract: `{ setValue(nextIconName) }`. Empty string = no icon.\n * Material-symbol names, emoji, and other short glyphs all flow through\n * the same string property (PricingCardIcons.render() handles dispatch).\n */\nvar IconPickerControl = /*#__PURE__*/function () {\n function IconPickerControl(label, value, callback) {\n var config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n _classCallCheck(this, IconPickerControl);\n this.label = label;\n this.value = value || '';\n this.callback = callback;\n this.id = '_ip_' + Math.random().toString(36).slice(2, 9);\n this.options = Array.isArray(config.options) && config.options.length ? config.options : IconPickerControl.defaultOptions();\n this.isOpen = false;\n this.isCustomOpen = this._detectCustom(value);\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-icon-picker-control');\n this._documentClickHandler = null;\n this._documentKeydownHandler = null;\n this.render();\n }\n return _createClass(IconPickerControl, [{\n key: \"_detectCustom\",\n value: function _detectCustom(val) {\n if (!val) return false;\n var key = String(val).trim();\n // If the value matches a registry entry, it's a preset — not custom.\n return !_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(key);\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this = this;\n var currentKey = this.value || '';\n var currentGlyph = currentKey ? _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].render(currentKey, {\n size: 20,\n color: 'currentColor'\n }) : '<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\"><circle cx=\"10\" cy=\"10\" r=\"7.5\" stroke=\"currentColor\" stroke-width=\"1.25\" stroke-dasharray=\"2 2\" fill=\"none\"/></svg>';\n var currentLabel = currentKey ? _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(currentKey) ? IconPickerControl.humanize(currentKey) : currentKey : _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.none');\n var tilesHtml = this.options.map(function (opt) {\n var checked = opt.key === _this.value ? 'true' : 'false';\n var glyph = opt.key ? _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].render(opt.key, {\n size: 22,\n color: 'currentColor'\n }) : '<svg viewBox=\"0 0 22 22\" xmlns=\"http://www.w3.org/2000/svg\" width=\"22\" height=\"22\"><line x1=\"4\" y1=\"4\" x2=\"18\" y2=\"18\" stroke=\"currentColor\" stroke-width=\"1.5\"/><line x1=\"18\" y1=\"4\" x2=\"4\" y2=\"18\" stroke=\"currentColor\" stroke-width=\"1.5\"/></svg>';\n var title = opt.label || opt.key || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.none');\n return \"\\n <button\\n type=\\\"button\\\"\\n class=\\\"bjs-icon-tile\\\"\\n role=\\\"radio\\\"\\n aria-checked=\\\"\".concat(checked, \"\\\"\\n data-key=\\\"\").concat(_this._esc(opt.key), \"\\\"\\n tabindex=\\\"\").concat(checked === 'true' ? '0' : '-1', \"\\\"\\n data-tooltip=\\\"\").concat(_this._esc(title), \"\\\"\\n aria-label=\\\"\").concat(_this._esc(title), \"\\\"\\n >\\n <span class=\\\"bjs-icon-tile-glyph\\\" aria-hidden=\\\"true\\\">\").concat(glyph, \"</span>\\n </button>\\n \");\n }).join('');\n\n // Custom-emoji tile: visually distinct (text \"ABC\" placeholder), toggles the inline text input\n var customActive = this.isCustomOpen || !_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(this.value) && this.value;\n var customTile = \"\\n <button\\n type=\\\"button\\\"\\n class=\\\"bjs-icon-tile bjs-icon-tile--custom \".concat(customActive ? 'is-active' : '', \"\\\"\\n aria-checked=\\\"\").concat(customActive ? 'true' : 'false', \"\\\"\\n role=\\\"radio\\\"\\n data-key=\\\"__custom\\\"\\n tabindex=\\\"\").concat(customActive ? '0' : '-1', \"\\\"\\n data-tooltip=\\\"\").concat(this._esc(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.custom')), \"\\\"\\n aria-label=\\\"\").concat(this._esc(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.custom')), \"\\\"\\n >\\n <span class=\\\"bjs-icon-tile-custom-label\\\">Aa</span>\\n </button>\\n \");\n var customInputHtml = this.isCustomOpen ? \"\\n <div class=\\\"bjs-icon-picker-custom\\\">\\n <label class=\\\"bjs-icon-picker-custom-label\\\" for=\\\"icon-custom-\".concat(this.id, \"\\\">\").concat(this._esc(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.custom_label')), \"</label>\\n <input\\n type=\\\"text\\\"\\n id=\\\"icon-custom-\").concat(this.id, \"\\\"\\n class=\\\"bjs-text-input\\\"\\n data-control=\\\"icon-custom\\\"\\n value=\\\"\").concat(this._esc(_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(this.value) ? '' : this.value), \"\\\"\\n placeholder=\\\"\").concat(this._esc(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.custom_placeholder')), \"\\\"\\n maxlength=\\\"16\\\"\\n autocomplete=\\\"off\\\"\\n />\\n </div>\\n \") : '';\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <label class=\\\"bjs-control-label\\\">\".concat(this._esc(this.label), \"</label>\\n <div class=\\\"bjs-control-input\\\">\\n <button\\n type=\\\"button\\\"\\n class=\\\"bjs-icon-trigger\\\"\\n aria-haspopup=\\\"listbox\\\"\\n aria-expanded=\\\"\").concat(this.isOpen ? 'true' : 'false', \"\\\"\\n data-control=\\\"icon-trigger\\\"\\n id=\\\"icon-trigger-\").concat(this.id, \"\\\"\\n >\\n <span class=\\\"bjs-icon-trigger-glyph\\\" aria-hidden=\\\"true\\\">\").concat(currentGlyph, \"</span>\\n <span class=\\\"bjs-icon-trigger-label\\\">\").concat(this._esc(currentLabel), \"</span>\\n <span class=\\\"bjs-icon-trigger-caret\\\" aria-hidden=\\\"true\\\"><svg viewBox=\\\"0 0 16 16\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"14\\\" height=\\\"14\\\" style=\\\"display:block\\\"><path d=\\\"M4 6l4 4 4-4\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.8\\\" fill=\\\"none\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/></svg></span>\\n </button>\\n </div>\\n </div>\\n <div\\n class=\\\"bjs-icon-popover\").concat(this.isOpen ? ' is-open' : '', \"\\\"\\n role=\\\"radiogroup\\\"\\n aria-labelledby=\\\"icon-trigger-\").concat(this.id, \"\\\"\\n data-control=\\\"icon-popover\\\"\\n >\\n <div class=\\\"bjs-icon-popover-grid\\\">\\n \").concat(tilesHtml, \"\\n \").concat(customTile, \"\\n </div>\\n \").concat(customInputHtml, \"\\n </div>\\n \");\n this._bind();\n }\n }, {\n key: \"_bind\",\n value: function _bind() {\n var _this2 = this;\n var trigger = this.domNode.querySelector('[data-control=\"icon-trigger\"]');\n var popover = this.domNode.querySelector('[data-control=\"icon-popover\"]');\n if (!trigger || !popover) return;\n trigger.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this2._toggle();\n });\n var tiles = Array.from(popover.querySelectorAll('.bjs-icon-tile'));\n tiles.forEach(function (tile, idx) {\n tile.addEventListener('click', function (e) {\n e.preventDefault();\n var key = tile.dataset.key;\n if (key === '__custom') {\n _this2.isCustomOpen = true;\n _this2.render();\n var input = _this2.domNode.querySelector('[data-control=\"icon-custom\"]');\n if (input) input.focus();\n return;\n }\n _this2._select(key);\n _this2._close();\n });\n tile.addEventListener('keydown', function (e) {\n var cols = 6;\n var target = null;\n if (e.key === 'ArrowRight') target = tiles[(idx + 1) % tiles.length];else if (e.key === 'ArrowLeft') target = tiles[(idx - 1 + tiles.length) % tiles.length];else if (e.key === 'ArrowDown') target = tiles[Math.min(idx + cols, tiles.length - 1)];else if (e.key === 'ArrowUp') target = tiles[Math.max(idx - cols, 0)];else if (e.key === 'Enter' || e.key === ' ') {\n tile.click();\n e.preventDefault();\n return;\n } else if (e.key === 'Escape') {\n _this2._close();\n trigger.focus();\n e.preventDefault();\n return;\n }\n if (target) {\n e.preventDefault();\n target.focus();\n }\n });\n });\n var customInput = this.domNode.querySelector('[data-control=\"icon-custom\"]');\n if (customInput) {\n var t = null;\n customInput.addEventListener('input', function (e) {\n var v = (e.target.value || '').trim();\n // Debounce to avoid re-render thrash as user types\n if (t) clearTimeout(t);\n t = setTimeout(function () {\n _this2.value = v;\n _this2.callback && _this2.callback.setValue && _this2.callback.setValue(v);\n _this2._refreshTrigger();\n }, 180);\n });\n customInput.addEventListener('keydown', function (e) {\n if (e.key === 'Escape') {\n _this2._close();\n trigger.focus();\n e.preventDefault();\n }\n });\n }\n }\n }, {\n key: \"_toggle\",\n value: function _toggle() {\n if (this.isOpen) this._close();else this._open();\n }\n }, {\n key: \"_open\",\n value: function _open() {\n var _this3 = this;\n this.isOpen = true;\n this.render();\n var active = this.domNode.querySelector('.bjs-icon-tile[aria-checked=\"true\"]') || this.domNode.querySelector('.bjs-icon-tile');\n if (active) active.focus();\n this._documentClickHandler = function (e) {\n if (!_this3.domNode.contains(e.target)) _this3._close();\n };\n this._documentKeydownHandler = function (e) {\n if (e.key === 'Escape') _this3._close();\n };\n document.addEventListener('click', this._documentClickHandler);\n document.addEventListener('keydown', this._documentKeydownHandler);\n }\n }, {\n key: \"_close\",\n value: function _close() {\n if (!this.isOpen) return;\n this.isOpen = false;\n this.render();\n if (this._documentClickHandler) document.removeEventListener('click', this._documentClickHandler);\n if (this._documentKeydownHandler) document.removeEventListener('keydown', this._documentKeydownHandler);\n this._documentClickHandler = null;\n this._documentKeydownHandler = null;\n }\n }, {\n key: \"_select\",\n value: function _select(key) {\n this.value = key || '';\n this.isCustomOpen = false;\n this.callback && this.callback.setValue && this.callback.setValue(this.value);\n // Render() is invoked by _close() after this call.\n }\n\n // Update the trigger preview without a full re-render. Used while the\n // user types in the custom-emoji input so the popover stays open but\n // the trigger glyph + label updates live.\n }, {\n key: \"_refreshTrigger\",\n value: function _refreshTrigger() {\n var glyphEl = this.domNode.querySelector('.bjs-icon-trigger-glyph');\n var labelEl = this.domNode.querySelector('.bjs-icon-trigger-label');\n if (!glyphEl || !labelEl) return;\n if (this.value) {\n glyphEl.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].render(this.value, {\n size: 20,\n color: 'currentColor'\n });\n labelEl.textContent = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(this.value) ? IconPickerControl.humanize(this.value) : this.value;\n } else {\n glyphEl.innerHTML = '<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\"><circle cx=\"10\" cy=\"10\" r=\"7.5\" stroke=\"currentColor\" stroke-width=\"1.25\" stroke-dasharray=\"2 2\" fill=\"none\"/></svg>';\n labelEl.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.none');\n }\n }\n }, {\n key: \"setValue\",\n value: function setValue(value) {\n this.value = value || '';\n this.isCustomOpen = this._detectCustom(this.value);\n this.render();\n }\n }, {\n key: \"_esc\",\n value: function _esc(s) {\n return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''');\n }\n }], [{\n key: \"defaultOptions\",\n value: function defaultOptions() {\n // Build from the icon registry + a \"None\" option. \"Custom emoji\" is\n // rendered last as a special tile (below the registry options).\n var opts = [{\n key: '',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.none')\n }];\n _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].allNames().forEach(function (name) {\n opts.push({\n key: name,\n label: IconPickerControl.humanize(name)\n });\n });\n return opts;\n }\n }, {\n key: \"humanize\",\n value: function humanize(name) {\n return String(name).replace(/_/g, ' ').replace(/\\b\\w/g, function (c) {\n return c.toUpperCase();\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (IconPickerControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/IconPickerControl.js?");
/***/ }),
/***/ "./src/includes/ImageControl.js":
/*!**************************************!*\
!*** ./src/includes/ImageControl.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseControl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseControl.js */ \"./src/includes/BaseControl.js\");\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n/**\n * ImageControl — sidebar preview + src/alt/url editor for ImageElement.\n *\n * Phase 1.8: Extends BaseControl so destroy() runs when the sidebar\n * rebuilds. Subscribes to element.render() via addSyncListener so overlay\n * mutations to element.src / element.alt auto-refresh here — the overlay\n * never needs to call this control directly (SA I13 observer pattern).\n * Legacy syncFromExternal(value) signature is preserved for back-compat.\n */\nvar ImageControl = /*#__PURE__*/function (_BaseControl) {\n function ImageControl(label, value, callback) {\n var _this;\n _classCallCheck(this, ImageControl);\n _this = _callSuper(this, ImageControl);\n _this.label = label;\n _this.value = value.src;\n _this.alt = value.alt;\n _this.callback = callback;\n _this.UploadMode = true;\n _this.PasteMode = false;\n _this.domNode = document.createElement('div');\n _this.debounceAltTimeout = null;\n _this.debounceUrlTimeout = null;\n\n // Phase 1.8 (SA I13) — subscribe via capability token. On notify,\n // pull fresh state via readState() (primitives like src/alt aren't\n // live references, so a getter is required). Overlay's Upload flow\n // mutates element.src then calls element.render(); the element's\n // notifySyncListeners invokes this subscriber automatically.\n if (typeof value.subscribe === 'function' && typeof value.readState === 'function') {\n _this.addDisposer(value.subscribe(function () {\n var fresh = value.readState();\n _this.syncFromExternal({\n src: fresh.src,\n alt: fresh.alt\n });\n }));\n }\n\n // Legacy shim — back-compat for overlay Upload call site that reads\n // host._activeControls.image. Wired in afterRender() so host\n // injection has already run; cleared in destroy().\n // (NOTE: this.host is null at constructor time — Builder\n // assigns it AFTER getControls() returns, BEFORE afterRender().)\n\n _this.render();\n return _this;\n }\n\n /** Hook fires after Builder.renderElementControls has appended this\n * control's domNode AND assigned `this.host`. Safe place to register\n * the active-control slot used by ImageActionsOverlay's sync flow. */\n _inherits(ImageControl, _BaseControl);\n return _createClass(ImageControl, [{\n key: \"afterRender\",\n value: function afterRender() {\n if (this.host) {\n this.host._activeControls = this.host._activeControls || {};\n this.host._activeControls.image = this;\n }\n }\n\n /** Control teardown (SA I14). BaseControl runs stashed disposers;\n * additionally clear the legacy shim slot so orphaned overlay code\n * can't write to a ghost instance. */\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this.host && this.host._activeControls && this.host._activeControls.image === this) {\n this.host._activeControls.image = null;\n }\n _superPropGet(ImageControl, \"destroy\", this, 3)([]);\n }\n\n /**\n * Patch the sidebar preview in place to reflect a new image value\n * sourced from outside this control (typically the canvas overlay's\n * Upload / Replace flow). Does NOT call `builder.renderElementControls`\n * — that would tear down + rebuild the entire panel + reset focus\n * (NO-FLICKER, SA invariant I9).\n *\n * Patches per field:\n * - src: reassigns `this.value`, swaps the preview <img src=>, refreshes\n * filename + dimensions meta, and (in paste mode only, when not\n * focused) updates the URL input's value.\n * - alt: reassigns `this.alt` and (when not focused) updates the alt\n * <input> value. Skipping the focused-input write preserves any\n * in-flight typing the user is doing.\n *\n * Pass `undefined` for fields you don't want to touch; pass the new\n * value (including `''`) for fields you DO want to update.\n */\n }, {\n key: \"syncFromExternal\",\n value: function syncFromExternal(value) {\n if (!value || _typeof(value) !== 'object') return;\n if (this._destroyed) return;\n if (!this.domNode) return; // DOM gone — sidebar rebuilt or section destroyed\n\n if (value.src !== undefined && value.src !== this.value) {\n this.value = value.src;\n var previewImg = this.domNode.querySelector('.bjs-image-preview img');\n if (previewImg) previewImg.src = value.src;\n var urlInput = this.domNode.querySelector('[name=\"image-url\"]');\n if (urlInput && document.activeElement !== urlInput) {\n urlInput.value = value.src;\n }\n this._updateImageMeta(value.src);\n }\n if (value.alt !== undefined && value.alt !== this.alt) {\n this.alt = value.alt;\n var altInput = this.domNode.querySelector('[name=\"alt-text\"]');\n if (altInput && document.activeElement !== altInput) {\n altInput.value = value.alt;\n }\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-stack\\\">\\n <div class=\\\"bjs-control-label\\\"><span>\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.mode'), \"</span></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-image-input\\\">\\n <div class=\\\"bjs-segmented bjs-image-input-mode\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.mode'), \"\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\").concat(this.UploadMode ? ' is-active' : '', \"\\\"\\n data-mode=\\\"upload\\\" role=\\\"radio\\\" aria-checked=\\\"\").concat(this.UploadMode, \"\\\">\\n \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.upload_image'), \"\\n </button>\\n <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\").concat(this.PasteMode ? ' is-active' : '', \"\\\"\\n data-mode=\\\"paste\\\" role=\\\"radio\\\" aria-checked=\\\"\").concat(this.PasteMode, \"\\\">\\n \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.paste_url'), \"\\n </button>\\n </div>\\n \").concat(this.UploadMode ? this._renderUploadMode() : this._renderPasteMode(), \"\\n </div>\\n </div>\\n </div>\\n <div class=\\\"bjs-control-stack\\\">\\n <div class=\\\"bjs-control-label\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.alt_text'), \"</span></div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" name=\\\"alt-text\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.enter_alt'), \"\\\" value=\\\"\").concat(this._escAttr(this.alt), \"\\\">\\n </div>\\n </div>\\n \");\n this._bindEvents();\n }\n }, {\n key: \"_renderUploadMode\",\n value: function _renderUploadMode() {\n var _this$host;\n return \"\\n <div class=\\\"bjs-image-input-body\\\">\\n <div class=\\\"bjs-image-preview\\\">\\n <img src=\\\"\".concat(this.value, \"\\\" alt=\\\"\\\">\\n </div>\\n <div class=\\\"bjs-image-meta\\\">\\n <div class=\\\"bjs-image-meta-name\\\" data-field=\\\"name\\\">--</div>\\n <div class=\\\"bjs-image-meta-size\\\" data-field=\\\"size\\\">-- \\xD7 -- px</div>\\n <div class=\\\"bjs-image-actions\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"upload\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.upload'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">upload</span>\\n </button>\\n \").concat((_this$host = this.host) !== null && _this$host !== void 0 && _this$host.fileManager ? \"\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"browse\\\" aria-label=\\\"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.browse'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">folder_open</span>\\n </button>\\n \") : '', \"\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"reload\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.replace'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">sync</span>\\n </button>\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-icon-btn--danger\\\" data-control=\\\"delete\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.remove'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">delete</span>\\n </button>\\n </div>\\n </div>\\n </div>\\n \");\n }\n }, {\n key: \"_renderPasteMode\",\n value: function _renderPasteMode() {\n return \"\\n <div class=\\\"bjs-image-input-body\\\">\\n <div class=\\\"bjs-image-preview\\\">\\n <img src=\\\"\".concat(this.value, \"\\\" alt=\\\"\\\">\\n </div>\\n <div class=\\\"bjs-image-meta\\\">\\n <input type=\\\"url\\\" name=\\\"image-url\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.enter_url'), \"\\\" value=\\\"\").concat(this._escAttr(this.value), \"\\\">\\n <div class=\\\"bjs-image-meta-size\\\" data-field=\\\"size\\\">-- \\xD7 -- px</div>\\n </div>\\n </div>\\n \");\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this2 = this;\n // Mode toggle\n var modeGroup = this.domNode.querySelector('.bjs-image-input-mode');\n if (modeGroup) {\n modeGroup.addEventListener('click', function (e) {\n var btn = e.target.closest('.bjs-segmented-btn');\n if (!btn) return;\n var mode = btn.dataset.mode;\n if (mode) _this2._switchMode(mode);\n });\n modeGroup.addEventListener('keydown', function (e) {\n if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) return;\n e.preventDefault();\n var buttons = Array.from(modeGroup.querySelectorAll('.bjs-segmented-btn'));\n var currentIndex = buttons.findIndex(function (b) {\n return b.classList.contains('is-active');\n });\n var nextIndex = currentIndex;\n if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n nextIndex = (currentIndex - 1 + buttons.length) % buttons.length;\n } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n nextIndex = (currentIndex + 1) % buttons.length;\n } else if (e.key === 'Home') {\n nextIndex = 0;\n } else if (e.key === 'End') {\n nextIndex = buttons.length - 1;\n }\n var nextBtn = buttons[nextIndex];\n if (nextBtn) {\n _this2._switchMode(nextBtn.dataset.mode);\n nextBtn.focus();\n }\n });\n }\n\n // Alt text input — debounce 300ms\n var altInput = this.domNode.querySelector('[name=\"alt-text\"]');\n if (altInput) {\n altInput.addEventListener('input', function () {\n clearTimeout(_this2.debounceAltTimeout);\n _this2.debounceAltTimeout = setTimeout(function () {\n _this2.alt = altInput.value;\n _this2.callback.setAlt(_this2.alt);\n }, 300);\n });\n }\n if (this.UploadMode) {\n this._bindUploadMode();\n } else {\n this._bindPasteMode();\n }\n\n // Update image meta in both modes (preview exists in both)\n this._updateImageMeta(this.value);\n }\n }, {\n key: \"_bindUploadMode\",\n value: function _bindUploadMode() {\n var _this3 = this;\n var uploadBtn = this.domNode.querySelector('[data-control=\"upload\"]');\n if (uploadBtn) {\n uploadBtn.addEventListener('click', function () {\n return _this3._openFileBrowser();\n });\n }\n var browseBtn = this.domNode.querySelector('[data-control=\"browse\"]');\n if (browseBtn) {\n browseBtn.addEventListener('click', function () {\n return _this3._openMediaBrowser();\n });\n }\n var reloadBtn = this.domNode.querySelector('[data-control=\"reload\"]');\n if (reloadBtn) {\n reloadBtn.addEventListener('click', function () {\n // Just refresh the image without full re-render\n var img = _this3.domNode.querySelector('.bjs-image-preview img');\n if (img) {\n img.src = _this3.value + '?' + new Date().getTime();\n _this3._updateImageMeta(_this3.value);\n }\n });\n }\n var deleteBtn = this.domNode.querySelector('[data-control=\"delete\"]');\n if (deleteBtn) {\n deleteBtn.addEventListener('click', function () {\n var emptyImageUrl = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJMYXllcl8yIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyOTYgMjk2Ij48ZyBpZD0iTGF5ZXJfMS0yIj48cmVjdCB3aWR0aD0iMjk2IiBoZWlnaHQ9IjI5NiIgc3R5bGU9ImZpbGw6I2U2ZTZlNjsiLz48cGF0aCBkPSJNMjM2Ljk4LDk5LjQ0Yy0xLjEyLDAtMi4wMi45MS0yLjAyLDIuMDJ2OTMuMzZjMCw0LjktMi4zLDkuMjctNS44NywxMi4xMWwtNDYuMS00Ny4yM2MtLjc1LS43Ny0xLjk3LS44Mi0yLjc4LS4xMmwtMzIuMTgsMjcuOTgtNS43OS01Ljk1Yy0uNzgtLjgtMi4wNi0uODItMi44Ni0uMDQtLjguNzgtLjgyLDIuMDYtLjA0LDIuODZsNy4xMyw3LjMzYy43NS43NywxLjk3LjgyLDIuNzguMTJsMzIuMTgtMjcuOTgsNDQuMDksNDUuMThjLTEuODYuNzktMy45LDEuMjMtNi4wNSwxLjIzaC0xMTIuNjRjLTEuMTIsMC0yLjAyLjktMi4wMiwyLjAycy45MSwyLjAyLDIuMDIsMi4wMmgxMTIuNjRjMTAuNzcsMCwxOS41My04Ljc2LDE5LjUzLTE5LjUzdi05My4zNmMwLTEuMTItLjktMi4wMi0yLjAyLTIuMDJaIiBzdHlsZT0iZmlsbDpncmF5OyIvPjxwYXRoIGQ9Ik0yMzguNDgsNjYuOWMtLjc1LS44My0yLjAzLS45LTIuODYtLjE2bC0xNi45MywxNS4xOEg3Ni4zNmMtMTAuNzcsMC0xOS41Myw4Ljc2LTE5LjUzLDE5LjUzdjkzLjM2YzAsOS4xNiw2LjM2LDE2Ljg2LDE0Ljg5LDE4Ljk1bC0xNC4yMiwxMi43NWMtLjgzLjc0LS45LDIuMDMtLjE2LDIuODYuNC40NS45NS42NywxLjUxLjY3LjQ4LDAsLjk2LS4xNywxLjM1LS41MkwyMzguMzMsNjkuNzZjLjgzLS43NS45LTIuMDMuMTYtMi44NlpNNzYuMzYsODUuOThoMTM3LjgybC04OC4wOSw3OS4wMi0yMS44My0yMi40NWMtLjc2LS43OC0xLjk5LS44Mi0yLjgtLjA5bC00MC41NywzNi40NXYtNzcuNDVjMC04LjU0LDYuOTQtMTUuNDgsMTUuNDgtMTUuNDhaTTYwLjg4LDE5NC44MnYtMTAuNDdsNDEuODMtMzcuNTgsMjAuMzYsMjAuOTQtNDcuNDQsNDIuNTVjLTguMTktLjM5LTE0Ljc1LTcuMTUtMTQuNzUtMTUuNDRaIiBzdHlsZT0iZmlsbDpncmF5OyIvPjxwYXRoIGQ9Ik0xMjIuODMsMTI5LjEzYy04LjE5LDAtMTQuODUtNi42Ni0xNC44NS0xNC44NXM2LjY2LTE0Ljg1LDE0Ljg1LTE0Ljg1LDE0Ljg1LDYuNjYsMTQuODUsMTQuODUtNi42NiwxNC44NS0xNC44NSwxNC44NVpNMTIyLjgzLDEwMy40OGMtNS45NSwwLTEwLjgsNC44NC0xMC44LDEwLjhzNC44NCwxMC44LDEwLjgsMTAuOCwxMC44LTQuODQsMTAuOC0xMC44LTQuODQtMTAuOC0xMC44LTEwLjhaIiBzdHlsZT0iZmlsbDpncmF5OyIvPjwvZz48L3N2Zz4=';\n _this3.value = emptyImageUrl;\n _this3.callback.setImage(emptyImageUrl);\n _this3.render();\n });\n }\n }\n }, {\n key: \"_bindPasteMode\",\n value: function _bindPasteMode() {\n var _this4 = this;\n var imageInput = this.domNode.querySelector('[name=\"image-url\"]');\n if (!imageInput) return;\n var applyUrl = function applyUrl() {\n var newUrl = imageInput.value;\n _this4.value = newUrl;\n _this4.callback.setImage(newUrl);\n var previewImg = _this4.domNode.querySelector('.bjs-image-preview img');\n if (previewImg) previewImg.src = newUrl;\n _this4._updateImageMeta(newUrl);\n };\n imageInput.addEventListener('input', function () {\n clearTimeout(_this4.debounceUrlTimeout);\n _this4.debounceUrlTimeout = setTimeout(applyUrl, 350);\n });\n imageInput.addEventListener('change', function () {\n clearTimeout(_this4.debounceUrlTimeout);\n applyUrl();\n });\n }\n }, {\n key: \"_switchMode\",\n value: function _switchMode(mode) {\n if (mode === 'upload') {\n this.UploadMode = true;\n this.PasteMode = false;\n } else if (mode === 'paste') {\n this.UploadMode = false;\n this.PasteMode = true;\n }\n this.render();\n }\n }, {\n key: \"_updateImageMeta\",\n value: function _updateImageMeta(url) {\n var nameField = this.domNode.querySelector('[data-field=\"name\"]');\n var sizeField = this.domNode.querySelector('[data-field=\"size\"]');\n if (!url) {\n if (nameField) nameField.textContent = '--';\n if (sizeField) sizeField.textContent = '-- × -- px';\n return;\n }\n\n // Extract filename from URL (strip query string + path)\n var filename = (url.split('/').pop() || '').split('?')[0] || '--';\n if (nameField) nameField.textContent = filename;\n\n // Use Image() to read natural dimensions — no blob fetch required\n var img = new Image();\n img.onload = function () {\n if (sizeField) sizeField.textContent = \"\".concat(img.naturalWidth, \" \\xD7 \").concat(img.naturalHeight, \" px\");\n };\n img.onerror = function () {\n if (sizeField) sizeField.textContent = '-- × -- px';\n };\n img.src = url;\n }\n }, {\n key: \"_openFileBrowser\",\n value: function _openFileBrowser() {\n var _this5 = this;\n var input = document.createElement('input');\n input.type = 'file';\n input.accept = 'image/*';\n input.addEventListener('change', /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(event) {\n var file, formData, response, result;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n file = event.target.files[0];\n if (!file) {\n _context.next = 18;\n break;\n }\n formData = new FormData();\n formData.append('file', file);\n _context.prev = 4;\n _context.next = 7;\n return fetch(_this5.host.assetUploadHandler, {\n method: 'POST',\n body: formData\n });\n case 7:\n response = _context.sent;\n if (!response.ok) {\n _context.next = 13;\n break;\n }\n _context.next = 11;\n return response.json();\n case 11:\n result = _context.sent;\n if (result.url) {\n _this5.value = result.url;\n _this5.callback.setImage(result.url);\n _this5.render();\n }\n case 13:\n _context.next = 18;\n break;\n case 15:\n _context.prev = 15;\n _context.t0 = _context[\"catch\"](4);\n console.error('Error uploading file:', _context.t0);\n case 18:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[4, 15]]);\n }));\n return function (_x) {\n return _ref.apply(this, arguments);\n };\n }());\n input.click();\n }\n }, {\n key: \"_openMediaBrowser\",\n value: function _openMediaBrowser() {\n var _this$host2,\n _this6 = this;\n if (!((_this$host2 = this.host) !== null && _this$host2 !== void 0 && _this$host2.fileManager)) return;\n this.host.browseMedia(function (url) {\n if (url) {\n _this6.value = url;\n _this6.callback.setImage(url);\n _this6.render();\n _this6.host.closeBrowseMedia();\n }\n });\n }\n }, {\n key: \"_escAttr\",\n value: function _escAttr(str) {\n return (str || '').replace(/\"/g, '"').replace(/</g, '<');\n }\n }]);\n}(_BaseControl_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageControl.js?");
/***/ }),
/***/ "./src/includes/ImageCropControl.js":
/*!******************************************!*\
!*** ./src/includes/ImageCropControl.js ***!
\******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseControl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseControl.js */ \"./src/includes/BaseControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n/**\n * ImageCropControl\n *\n * CSS-based image crop / focus point / zoom selector.\n * Aspect ratio is expressed as TWO INTEGERS (ratioX:ratioY) — best practice for\n * responsive emails. The actual crop frame width is 100% of its parent; height\n * is auto-derived via CSS `aspect-ratio: X/Y`.\n *\n * Render output (in Image.template.html when crop.enabled):\n * <div style=\"overflow:hidden; aspect-ratio: X/Y; width:100%\">\n * <img style=\"object-fit:cover; object-position:X% Y%; transform:scale(N); ...\">\n * </div>\n *\n * UI:\n * - Toggle on/off\n * - Email-compat info banner (Outlook 2007–2013 falls back to original image)\n * - Live preview with rule-of-thirds grid, draggable focus dot, scroll-wheel zoom\n * - Preset chips: Original, 1:1, 16:9, 4:3, 3:2, 2:3, 21:9, 9:16\n * (\"Original\" loads image natural dimensions, GCD-reduces to integers)\n * - Custom inputs: [X] : [Y] with swap button (rotate 90°)\n * - Live \"Ratio: X:Y\" display\n * - Sliders: Zoom (1×–3×), Focus X (0–100%), Focus Y (0–100%)\n * - Reset button\n *\n * Phase 1.8 (SA I13/I14): Extends BaseControl → auto-dispose of the\n * sync-listener subscription when the sidebar rebuilds.\n */\nvar ImageCropControl = /*#__PURE__*/function (_BaseControl) {\n function ImageCropControl(label, value, callback) {\n var _this;\n _classCallCheck(this, ImageCropControl);\n _this = _callSuper(this, ImageCropControl);\n _this.label = label;\n _this.src = value.src;\n var c = value.crop || {};\n _this.crop = {\n enabled: !!c.enabled,\n ratioX: _this._safeRatio(c.ratioX, 3),\n ratioY: _this._safeRatio(c.ratioY, 2),\n zoom: typeof c.zoom === 'number' ? c.zoom : 1,\n posX: typeof c.posX === 'number' ? c.posX : 50,\n posY: typeof c.posY === 'number' ? c.posY : 50\n };\n _this.callback = callback;\n\n // Phase 1.4 (SA invariant I4) — stash source reference so overlay-side\n // mutations to element.crop can be re-read via syncFromExternal(). The\n // caller (ImageElement.getControls) passes the element's own crop object\n // via `value.crop` — storing value (not a copy) lets us re-read on demand.\n _this._sourceValueRef = value;\n\n // Phase 1.8 (SA I13) — subscribe to state-change notifications. The\n // caller passes a narrow `subscribe(fn) → disposer` capability token\n // (NOT the whole element). Control stays decoupled from element API;\n // future infrastructure changes (render-hook → event bus → whatever)\n // don't propagate here. Disposer auto-runs in BaseControl.destroy.\n if (typeof value.subscribe === 'function') {\n _this.addDisposer(value.subscribe(function () {\n return _this.syncFromExternal();\n }));\n }\n\n // Legacy shim slot is registered in afterRender() — this.host is\n // null at constructor time. Cleared in destroy().\n\n // Preset ratios — common photographic / video / mobile / cinema standards.\n // \"original\" is special: resolved at click time from image natural size.\n _this.presets = [{\n x: null,\n y: null,\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.preset_original'),\n original: true\n }, {\n x: 1,\n y: 1,\n label: '1:1'\n }, {\n x: 16,\n y: 9,\n label: '16:9'\n }, {\n x: 4,\n y: 3,\n label: '4:3'\n }, {\n x: 3,\n y: 2,\n label: '3:2'\n }, {\n x: 2,\n y: 3,\n label: '2:3'\n }, {\n x: 21,\n y: 9,\n label: '21:9'\n }, {\n x: 9,\n y: 16,\n label: '9:16'\n }];\n _this.zoomDef = {\n min: 1,\n max: 3,\n step: 0.05,\n def: 1\n };\n _this.RATIO_MAX = 99;\n _this.domNode = document.createElement('div');\n _this.domNode.className = 'ImageCropControl';\n _this._dragging = false;\n _this.render();\n return _this;\n }\n _inherits(ImageCropControl, _BaseControl);\n return _createClass(ImageCropControl, [{\n key: \"_safeRatio\",\n value: function _safeRatio(v, def) {\n var n = parseInt(v, 10);\n if (!Number.isFinite(n) || n < 1) return def;\n return Math.min(this.RATIO_MAX, n);\n }\n\n /**\n * Greatest common divisor for reducing image natural dimensions\n * (e.g. 1920×1080 → 16:9, 4032×3024 → 4:3).\n */\n }, {\n key: \"_gcd\",\n value: function _gcd(a, b) {\n a = Math.abs(a);\n b = Math.abs(b);\n while (b) {\n var _ref = [b, a % b];\n a = _ref[0];\n b = _ref[1];\n }\n return a || 1;\n }\n }, {\n key: \"isModified\",\n value: function isModified() {\n if (!this.crop.enabled) return false;\n // Default = 3:2, zoom 1, focus 50/50\n return this.crop.ratioX !== 3 || this.crop.ratioY !== 2 || this.crop.zoom !== 1 || this.crop.posX !== 50 || this.crop.posY !== 50;\n }\n }, {\n key: \"_matchedPreset\",\n value: function _matchedPreset() {\n var _this2 = this;\n return this.presets.find(function (p) {\n return !p.original && p.x === _this2.crop.ratioX && p.y === _this2.crop.ratioY;\n }) || null;\n }\n }, {\n key: \"render\",\n value: function render() {\n // Defensive: snap any rogue values back to safe defaults BEFORE rendering\n // (guards against external code or async race conditions setting NaN/null).\n this.crop.ratioX = this._safeRatio(this.crop.ratioX, 3);\n this.crop.ratioY = this._safeRatio(this.crop.ratioY, 2);\n if (!Number.isFinite(this.crop.zoom)) this.crop.zoom = 1;\n if (!Number.isFinite(this.crop.posX)) this.crop.posX = 50;\n if (!Number.isFinite(this.crop.posY)) this.crop.posY = 50;\n var c = this.crop;\n var matched = this._matchedPreset();\n var presetChips = this.presets.map(function (p) {\n var isActive = !p.original && matched && matched.label === p.label;\n var dataAttrs = p.original ? \"data-preset=\\\"original\\\"\" : \"data-rx=\\\"\".concat(p.x, \"\\\" data-ry=\\\"\").concat(p.y, \"\\\"\");\n return \"\\n <button type=\\\"button\\\"\\n class=\\\"icrop-chip\".concat(isActive ? ' is-active' : '').concat(p.original ? ' icrop-chip-original' : '', \"\\\"\\n \").concat(dataAttrs, \"\\n \").concat(!c.enabled ? 'disabled' : '', \"\\n data-tooltip=\\\"\").concat(p.label, \"\\\">\").concat(p.label, \"</button>\\n \");\n }).join('');\n var zoomPct = (c.zoom - this.zoomDef.min) / (this.zoomDef.max - this.zoomDef.min) * 100;\n this.domNode.innerHTML = \"\\n <div class=\\\"icrop-container\".concat(c.enabled ? ' is-enabled' : '', \"\\\" data-role=\\\"container\\\">\\n <div class=\\\"icrop-header\\\">\\n <label class=\\\"icrop-title\\\">\").concat(this.label, \"</label>\\n <label class=\\\"icrop-toggle\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.toggle_hint'), \"\\\">\\n <input type=\\\"checkbox\\\" class=\\\"icrop-toggle-input\\\" data-role=\\\"enabled\\\" \").concat(c.enabled ? 'checked' : '', \">\\n <span class=\\\"icrop-toggle-slider\\\"></span>\\n </label>\\n </div>\\n\\n <div class=\\\"icrop-body\\\" data-role=\\\"body\\\" \").concat(c.enabled ? '' : 'hidden', \">\\n <div class=\\\"icrop-info\\\">\\n <span class=\\\"icrop-info-icon\\\" aria-hidden=\\\"true\\\">\\n <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\">\\n <circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"10\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\"/>\\n <path d=\\\"M12 8v5\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\" stroke-linecap=\\\"round\\\"/>\\n <circle cx=\\\"12\\\" cy=\\\"16.2\\\" r=\\\"1\\\" fill=\\\"currentColor\\\"/>\\n </svg>\\n </span>\\n <span class=\\\"icrop-info-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.email_warning'), \"</span>\\n </div>\\n\\n <div class=\\\"icrop-preview-wrap\\\">\\n <div class=\\\"icrop-preview\\\" data-role=\\\"preview\\\" style=\\\"aspect-ratio:\").concat(c.ratioX, \"/\").concat(c.ratioY, \";\\\">\\n <img src=\\\"\").concat(this.src, \"\\\" alt=\\\"\\\"\\n class=\\\"icrop-preview-img\\\"\\n style=\\\"object-position:\").concat(c.posX, \"% \").concat(c.posY, \"%; transform:scale(\").concat(c.zoom, \"); transform-origin:\").concat(c.posX, \"% \").concat(c.posY, \"%;\\\"\\n draggable=\\\"false\\\">\\n <div class=\\\"icrop-focus-dot\\\" style=\\\"left:\").concat(c.posX, \"%; top:\").concat(c.posY, \"%;\\\" aria-hidden=\\\"true\\\"></div>\\n <div class=\\\"icrop-grid\\\" aria-hidden=\\\"true\\\">\\n <span></span><span></span><span></span><span></span>\\n </div>\\n </div>\\n <div class=\\\"icrop-preview-hint\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.preview_hint'), \"</div>\\n </div>\\n\\n <div class=\\\"icrop-section\\\">\\n <div class=\\\"icrop-section-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.aspect_ratio'), \"</div>\\n <div class=\\\"icrop-chips\\\">\").concat(presetChips, \"</div>\\n </div>\\n\\n <div class=\\\"icrop-section\\\">\\n <div class=\\\"icrop-section-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.custom_ratio'), \"</div>\\n <div class=\\\"icrop-ratio-row\\\">\\n <input type=\\\"number\\\" class=\\\"icrop-ratio-input\\\" data-role=\\\"ratioX\\\"\\n min=\\\"1\\\" max=\\\"\").concat(this.RATIO_MAX, \"\\\" step=\\\"1\\\"\\n value=\\\"\").concat(c.ratioX, \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.ratio_x'), \"\\\">\\n <span class=\\\"icrop-ratio-sep\\\">:</span>\\n <input type=\\\"number\\\" class=\\\"icrop-ratio-input\\\" data-role=\\\"ratioY\\\"\\n min=\\\"1\\\" max=\\\"\").concat(this.RATIO_MAX, \"\\\" step=\\\"1\\\"\\n value=\\\"\").concat(c.ratioY, \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.ratio_y'), \"\\\">\\n <button type=\\\"button\\\" class=\\\"icrop-ratio-swap\\\" data-role=\\\"swap\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.swap_hint'), \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.swap_hint'), \"\\\">\\n <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 16 16\\\" fill=\\\"none\\\">\\n <path d=\\\"M3 5h9M3 5l3-3M3 5l3 3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.4\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M13 11H4M13 11l-3-3M13 11l-3 3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.4\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\\n </button>\\n <span class=\\\"icrop-ratio-display\\\">= \").concat(c.ratioX, \":\").concat(c.ratioY, \"</span>\\n </div>\\n </div>\\n\\n <div class=\\\"icrop-section\\\">\\n <div class=\\\"icrop-row\\\">\\n <label class=\\\"icrop-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.zoom'), \"</label>\\n <div class=\\\"icrop-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"icrop-slider\\\" data-role=\\\"zoom\\\"\\n min=\\\"\").concat(this.zoomDef.min, \"\\\" max=\\\"\").concat(this.zoomDef.max, \"\\\" step=\\\"\").concat(this.zoomDef.step, \"\\\"\\n value=\\\"\").concat(c.zoom, \"\\\" style=\\\"--pct:\").concat(zoomPct, \"%\\\">\\n </div>\\n <div class=\\\"icrop-value-wrap\\\">\\n <input type=\\\"number\\\" class=\\\"icrop-value-input\\\" data-role=\\\"zoom-num\\\"\\n min=\\\"\").concat(this.zoomDef.min, \"\\\" max=\\\"\").concat(this.zoomDef.max, \"\\\" step=\\\"\").concat(this.zoomDef.step, \"\\\"\\n value=\\\"\").concat(c.zoom.toFixed(2), \"\\\">\\n <span class=\\\"icrop-unit\\\">\\xD7</span>\\n </div>\\n </div>\\n\\n <div class=\\\"icrop-row\\\">\\n <label class=\\\"icrop-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.focus_x'), \"</label>\\n <div class=\\\"icrop-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"icrop-slider\\\" data-role=\\\"posX\\\"\\n min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\"\\n value=\\\"\").concat(c.posX, \"\\\" style=\\\"--pct:\").concat(c.posX, \"%\\\">\\n </div>\\n <div class=\\\"icrop-value-wrap\\\">\\n <input type=\\\"number\\\" class=\\\"icrop-value-input\\\" data-role=\\\"posX-num\\\"\\n min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(c.posX, \"\\\">\\n <span class=\\\"icrop-unit\\\">%</span>\\n </div>\\n </div>\\n\\n <div class=\\\"icrop-row\\\">\\n <label class=\\\"icrop-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.focus_y'), \"</label>\\n <div class=\\\"icrop-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"icrop-slider\\\" data-role=\\\"posY\\\"\\n min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\"\\n value=\\\"\").concat(c.posY, \"\\\" style=\\\"--pct:\").concat(c.posY, \"%\\\">\\n </div>\\n <div class=\\\"icrop-value-wrap\\\">\\n <input type=\\\"number\\\" class=\\\"icrop-value-input\\\" data-role=\\\"posY-num\\\"\\n min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(c.posY, \"\\\">\\n <span class=\\\"icrop-unit\\\">%</span>\\n </div>\\n </div>\\n </div>\\n\\n <div class=\\\"icrop-actions\\\">\\n <button type=\\\"button\\\" class=\\\"icrop-reset\\\" data-role=\\\"reset\\\" \").concat(this.isModified() ? '' : 'disabled', \">\\n <svg width=\\\"11\\\" height=\\\"11\\\" viewBox=\\\"0 0 12 12\\\" fill=\\\"none\\\" style=\\\"margin-right:4px;vertical-align:-1px;\\\">\\n <path d=\\\"M2 6a4 4 0 1 0 1.2-2.83\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/>\\n <path d=\\\"M2 2v3h3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\\n \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.reset'), \"\\n </button>\\n </div>\\n </div>\\n </div>\");\n this._setupListeners();\n }\n }, {\n key: \"_setupListeners\",\n value: function _setupListeners() {\n var _this3 = this;\n // Toggle enable/disable\n var toggle = this.domNode.querySelector('.icrop-toggle-input');\n toggle.addEventListener('change', function (e) {\n _this3.crop.enabled = e.target.checked;\n _this3._apply();\n _this3.render();\n });\n if (!this.crop.enabled) return;\n\n // Preset chips\n this.domNode.querySelectorAll('.icrop-chip').forEach(function (chip) {\n chip.addEventListener('click', function () {\n if (chip.dataset.preset === 'original') {\n _this3._applyOriginalRatio(chip);\n return;\n }\n _this3.crop.ratioX = parseInt(chip.dataset.rx, 10);\n _this3.crop.ratioY = parseInt(chip.dataset.ry, 10);\n _this3._apply();\n _this3.render();\n });\n });\n\n // Custom ratio inputs (X / Y)\n // While typing (input event), allow empty/partial values without re-rendering;\n // only on blur do we commit + clamp. This way the user can clear and re-type\n // without the field flicker-resetting to 1 on every keystroke.\n ['ratioX', 'ratioY'].forEach(function (role) {\n var input = _this3.domNode.querySelector(\".icrop-ratio-input[data-role=\\\"\".concat(role, \"\\\"]\"));\n if (!input) return;\n var debounce = null;\n input.addEventListener('input', function () {\n var v = parseInt(input.value, 10);\n if (!Number.isFinite(v) || v < 1) return; // ignore intermediate empty/0 state\n var clamped = Math.max(1, Math.min(_this3.RATIO_MAX, v));\n _this3.crop[role] = clamped;\n _this3._updatePreview();\n _this3._updateRatioDisplay();\n _this3._updateChipActive();\n _this3._updateResetState();\n clearTimeout(debounce);\n debounce = setTimeout(function () {\n return _this3._apply();\n }, 200);\n });\n input.addEventListener('blur', function () {\n var v = parseInt(input.value, 10);\n // Clamp to bounds (NaN/empty → 1, negative/0 → 1, > MAX → MAX).\n // Clamping > resetting because user intent was \"type a number\" — give\n // them the closest valid one rather than discarding their attempt.\n if (!Number.isFinite(v)) v = 1;\n v = Math.max(1, Math.min(_this3.RATIO_MAX, v));\n _this3.crop[role] = v;\n input.value = v; // snap visible value\n _this3._updatePreview();\n _this3._updateRatioDisplay();\n _this3._updateChipActive();\n _this3._updateResetState();\n _this3._apply();\n });\n });\n\n // Swap X ↔ Y\n var swap = this.domNode.querySelector('[data-role=\"swap\"]');\n if (swap) {\n swap.addEventListener('click', function () {\n var t = _this3.crop.ratioX;\n _this3.crop.ratioX = _this3.crop.ratioY;\n _this3.crop.ratioY = t;\n _this3._apply();\n _this3.render();\n });\n }\n\n // Zoom + focus sliders\n var wireRow = function wireRow(role) {\n var slider = _this3.domNode.querySelector(\".icrop-slider[data-role=\\\"\".concat(role, \"\\\"]\"));\n var numInput = _this3.domNode.querySelector(\".icrop-value-input[data-role=\\\"\".concat(role, \"-num\\\"]\"));\n var sync = function sync(val, source) {\n val = _this3._clamp(role, val);\n _this3.crop[role] = role === 'zoom' ? Math.round(val * 100) / 100 : Math.round(val);\n if (source !== 'slider') slider.value = _this3.crop[role];\n if (source !== 'input') numInput.value = role === 'zoom' ? _this3.crop[role].toFixed(2) : _this3.crop[role];\n var pct = role === 'zoom' ? (_this3.crop.zoom - _this3.zoomDef.min) / (_this3.zoomDef.max - _this3.zoomDef.min) * 100 : _this3.crop[role];\n slider.style.setProperty('--pct', pct + '%');\n _this3._updatePreview();\n _this3._updateResetState();\n };\n var debounce = null;\n slider.addEventListener('input', function (e) {\n sync(parseFloat(e.target.value), 'slider');\n clearTimeout(debounce);\n debounce = setTimeout(function () {\n return _this3._apply();\n }, 80);\n });\n numInput.addEventListener('input', function (e) {\n var v = parseFloat(e.target.value);\n if (isNaN(v)) return;\n sync(v, 'input');\n clearTimeout(debounce);\n debounce = setTimeout(function () {\n return _this3._apply();\n }, 150);\n });\n numInput.addEventListener('blur', function (e) {\n var v = parseFloat(e.target.value);\n if (isNaN(v)) v = role === 'zoom' ? 1 : 50;\n sync(v, 'both');\n _this3._apply();\n });\n };\n wireRow('zoom');\n wireRow('posX');\n wireRow('posY');\n\n // Drag focus on preview\n var preview = this.domNode.querySelector('[data-role=\"preview\"]');\n if (preview) {\n var move = function move(clientX, clientY) {\n var rect = preview.getBoundingClientRect();\n var x = Math.max(0, Math.min(100, (clientX - rect.left) / rect.width * 100));\n var y = Math.max(0, Math.min(100, (clientY - rect.top) / rect.height * 100));\n _this3.crop.posX = Math.round(x);\n _this3.crop.posY = Math.round(y);\n _this3._syncSlider('posX');\n _this3._syncSlider('posY');\n _this3._updatePreview();\n _this3._updateResetState();\n };\n var onDown = function onDown(e) {\n e.preventDefault();\n _this3._dragging = true;\n preview.classList.add('is-dragging');\n var ev = e.touches ? e.touches[0] : e;\n move(ev.clientX, ev.clientY);\n };\n var onMove = function onMove(e) {\n if (!_this3._dragging) return;\n var ev = e.touches ? e.touches[0] : e;\n move(ev.clientX, ev.clientY);\n };\n var onUp = function onUp() {\n if (!_this3._dragging) return;\n _this3._dragging = false;\n preview.classList.remove('is-dragging');\n _this3._apply();\n };\n preview.addEventListener('mousedown', onDown);\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', onUp);\n preview.addEventListener('touchstart', onDown, {\n passive: false\n });\n window.addEventListener('touchmove', onMove, {\n passive: false\n });\n window.addEventListener('touchend', onUp);\n\n // Wheel zoom\n preview.addEventListener('wheel', function (e) {\n e.preventDefault();\n var delta = e.deltaY > 0 ? -0.1 : 0.1;\n var z = _this3._clamp('zoom', _this3.crop.zoom + delta);\n z = Math.round(z * 100) / 100;\n _this3.crop.zoom = z;\n _this3._syncSlider('zoom');\n _this3._updatePreview();\n _this3._updateResetState();\n _this3._apply();\n }, {\n passive: false\n });\n }\n\n // Reset\n var resetBtn = this.domNode.querySelector('[data-role=\"reset\"]');\n resetBtn.addEventListener('click', function () {\n _this3.crop.ratioX = 3;\n _this3.crop.ratioY = 2;\n _this3.crop.zoom = 1;\n _this3.crop.posX = 50;\n _this3.crop.posY = 50;\n _this3._apply();\n _this3.render();\n });\n }\n\n /**\n * Find the integer pair (rx, ry) within [1, max] whose ratio rx/ry best\n * approximates target = w/h. Linear scan — RATIO_MAX is small (99), trivial.\n * Beats naive halving which discards precision (523:172 → 66:22 = 3.0\n * vs target 3.04). This finds 95:31 = 3.065 → much closer.\n */\n }, {\n key: \"_bestRatio\",\n value: function _bestRatio(w, h, max) {\n if (w <= max && h <= max) return [w, h]; // already fits\n var target = w / h;\n var best = [1, 1];\n var bestDiff = Infinity;\n // Search both axes to handle landscape and portrait equally well\n for (var rx = 1; rx <= max; rx++) {\n var ry = Math.round(rx / target);\n if (ry < 1 || ry > max) continue;\n var diff = Math.abs(rx / ry - target);\n if (diff < bestDiff) {\n bestDiff = diff;\n best = [rx, ry];\n }\n if (diff < 1e-6) return best;\n }\n for (var _ry = 1; _ry <= max; _ry++) {\n var _rx = Math.round(_ry * target);\n if (_rx < 1 || _rx > max) continue;\n var _diff = Math.abs(_rx / _ry - target);\n if (_diff < bestDiff) {\n bestDiff = _diff;\n best = [_rx, _ry];\n }\n if (_diff < 1e-6) return best;\n }\n return best;\n }\n\n /**\n * \"Original\" preset — load the image, read naturalWidth × naturalHeight,\n * GCD-reduce to integer ratio (e.g. 1920×1080 → 16:9). When GCD-reduced\n * pair exceeds RATIO_MAX, fall back to closest integer-pair approximation.\n */\n }, {\n key: \"_applyOriginalRatio\",\n value: function _applyOriginalRatio(chip) {\n var _this4 = this;\n var previewImg = this.domNode.querySelector('.icrop-preview-img');\n var apply = function apply(w, h) {\n if (!w || !h) return;\n var g = _this4._gcd(w, h);\n var rx = Math.round(w / g);\n var ry = Math.round(h / g);\n if (rx > _this4.RATIO_MAX || ry > _this4.RATIO_MAX) {\n var _this4$_bestRatio = _this4._bestRatio(rx, ry, _this4.RATIO_MAX);\n var _this4$_bestRatio2 = _slicedToArray(_this4$_bestRatio, 2);\n rx = _this4$_bestRatio2[0];\n ry = _this4$_bestRatio2[1];\n }\n _this4.crop.ratioX = Math.max(1, Math.min(_this4.RATIO_MAX, rx));\n _this4.crop.ratioY = Math.max(1, Math.min(_this4.RATIO_MAX, ry));\n _this4._apply();\n _this4.render();\n };\n if (previewImg && previewImg.complete && previewImg.naturalWidth) {\n apply(previewImg.naturalWidth, previewImg.naturalHeight);\n return;\n }\n\n // Fall back to a fresh probe Image if preview isn't loaded yet\n var probe = new Image();\n probe.crossOrigin = 'anonymous';\n if (chip) {\n chip.disabled = true;\n chip.classList.add('is-loading');\n }\n var restore = function restore() {\n if (chip) {\n chip.disabled = false;\n chip.classList.remove('is-loading');\n }\n };\n probe.onload = function () {\n apply(probe.naturalWidth, probe.naturalHeight);\n restore();\n };\n probe.onerror = restore;\n probe.src = this.src;\n }\n }, {\n key: \"_clamp\",\n value: function _clamp(role, v) {\n if (role === 'zoom') return Math.max(this.zoomDef.min, Math.min(this.zoomDef.max, v));\n return Math.max(0, Math.min(100, v));\n }\n }, {\n key: \"_syncSlider\",\n value: function _syncSlider(role) {\n var slider = this.domNode.querySelector(\".icrop-slider[data-role=\\\"\".concat(role, \"\\\"]\"));\n var numInput = this.domNode.querySelector(\".icrop-value-input[data-role=\\\"\".concat(role, \"-num\\\"]\"));\n if (slider) {\n slider.value = this.crop[role];\n var pct = role === 'zoom' ? (this.crop.zoom - this.zoomDef.min) / (this.zoomDef.max - this.zoomDef.min) * 100 : this.crop[role];\n slider.style.setProperty('--pct', pct + '%');\n }\n if (numInput) numInput.value = role === 'zoom' ? this.crop.zoom.toFixed(2) : this.crop[role];\n }\n }, {\n key: \"_updatePreview\",\n value: function _updatePreview() {\n var img = this.domNode.querySelector('.icrop-preview-img');\n var dot = this.domNode.querySelector('.icrop-focus-dot');\n var preview = this.domNode.querySelector('[data-role=\"preview\"]');\n if (!img) return;\n img.style.objectPosition = \"\".concat(this.crop.posX, \"% \").concat(this.crop.posY, \"%\");\n img.style.transform = \"scale(\".concat(this.crop.zoom, \")\");\n img.style.transformOrigin = \"\".concat(this.crop.posX, \"% \").concat(this.crop.posY, \"%\");\n if (dot) {\n dot.style.left = this.crop.posX + '%';\n dot.style.top = this.crop.posY + '%';\n }\n if (preview) {\n preview.style.aspectRatio = \"\".concat(this.crop.ratioX, \"/\").concat(this.crop.ratioY);\n }\n }\n }, {\n key: \"_updateRatioDisplay\",\n value: function _updateRatioDisplay() {\n var display = this.domNode.querySelector('.icrop-ratio-display');\n if (display) display.textContent = \"= \".concat(this.crop.ratioX, \":\").concat(this.crop.ratioY);\n }\n }, {\n key: \"_updateChipActive\",\n value: function _updateChipActive() {\n var matched = this._matchedPreset();\n this.domNode.querySelectorAll('.icrop-chip').forEach(function (chip) {\n if (chip.dataset.preset === 'original') {\n chip.classList.remove('is-active'); // never marked active (it's a one-shot action)\n return;\n }\n var isMatch = matched && parseInt(chip.dataset.rx, 10) === matched.x && parseInt(chip.dataset.ry, 10) === matched.y;\n chip.classList.toggle('is-active', !!isMatch);\n });\n }\n }, {\n key: \"_updateResetState\",\n value: function _updateResetState() {\n var btn = this.domNode.querySelector('[data-role=\"reset\"]');\n if (btn) btn.disabled = !this.isModified();\n }\n }, {\n key: \"_apply\",\n value: function _apply() {\n this.callback.setCrop(_objectSpread({}, this.crop));\n }\n\n /**\n * Phase 1.4 (SA invariant I4) — re-read external crop state and patch\n * DOM in place, without a full control re-render (NO-FLICKER rule I9).\n * Phase 1.8: now auto-triggered via addSyncListener on element.render().\n *\n * Handles every state-bearing DOM surface:\n * - Toggle checkbox (data-role=\"enabled\")\n * - Container `.is-enabled` class (data-role=\"container\")\n * - Body `hidden` attribute (data-role=\"body\")\n * - Ratio number inputs (data-role=\"ratioX\" / \"ratioY\")\n * - Ratio display text (.icrop-ratio-display)\n * - Sliders (zoom/posX/posY) + paired number inputs\n * - Slider `--pct` CSS variable\n * - Preview aspect-ratio + object-position + transform + focus-dot\n * - Preset chip active states + disabled state when crop off\n * - Reset button disabled state\n *\n * Does NOT call renderElementControls (NO-FLICKER, SA I9). Does NOT trigger\n * `callback.setCrop` — the caller already committed state to the element.\n *\n * Mutates `this.crop` IN PLACE via Object.assign (SA I13 — reference\n * stability; a replacement would break any sub-component holding the ref).\n */\n }, {\n key: \"syncFromExternal\",\n value: function syncFromExternal() {\n var _this5 = this;\n if (!this._sourceValueRef) return;\n if (this._destroyed) return; // disposer should have unsubscribed\n if (!this.domNode) return; // DOM gone — sidebar rebuilt or section destroyed\n var c = this._sourceValueRef.crop || {};\n\n // Copy external state into our local snapshot.\n var next = {\n enabled: !!c.enabled,\n ratioX: this._safeRatio(c.ratioX, 3),\n ratioY: this._safeRatio(c.ratioY, 2),\n zoom: typeof c.zoom === 'number' ? c.zoom : 1,\n posX: typeof c.posX === 'number' ? c.posX : 50,\n posY: typeof c.posY === 'number' ? c.posY : 50\n };\n // Early-out if nothing changed (prevents DOM churn when sync fires\n // but crop state was already identical — this happens every time\n // element.render() runs for any unrelated reason).\n var same = next.enabled === this.crop.enabled && next.ratioX === this.crop.ratioX && next.ratioY === this.crop.ratioY && next.zoom === this.crop.zoom && next.posX === this.crop.posX && next.posY === this.crop.posY;\n if (same) return;\n var enabledFlipped = next.enabled !== this.crop.enabled;\n\n // Phase 1.8 (SA I13) — in-place mutation preserves this.crop's object\n // identity in case sub-components (or future code) stash the ref.\n Object.assign(this.crop, next);\n\n // Patch DOM in place — avoid innerHTML rebuild.\n try {\n // Toggle checkbox\n var enabledEl = this.domNode.querySelector('[data-role=\"enabled\"]');\n if (enabledEl && 'checked' in enabledEl) enabledEl.checked = !!this.crop.enabled;\n\n // Container `is-enabled` class + body `hidden` attribute.\n // When enabled flips, the body's interactive elements (sliders,\n // chips, etc.) don't exist in the DOM (the template only renders\n // them inside the body div, which is `hidden` when disabled).\n // If enabled just flipped ON, we need a full render() because the\n // body child elements are absent — the subsequent patches would\n // silently no-op. When it flipped OFF we just hide the body, no\n // re-render needed.\n var container = this.domNode.querySelector('[data-role=\"container\"]');\n var body = this.domNode.querySelector('[data-role=\"body\"]');\n if (enabledFlipped && this.crop.enabled) {\n // Going OFF→ON — body contents don't exist yet. Only safe path\n // is a full re-render, which is fine here because:\n // (a) NO-FLICKER rule is about renderElementControls (full\n // panel rebuild), not control-internal render();\n // (b) flipping the enable toggle is a discrete user action,\n // not a keystroke-frequency operation.\n this.render();\n return;\n }\n if (container) container.classList.toggle('is-enabled', this.crop.enabled);\n if (body) {\n if (this.crop.enabled) body.removeAttribute('hidden');else body.setAttribute('hidden', '');\n }\n\n // If crop is now disabled, the rest of the body elements are\n // hidden and don't need further patching.\n if (!this.crop.enabled) {\n this._updateResetState();\n return;\n }\n\n // Ratio number inputs (template uses .icrop-ratio-input class +\n // data-role; be tolerant of either selector form for future renames).\n var rxEl = this.domNode.querySelector('.icrop-ratio-input[data-role=\"ratioX\"]');\n var ryEl = this.domNode.querySelector('.icrop-ratio-input[data-role=\"ratioY\"]');\n if (rxEl && 'value' in rxEl && document.activeElement !== rxEl) rxEl.value = String(this.crop.ratioX);\n if (ryEl && 'value' in ryEl && document.activeElement !== ryEl) ryEl.value = String(this.crop.ratioY);\n\n // Ratio display text \"= X:Y\"\n this._updateRatioDisplay();\n\n // Sliders + paired number inputs. Template uses .icrop-slider[data-role=\"<name>\"]\n // for range + .icrop-value-input[data-role=\"<name>-num\"] for the number.\n ['zoom', 'posX', 'posY'].forEach(function (role) {\n var slider = _this5.domNode.querySelector(\".icrop-slider[data-role=\\\"\".concat(role, \"\\\"]\"));\n var numInput = _this5.domNode.querySelector(\".icrop-value-input[data-role=\\\"\".concat(role, \"-num\\\"]\"));\n if (slider && 'value' in slider && document.activeElement !== slider) {\n slider.value = String(_this5.crop[role]);\n }\n if (numInput && 'value' in numInput && document.activeElement !== numInput) {\n numInput.value = role === 'zoom' ? _this5.crop[role].toFixed(2) : String(_this5.crop[role]);\n }\n // Filled-slider --pct variable re-sync.\n if (slider) {\n var val = role === 'zoom' ? (_this5.crop.zoom - _this5.zoomDef.min) / (_this5.zoomDef.max - _this5.zoomDef.min) * 100 : _this5.crop[role];\n slider.style.setProperty('--pct', val + '%');\n }\n });\n\n // Preset chip active states + disabled attr.\n this._updateChipActive();\n this.domNode.querySelectorAll('.icrop-chip').forEach(function (chip) {\n chip.disabled = !_this5.crop.enabled;\n });\n\n // Preview transform + aspect-ratio + focus dot.\n this._updatePreview();\n\n // Reset button enabled-state.\n this._updateResetState();\n } catch (err) {\n // eslint-disable-next-line no-console\n console.warn('[ImageCropControl] syncFromExternal: partial DOM patch failed:', err);\n }\n }\n\n /** Builder hook — fires after host injection + DOM mount. Register\n * the legacy back-compat slot for any third-party code reading\n * host._activeControls.imageCrop. New code uses the observer pattern\n * via value.subscribe (set up in the constructor). */\n }, {\n key: \"afterRender\",\n value: function afterRender() {\n if (this.host) {\n this.host._activeControls = this.host._activeControls || {};\n this.host._activeControls.imageCrop = this;\n }\n }\n\n /** Control teardown (SA I14). BaseControl runs stashed disposers (the\n * sync-listener removal). We additionally clear the legacy shim slot so\n * orphaned code can't read a ghost instance. */\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this.host && this.host._activeControls && this.host._activeControls.imageCrop === this) {\n this.host._activeControls.imageCrop = null;\n }\n _superPropGet(ImageCropControl, \"destroy\", this, 3)([]);\n }\n }]);\n}(_BaseControl_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageCropControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageCropControl.js?");
/***/ }),
/***/ "./src/includes/ImageEffectControl.js":
/*!********************************************!*\
!*** ./src/includes/ImageEffectControl.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseControl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseControl.js */ \"./src/includes/BaseControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar ImageEffectControl = /*#__PURE__*/function (_BaseControl) {\n /**\n * @param {string} label\n * @param {object} value — supports both legacy + capability-token form:\n * { src, current_effects } — legacy primitive form\n * { src, current_effects, subscribe, readState } — observer-aware form\n * `subscribe(fn) → disposer` — fires on every element.render\n * (Phase 1.8 SA I13 R3).\n * `readState() → freshEffects`— returns the current effect map\n * (e.g. () => element.effect).\n * Multiple instances of the SAME control (sidebar + popover) coexist;\n * both subscribe and stay in sync via syncFromExternal().\n */\n function ImageEffectControl(label, value, callback) {\n var _this;\n _classCallCheck(this, ImageEffectControl);\n _this = _callSuper(this, ImageEffectControl);\n _this.label = label;\n _this.value = value.src;\n _this.current_effects = value.current_effects || {};\n _this.callback = callback;\n _this._readState = typeof value.readState === 'function' ? value.readState : null;\n if (typeof value.subscribe === 'function') {\n // Disposer auto-runs in BaseControl.destroy(). Embedded\n // popover instances must call control.destroy() in their\n // beforeDestroy() so the listener Set stays bounded.\n _this.addDisposer(value.subscribe(function () {\n return _this.syncFromExternal();\n }));\n }\n\n // Effect definitions: { key: { min, max, step, default, unit } }\n _this.effectDefs = {\n grayscale: {\n min: 0,\n max: 100,\n step: 1,\n def: 0,\n unit: '%'\n },\n sepia: {\n min: 0,\n max: 100,\n step: 1,\n def: 0,\n unit: '%'\n },\n invert: {\n min: 0,\n max: 100,\n step: 1,\n def: 0,\n unit: '%'\n },\n blur: {\n min: 0,\n max: 10,\n step: 0.1,\n def: 0,\n unit: 'px'\n },\n brightness: {\n min: 0,\n max: 200,\n step: 1,\n def: 100,\n unit: '%'\n },\n contrast: {\n min: 0,\n max: 200,\n step: 1,\n def: 100,\n unit: '%'\n },\n saturate: {\n min: 0,\n max: 300,\n step: 1,\n def: 100,\n unit: '%'\n },\n hueRotate: {\n min: 0,\n max: 360,\n step: 1,\n def: 0,\n unit: '°'\n },\n opacity: {\n min: 0,\n max: 100,\n step: 1,\n def: 100,\n unit: '%'\n }\n };\n _this.effectLabels = {\n grayscale: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.grayscale'),\n sepia: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.sepia'),\n invert: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.invert'),\n blur: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.blur'),\n brightness: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.brightness'),\n contrast: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.contrast'),\n saturate: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.saturation'),\n hueRotate: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.hue_rotate'),\n opacity: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.opacity')\n };\n _this.domNode = document.createElement('div');\n _this.domNode.className = 'ImageEffectControl';\n _this.render();\n return _this;\n }\n _inherits(ImageEffectControl, _BaseControl);\n return _createClass(ImageEffectControl, [{\n key: \"getCurrentValues\",\n value: function getCurrentValues() {\n var vals = {};\n for (var _i = 0, _Object$entries = Object.entries(this.effectDefs); _i < _Object$entries.length; _i++) {\n var _this$current_effects;\n var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),\n key = _Object$entries$_i[0],\n def = _Object$entries$_i[1];\n vals[key] = (_this$current_effects = this.current_effects[key]) !== null && _this$current_effects !== void 0 ? _this$current_effects : def.def;\n }\n return vals;\n }\n }, {\n key: \"isDefault\",\n value: function isDefault(key, value) {\n return Number(value) === this.effectDefs[key].def;\n }\n }, {\n key: \"isAllDefault\",\n value: function isAllDefault(values) {\n var _this2 = this;\n return Object.entries(values).every(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n k = _ref2[0],\n v = _ref2[1];\n return _this2.isDefault(k, v);\n });\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this3 = this;\n var current = this.getCurrentValues();\n var allDefault = this.isAllDefault(current);\n var sliderRows = Object.entries(this.effectDefs).map(function (_ref3) {\n var _ref4 = _slicedToArray(_ref3, 2),\n key = _ref4[0],\n def = _ref4[1];\n var val = current[key];\n var modified = !_this3.isDefault(key, val);\n var pct = (val - def.min) / (def.max - def.min) * 100;\n return \"\\n <div class=\\\"iec-row\".concat(modified ? ' iec-row--modified' : '', \"\\\" data-effect=\\\"\").concat(key, \"\\\">\\n <label class=\\\"iec-row-label\\\">\").concat(_this3.effectLabels[key], \"</label>\\n <div class=\\\"iec-slider-wrap\\\">\\n <input type=\\\"range\\\" class=\\\"iec-slider\\\"\\n min=\\\"\").concat(def.min, \"\\\" max=\\\"\").concat(def.max, \"\\\" step=\\\"\").concat(def.step, \"\\\" value=\\\"\").concat(val, \"\\\"\\n data-effect=\\\"\").concat(key, \"\\\"\\n style=\\\"--pct: \").concat(pct, \"%\\\">\\n </div>\\n <div class=\\\"iec-value-wrap\\\">\\n <input type=\\\"number\\\" class=\\\"iec-value-input\\\"\\n min=\\\"\").concat(def.min, \"\\\" max=\\\"\").concat(def.max, \"\\\" step=\\\"\").concat(def.step, \"\\\" value=\\\"\").concat(val, \"\\\"\\n data-effect=\\\"\").concat(key, \"\\\">\\n <span class=\\\"iec-unit\\\">\").concat(def.unit, \"</span>\\n </div>\\n <button type=\\\"button\\\" class=\\\"iec-row-reset\\\" data-effect=\\\"\").concat(key, \"\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.reset'), \"\\\" aria-label=\\\"reset \").concat(_this3.effectLabels[key], \"\\\">\\n <svg width=\\\"10\\\" height=\\\"10\\\" viewBox=\\\"0 0 12 12\\\" fill=\\\"none\\\"><path d=\\\"M2.5 2.5L9.5 9.5M9.5 2.5L2.5 9.5\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/></svg>\\n </button>\\n </div>\");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"iec-container\\\">\\n <div class=\\\"iec-header\\\">\\n <label class=\\\"iec-title\\\">\".concat(this.label, \"</label>\\n <button type=\\\"button\\\" class=\\\"iec-reset-all\").concat(allDefault ? ' iec-hidden' : '', \"\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.reset'), \"</button>\\n </div>\\n\\n <div class=\\\"iec-preview-wrap\\\">\\n <div class=\\\"iec-preview\\\">\\n <img src=\\\"\").concat(this.value, \"\\\" style=\\\"filter: \").concat(this.generateFilterString(current), \";\\\">\\n </div>\\n </div>\\n\\n <div class=\\\"iec-sliders\\\">\\n \").concat(sliderRows, \"\\n </div>\\n </div>\");\n this.setupListeners();\n }\n }, {\n key: \"setupListeners\",\n value: function setupListeners() {\n var _this4 = this;\n // Slider input (live drag)\n this.domNode.querySelectorAll('.iec-slider').forEach(function (slider) {\n var debounce = null;\n slider.addEventListener('input', function (e) {\n var key = e.target.dataset.effect;\n var val = parseFloat(e.target.value);\n _this4.syncValue(key, val, 'slider');\n\n // Debounce callback for performance\n clearTimeout(debounce);\n debounce = setTimeout(function () {\n return _this4.applyEffects();\n }, 80);\n });\n });\n\n // Number input\n this.domNode.querySelectorAll('.iec-value-input').forEach(function (input) {\n var debounce = null;\n input.addEventListener('input', function (e) {\n var key = e.target.dataset.effect;\n var def = _this4.effectDefs[key];\n var val = parseFloat(e.target.value);\n if (isNaN(val)) return;\n val = Math.min(def.max, Math.max(def.min, val));\n _this4.syncValue(key, val, 'input');\n clearTimeout(debounce);\n debounce = setTimeout(function () {\n return _this4.applyEffects();\n }, 150);\n });\n\n // Commit clamped value on blur\n input.addEventListener('blur', function (e) {\n var key = e.target.dataset.effect;\n var def = _this4.effectDefs[key];\n var val = parseFloat(e.target.value);\n if (isNaN(val)) val = def.def;\n val = Math.min(def.max, Math.max(def.min, val));\n e.target.value = val;\n _this4.syncValue(key, val, 'input');\n _this4.applyEffects();\n });\n });\n\n // Per-row reset button\n this.domNode.querySelectorAll('.iec-row-reset').forEach(function (btn) {\n btn.addEventListener('click', function (e) {\n e.stopPropagation();\n var key = btn.dataset.effect;\n var def = _this4.effectDefs[key].def;\n _this4.syncValue(key, def, 'both');\n _this4.applyEffects();\n });\n });\n\n // Reset all button\n var resetAll = this.domNode.querySelector('.iec-reset-all');\n if (resetAll) {\n resetAll.addEventListener('click', function () {\n return _this4.resetAll();\n });\n }\n }\n }, {\n key: \"syncValue\",\n value: function syncValue(key, val, source) {\n var row = this.domNode.querySelector(\".iec-row[data-effect=\\\"\".concat(key, \"\\\"]\"));\n if (!row) return;\n var slider = row.querySelector('.iec-slider');\n var input = row.querySelector('.iec-value-input');\n var def = this.effectDefs[key];\n var modified = !this.isDefault(key, val);\n\n // Skip the originator (source) AND any element the user is currently\n // editing (SA I13 R4) — preserves in-flight typing / drag from other surfaces.\n if (source !== 'slider' && document.activeElement !== slider) slider.value = val;\n if (source !== 'input' && document.activeElement !== input) input.value = val;\n\n // Fill-track percentage — single source of truth, always applied\n // regardless of source, so external sync paints identical visual state.\n var pct = (val - def.min) / (def.max - def.min) * 100;\n slider.style.setProperty('--pct', pct + '%');\n\n // Toggle modified state (controls visibility of reset button via CSS)\n row.classList.toggle('iec-row--modified', modified);\n\n // Update current_effects\n this.current_effects[key] = val;\n\n // Update preview\n this.updatePreview();\n\n // Update reset-all visibility\n var allDefault = this.isAllDefault(this.getCurrentValues());\n var resetAllBtn = this.domNode.querySelector('.iec-reset-all');\n if (resetAllBtn) resetAllBtn.classList.toggle('iec-hidden', allDefault);\n }\n }, {\n key: \"updatePreview\",\n value: function updatePreview() {\n var previewImg = this.domNode.querySelector('.iec-preview img');\n if (!previewImg) return;\n var current = this.getCurrentValues();\n if (current.opacity <= 0) {\n previewImg.style.visibility = 'hidden';\n } else {\n previewImg.style.visibility = 'visible';\n previewImg.style.filter = this.generateFilterString(current);\n }\n }\n }, {\n key: \"generateFilterString\",\n value: function generateFilterString(effects) {\n return \"grayscale(\".concat(effects.grayscale, \"%) sepia(\").concat(effects.sepia, \"%) invert(\").concat(effects.invert, \"%) blur(\").concat(effects.blur, \"px) brightness(\").concat(effects.brightness, \"%) contrast(\").concat(effects.contrast, \"%) saturate(\").concat(effects.saturate, \"%) hue-rotate(\").concat(effects.hueRotate, \"deg) opacity(\").concat(effects.opacity, \"%)\");\n }\n }, {\n key: \"resetAll\",\n value: function resetAll() {\n for (var _i2 = 0, _Object$entries2 = Object.entries(this.effectDefs); _i2 < _Object$entries2.length; _i2++) {\n var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),\n key = _Object$entries2$_i[0],\n def = _Object$entries2$_i[1];\n this.syncValue(key, def.def, 'both');\n }\n this.applyEffects();\n }\n }, {\n key: \"applyEffects\",\n value: function applyEffects() {\n var effects = {};\n for (var _i3 = 0, _Object$keys = Object.keys(this.effectDefs); _i3 < _Object$keys.length; _i3++) {\n var _this$current_effects2;\n var key = _Object$keys[_i3];\n effects[key] = (_this$current_effects2 = this.current_effects[key]) !== null && _this$current_effects2 !== void 0 ? _this$current_effects2 : this.effectDefs[key].def;\n }\n this.callback.setEffects(effects);\n }\n\n /** Re-read effects from `readState()` (capability token) and delegate\n * each changed key to `syncValue()` — the single authoritative painter\n * for slider value, fill track (--pct), numeric input, modified-row\n * class, and reset-all visibility. `syncValue()` is focus-aware so\n * in-flight typing / drag on this surface is preserved (SA I13 R4).\n * Listener idempotence (SA I13 R7) — we early-out cheaply per-key\n * when the value is unchanged. */\n }, {\n key: \"syncFromExternal\",\n value: function syncFromExternal() {\n if (!this._readState) return;\n if (this._destroyed) return;\n if (!this.domNode) return;\n var next = this._readState() || {};\n for (var _i4 = 0, _Object$keys2 = Object.keys(this.effectDefs); _i4 < _Object$keys2.length; _i4++) {\n var _this$current_effects3;\n var key = _Object$keys2[_i4];\n var newVal = next[key] !== undefined && next[key] !== null ? Number(next[key]) : this.effectDefs[key].def;\n var curVal = (_this$current_effects3 = this.current_effects[key]) !== null && _this$current_effects3 !== void 0 ? _this$current_effects3 : this.effectDefs[key].def;\n if (newVal !== Number(curVal)) {\n this.syncValue(key, newVal, 'external');\n }\n }\n }\n }]);\n}(_BaseControl_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageEffectControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageEffectControl.js?");
/***/ }),
/***/ "./src/includes/ImageElement.js":
/*!**************************************!*\
!*** ./src/includes/ImageElement.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _DimensionControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./DimensionControl.js */ \"./src/includes/DimensionControl.js\");\n/* harmony import */ var _ImageControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ImageControl.js */ \"./src/includes/ImageControl.js\");\n/* harmony import */ var _ImageEffectControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ImageEffectControl.js */ \"./src/includes/ImageEffectControl.js\");\n/* harmony import */ var _ImageCropControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ImageCropControl.js */ \"./src/includes/ImageCropControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./LinkConfigControl.js */ \"./src/includes/LinkConfigControl.js\");\n/* harmony import */ var _SectionGroupControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./SectionGroupControl.js */ \"./src/includes/SectionGroupControl.js\");\n/* harmony import */ var _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./InfoBannerControl.js */ \"./src/includes/InfoBannerControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _overlays_ImageActionsOverlay_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./overlays/ImageActionsOverlay.js */ \"./src/includes/overlays/ImageActionsOverlay.js\");\n/* harmony import */ var _overlays_ImageCropInlineOverlay_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./overlays/ImageCropInlineOverlay.js */ \"./src/includes/overlays/ImageCropInlineOverlay.js\");\n/* harmony import */ var _overlays_ImageCropPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./overlays/ImageCropPopoverOverlay.js */ \"./src/includes/overlays/ImageCropPopoverOverlay.js\");\n/* harmony import */ var _overlays_ImageResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./overlays/ImageResizeCornerOverlay.js */ \"./src/includes/overlays/ImageResizeCornerOverlay.js\");\n/* harmony import */ var _overlays_ImageEdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./overlays/ImageEdgeResizerOverlay.js */ \"./src/includes/overlays/ImageEdgeResizerOverlay.js\");\n/* harmony import */ var _overlays_ImageResizeInlineOverlay_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./overlays/ImageResizeInlineOverlay.js */ \"./src/includes/overlays/ImageResizeInlineOverlay.js\");\n/* harmony import */ var _overlays_ImageResizePopoverOverlay_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./overlays/ImageResizePopoverOverlay.js */ \"./src/includes/overlays/ImageResizePopoverOverlay.js\");\n/* harmony import */ var _overlays_ImageEffectPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./overlays/ImageEffectPopoverOverlay.js */ \"./src/includes/overlays/ImageEffectPopoverOverlay.js\");\n/* harmony import */ var _overlays_LinkPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./overlays/LinkPopoverOverlay.js */ \"./src/includes/overlays/LinkPopoverOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar ImageElement = /*#__PURE__*/function (_BaseElement) {\n function ImageElement(template) {\n var _this;\n var src = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTY5IDUxNiI+CiAgPGRlZnM+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImJnIiB4MT0iMCIgeTE9IjAiIHgyPSIwIiB5Mj0iMSI+CiAgICAgIDxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2YwZWZlZCIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNlOGU3ZTQiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9Im0xIiB4MT0iLjUiIHkxPSIwIiB4Mj0iLjUiIHkyPSIxIj4KICAgICAgPHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZDVkNGQwIi8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2NkY2NjOCIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0ibTIiIHgxPSIuNSIgeTE9IjAiIHgyPSIuNSIgeTI9IjEiPgogICAgICA8c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNjOWM4YzQiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjYzBiZmJiIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogIDwvZGVmcz4KCiAgPCEtLSBCYWNrZ3JvdW5kIC0tPgogIDxyZWN0IHdpZHRoPSIxNTY5IiBoZWlnaHQ9IjUxNiIgZmlsbD0idXJsKCNiZykiLz4KCiAgPCEtLSBTdW4gLS0+CiAgPGNpcmNsZSBjeD0iNTA1IiBjeT0iMTU1IiByPSI1MiIgZmlsbD0iI2RkZGNkOCIvPgoKICA8IS0tIE1haW4gbW91bnRhaW4gKHJvdW5kZWQgcGVhaykgLS0+CiAgPHBhdGggZD0iTTQ0MCw0NDAgTDY4MCwxNzAgUTc0OCwxMDAgODE2LDE3MCBMMTA1Niw0NDAgWiIgZmlsbD0idXJsKCNtMSkiLz4KCiAgPCEtLSBTbm93IGNhcCBhY2NlbnQgLS0+CiAgPHBhdGggZD0iTTcwMCwxOTAgUTc0OCwxMjAgNzk2LDE5MCBaIiBmaWxsPSIjZTVlNGUwIi8+CgogIDwhLS0gU2Vjb25kYXJ5IG1vdW50YWluIChyb3VuZGVkIHBlYWssIG92ZXJsYXBwaW5nIGZyb250KSAtLT4KICA8cGF0aCBkPSJNNzgwLDQ0MCBMOTUwLDI0MCBRMTAxMCwxODUgMTA3MCwyNDAgTDEyNDAsNDQwIFoiIGZpbGw9InVybCgjbTIpIi8+Cjwvc3ZnPgo=\";\n var alt = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : \"\";\n var url = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : \"\";\n var target = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : \"\";\n _classCallCheck(this, ImageElement);\n _this = _callSuper(this, ImageElement);\n _this.src = src;\n _this.alt = alt;\n _this.url = url || '';\n _this.target = target || '';\n // Full-link semantics (parity with ButtonElement). LinkConfigControl\n // edits all five — url + target + rel + title + download — and\n // applyLinkAttrs() patches them on the rendered <a>. Default empty,\n // so existing image data without these keys renders identically to\n // before this upgrade.\n _this.rel = '';\n _this.title = '';\n _this.download = '';\n _this.template = template;\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['src'];\n\n // Formatter - similar to PElement but with image-specific properties\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"]({\n // spacing\n padding_top: null,\n padding_right: null,\n padding_bottom: null,\n padding_left: null,\n // image-specific sizing — stored as unit-qualified strings\n // (\"300px\" | \"50%\" | \"1.5em\" | \"auto\") via DimensionControl.\n // Legacy numeric values (e.g. 200) are treated as px for backward compat.\n width: null,\n height: null,\n max_width: null,\n max_height: null,\n min_width: null,\n min_height: null,\n align: \"center\",\n // left, center, right\n\n // border\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_width: null,\n border_left_style: null,\n border_left_color: null,\n border_radius: 0,\n // box shadow\n box_shadow: null\n });\n _this.effect = {\n grayscale: null,\n sepia: null,\n invert: null,\n blur: null,\n brightness: null,\n contrast: null,\n saturate: null,\n hueRotate: null,\n opacity: null\n };\n\n // CSS-based crop / focus / zoom (no actual image bytes are altered)\n // ratioX:ratioY define the aspect ratio of the crop frame as INTEGERS.\n // Frame width is responsive (100% of parent); height auto via CSS aspect-ratio.\n // Email best practice — pixel-locked crop sizes break on mobile.\n _this.crop = {\n enabled: false,\n ratioX: 3,\n // aspect ratio numerator (positive integer)\n ratioY: 2,\n // aspect ratio denominator (positive integer)\n zoom: 1,\n // 1 .. 3\n posX: 50,\n // 0..100 (object-position X%)\n posY: 50 // 0..100 (object-position Y%)\n };\n\n // Per-element listener name counter — multiple instances of the\n // same Control class can subscribe to element state without\n // overwriting each other (BaseElement._syncListeners is a Map).\n _this._listenerSeq = 0;\n\n // Aspect-lock state for width/height coupling in Resize popover +\n // Inline overlay. In-memory only (NOT serialized) so opening /\n // closing the popover preserves the user's choice within the\n // session while the saved template stays free of UI-preference\n // fields. Defaults to true (matches corner-handle default +\n // Figma/Canva \"lock engaged by default\" convention). Surfaces\n // that opt in via `buildDimensionControl(..., { coupleAspect })`\n // honor this flag; corners and edges do NOT (they have fixed\n // semantics — corners aspect-locked, edges single-axis — per\n // docs/core/OVERLAY.md §7.2). Mutation notifies sync listeners so any\n // concurrent surface re-renders its toggle state.\n _this._aspectLocked = true;\n return _this;\n }\n\n /** Mutate the aspect-lock flag + notify listeners so any mounted\n * resize overlay re-reads and updates its toggle chrome.\n *\n * On OFF→ON transition, flipping the toggle doubles as \"undo any\n * prior distortion\" — if the user has dragged an edge (or typed\n * mismatched width/height in the popover with lock off), the image\n * is sitting at a manual aspect. Flipping lock ON is the natural\n * cue to restore the image's intrinsic aspect, so we hand the\n * second axis back to the browser by setting `height: auto`\n * (preserving width — responsive convention, matches the native\n * `<img>` aspect fallback). Skipped when either axis is already\n * `auto` / unset (intrinsic aspect already in play — forcing\n * `height: auto` would be a no-op). */\n _inherits(ImageElement, _BaseElement);\n return _createClass(ImageElement, [{\n key: \"setAspectLocked\",\n value: function setAspectLocked(v) {\n var next = !!v;\n if (this._aspectLocked === next) return;\n this._aspectLocked = next;\n if (next) this._restoreIntrinsicAspectIfDistorted();\n this.notifySyncListeners();\n }\n\n /** Restore intrinsic aspect by demoting `height` to `auto`, so the\n * browser re-derives height from width using the image's natural\n * ratio. Called ONLY on OFF→ON transition; the popover input\n * coupling path is separate (`_writeCoupledDimensions`) and handles\n * the \"edit a number after lock is on\" scenario. */\n }, {\n key: \"_restoreIntrinsicAspectIfDistorted\",\n value: function _restoreIntrinsicAspectIfDistorted() {\n var w = this.formatter.getFormat('width');\n var h = this.formatter.getFormat('height');\n var widthIntrinsic = this._isAutoOrEmpty(w);\n var heightIntrinsic = this._isAutoOrEmpty(h);\n if (widthIntrinsic || heightIntrinsic) return;\n this.formatter.setFormat('height', 'auto');\n this.render();\n }\n }, {\n key: \"_isAutoOrEmpty\",\n value: function _isAutoOrEmpty(v) {\n if (v == null) return true;\n var s = String(v).trim().toLowerCase();\n return s === '' || s === 'auto';\n }\n }, {\n key: \"getName\",\n value: function getName() {\n return \"Image\";\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c); ImageElement has no `text` field\n this.domNode.innerHTML = this.renderTemplate({\n src: this.transferMediaAbsUrl(this.src),\n alt: this.alt,\n url: this.url,\n target: this.target,\n rel: this.rel,\n title: this.title,\n download: this.download,\n effect: this.effect,\n crop: this.crop\n });\n\n // Themes only render <a href + target>. Any rel/title/download\n // stored on the element is patched in-place after render so\n // existing themes light up the new semantics without edits.\n this._applyExtendedLinkAttrs();\n\n // W0.2a: notifySyncListeners() now auto-fires from BaseElement.render()\n // lifecycle. Phase 1.8 (SA I13) sync listeners (e.g. ImageCropControl)\n // still fire on every render — re-entrancy guard intact.\n }\n\n /**\n * Patch rel/title/download on the existing <a> wrapper. Called at end of\n * render() (themes only wire href+target); and as a fast path from\n * applyLinkAttrs() when no structure change is needed. No-op when the\n * theme didn't wrap the image in <a> (url was empty at render time).\n */\n }, {\n key: \"_applyExtendedLinkAttrs\",\n value: function _applyExtendedLinkAttrs() {\n if (!this.domNode) return;\n var a = this.domNode.querySelector('a');\n if (!a) return;\n if (this.rel) a.setAttribute('rel', this.rel);else a.removeAttribute('rel');\n if (this.title) a.setAttribute('title', this.title);else a.removeAttribute('title');\n if (this.download) a.setAttribute('download', this.download);else a.removeAttribute('download');\n }\n\n /**\n * Link-attrs hot path — parity with ButtonElement.applyLinkAttrs.\n * Structure-preserving href/target/rel/title/download patch when the\n * <a> already exists (or already doesn't); falls back to a full render\n * when the url toggles between empty and set (because the theme\n * conditionally wraps <img> in <a> based on url — structure change).\n *\n * Fires `notifySyncListeners()` at the end so both live Link controls\n * (sidebar + popover) re-read element state.\n */\n }, {\n key: \"applyLinkAttrs\",\n value: function applyLinkAttrs() {\n if (!this.domNode) {\n this.render();\n return;\n }\n var a = this.domNode.querySelector('a');\n var hasAnchor = !!a;\n var wantsAnchor = !!(this.url && this.url !== '#');\n if (hasAnchor !== wantsAnchor) {\n // Structure change — template toggles <a> on url presence.\n this.render();\n return;\n }\n if (!hasAnchor) {\n // No <a> and no url: nothing to patch; still notify so controls\n // can reconcile other shared state.\n this.notifySyncListeners();\n return;\n }\n a.setAttribute('href', this.url || '#');\n if (this.target) a.setAttribute('target', this.target);else a.removeAttribute('target');\n if (this.rel) a.setAttribute('rel', this.rel);else a.removeAttribute('rel');\n if (this.title) a.setAttribute('title', this.title);else a.removeAttribute('title');\n if (this.download) a.setAttribute('download', this.download);else a.removeAttribute('download');\n this.notifySyncListeners();\n }\n\n // Resolve the node that overlay chrome (selected-outline rainbow,\n // 4 corner handles, 4 edge bars) should hug.\n //\n // Non-crop: the <img> itself — its rect is the visible image.\n // Crop on: the wrapper div marked `data-bjs-crop-frame` — overflow:\n // hidden + aspect-ratio define the visible frame. The\n // inner <img> is scaled via transform (zoom) and its own\n // rect is the un-cropped content, NOT what the user sees;\n // hugging it makes handles float outside the crop box.\n //\n // Stable template contract (`data-bjs-crop-frame`) — no DOM-tree-\n // walking from the <img>, survives template edits that reorder\n // wrappers. Falls back to <img> if the marker is absent (older\n // theme bundles) so behavior degrades gracefully.\n }, {\n key: \"_getHighlightTarget\",\n value: function _getHighlightTarget() {\n if (!this.domNode) return null;\n if (this.crop && this.crop.enabled) {\n var frame = this.domNode.querySelector('[data-bjs-crop-frame]');\n if (frame) return frame;\n }\n var img = this.domNode.querySelector('img');\n if (img) return img;\n var divs = this.domNode.querySelectorAll('div');\n if (divs && divs.length) return divs[divs.length - 1];\n return this.domNode;\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(ImageElement, \"getData\", this, 3)([])), {}, {\n src: this.src,\n alt: this.alt,\n url: this.url,\n target: this.target,\n rel: this.rel,\n title: this.title,\n download: this.download,\n effect: this.effect,\n crop: this.crop\n });\n }\n }, {\n key: \"isAutoFormat\",\n value: function isAutoFormat(key) {\n return this.formatter.getFormat(key) === \"auto\";\n }\n }, {\n key: \"setFormat\",\n value: function setFormat(key, value) {\n this.formatter.setFormat(key, value);\n // Use render() (not update()) so notifySyncListeners fires —\n // multi-surface DimensionControl instances depend on this to\n // re-sync after the sidebar / popup / popover mutates a format\n // (SA I13 R2). update() only rewrites innerHTML and skips the\n // listener fire, leaving other surfaces with stale state.\n this.render();\n }\n\n /**\n * Build a DimensionControl bound to a formatter key — observer-aware\n * factory. Multiple instances on the same key (sidebar + popup overlay\n * + future anchored popover) all subscribe to element state via the\n * `subscribe` capability token (SA I13 R3) and stay in sync via\n * `syncFromExternal()`. The popup must call `instance.destroy()` in\n * its teardown so the disposer fires and the listener Set stays\n * bounded across open/close cycles.\n *\n * @param {string} label Already-translated label\n * @param {string} key Formatter key ('width', 'max_width', ...)\n * @param {string[]} units Units to offer (defaults to full set for width/height,\n * limited to px/% for min/max bounds)\n */\n }, {\n key: \"buildDimensionControl\",\n value: function buildDimensionControl(label, key, units) {\n var _this2 = this;\n var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n // Unique listener name per instance — multiple instances of the\n // SAME control (sidebar + popup + popover) coexist; sharing a\n // name would let the LAST registration overwrite the others\n // (BaseElement.addSyncListener uses a Map keyed by name).\n var listenerId = \"DimensionControl:\".concat(key, \":\").concat(++this._listenerSeq);\n // `coupleAspect: true` opts this control into width↔height\n // coupling driven by `this._aspectLocked`. Resize popover + inline\n // overlay pass it; sidebar controls do NOT (sidebar stays\n // independent so existing single-field edits don't silently\n // mutate the companion axis — matches pre-fix behavior).\n var coupleAspect = !!options.coupleAspect;\n return new _DimensionControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](label, {\n initial: this.formatter.getFormat(key),\n subscribe: function subscribe(fn) {\n return _this2.addSyncListener(listenerId, fn);\n },\n readState: function readState() {\n return _this2.formatter.getFormat(key);\n }\n }, {\n units: units,\n onChange: function onChange(serialized) {\n if (coupleAspect && _this2._aspectLocked && (key === 'width' || key === 'height') && !_this2._inCoupleWrite) {\n _this2._inCoupleWrite = true;\n try {\n _this2._writeCoupledDimensions(key, serialized);\n } finally {\n _this2._inCoupleWrite = false;\n }\n return;\n }\n // Mutate format + render — fires notifySyncListeners\n // automatically (SA I13 R2). All other instances of\n // this DimensionControl re-sync via their disposer.\n _this2.setFormat(key, serialized);\n }\n });\n }\n\n /** Aspect ratio used for width↔height coupling. Priority:\n * 1. Crop ratio (user-chosen explicit aspect) when crop.enabled\n * 2. Natural image dims (stable, no drift from repeated edits)\n * 3. Rendered bounding rect (fallback if image not loaded)\n * 4. 1:1 safe default\n * Kept public-ish (underscore prefix) so corner/edge overlays or\n * future surfaces can reuse the same source of truth. */\n }, {\n key: \"_getAspectRatio\",\n value: function _getAspectRatio() {\n if (this.crop && this.crop.enabled) {\n var rx = this.crop.ratioX || 0;\n var ry = this.crop.ratioY || 0;\n if (rx > 0 && ry > 0) return rx / ry;\n }\n var img = this.domNode && this.domNode.querySelector('img');\n if (img && img.naturalWidth > 0 && img.naturalHeight > 0) {\n return img.naturalWidth / img.naturalHeight;\n }\n var target = typeof this._getHighlightTarget === 'function' ? this._getHighlightTarget() : null;\n if (target) {\n var r = target.getBoundingClientRect();\n if (r.height > 0) return r.width / r.height;\n }\n return 1;\n }\n\n /** Atomic write of width + height when aspect-lock coupling is\n * active. `editedKey` is the axis the user just edited; `serialized`\n * is its new DimensionControl-formatted string. The companion axis\n * is computed via `_getAspectRatio()` and written in `px` (matches\n * the established ImageResizeCornerOverlay convention), EXCEPT when\n * the companion was previously `auto` — leave it `auto` so the\n * browser's intrinsic aspect preservation keeps working (no reason\n * to force a concrete number if the markup was already responsive).\n *\n * Both formats are set on the formatter directly, then a single\n * render() fires so only ONE notifySyncListeners pass runs —\n * prevents double paint + avoids re-entrancy surprises. */\n }, {\n key: \"_writeCoupledDimensions\",\n value: function _writeCoupledDimensions(editedKey, serialized) {\n var companionKey = editedKey === 'width' ? 'height' : 'width';\n var ratio = this._getAspectRatio();\n var companionCurrent = this.formatter.getFormat(companionKey);\n var companionIsAuto = typeof companionCurrent === 'string' && companionCurrent.trim().toLowerCase() === 'auto';\n this.formatter.setFormat(editedKey, serialized);\n if (!companionIsAuto && ratio > 0) {\n var editedPx = this._resolveDimensionPx(editedKey, serialized);\n if (editedPx > 0 && Number.isFinite(editedPx)) {\n var companionPx = editedKey === 'width' ? editedPx / ratio : editedPx * ratio;\n var clamped = Math.max(16, Math.round(companionPx));\n this.formatter.setFormat(companionKey, clamped + 'px');\n }\n }\n\n // Single render → single notifySyncListeners → every embedded\n // DimensionControl on this element re-reads the new formats.\n this.render();\n }\n\n /** Resolve a DimensionControl-serialized value (e.g. \"300px\", \"50%\",\n * \"1.5em\", \"auto\") into an absolute pixel number for the given axis.\n * Used by aspect-lock coupling math. Returns 0 for unresolvable\n * inputs — callers should guard. */\n }, {\n key: \"_resolveDimensionPx\",\n value: function _resolveDimensionPx(key, serialized) {\n if (serialized == null) return 0;\n var str = String(serialized).trim().toLowerCase();\n if (str === '' || str === 'auto') return 0;\n var num = parseFloat(str);\n if (!Number.isFinite(num)) return 0;\n if (/px$/.test(str)) return num;\n if (/%$/.test(str)) {\n var parent = this.domNode && this.domNode.parentElement;\n if (!parent) return 0;\n var rect = parent.getBoundingClientRect();\n var base = key === 'width' ? rect.width : rect.height;\n return num / 100 * base;\n }\n if (/(em|rem)$/.test(str)) {\n var ref = this.domNode || document.body;\n var fs = parseFloat(getComputedStyle(ref).fontSize) || 16;\n return num * fs;\n }\n if (/vw$/.test(str)) return num / 100 * (window.innerWidth || 0);\n if (/vh$/.test(str)) return num / 100 * (window.innerHeight || 0);\n // Unknown unit — assume number alone means px (legacy data)\n return num;\n }\n\n /** Shared renderer for the \"Lock aspect ratio\" toggle row used by\n * ImageResizePopoverOverlay + ImageResizeInlineOverlay. Single source\n * of truth for DOM structure, aria attributes, and the element-state\n * sync contract:\n * - toggle reflects `this._aspectLocked` on every mount\n * - click flips `this._aspectLocked` via `setAspectLocked()` which\n * fires notifySyncListeners → any concurrent surface re-syncs\n * - the overlay subscribes so external mutations re-paint the\n * toggle chrome (e.g. sidebar adds a sibling toggle one day)\n * Returns `{ row, dispose }`. Callers MUST invoke `dispose()` in\n * beforeDestroy to keep the sync-listener Map bounded (SA I14).\n */\n }, {\n key: \"buildAspectLockRow\",\n value: function buildAspectLockRow() {\n var _this3 = this;\n var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var label = opts.label || 'Lock aspect ratio';\n var hint = opts.hint || '';\n var row = document.createElement('div');\n row.className = 'bjs-ovl-image-resize-aspect-row';\n var labelWrap = document.createElement('div');\n labelWrap.className = 'bjs-ovl-image-crop-toggle-label';\n var labelEl = document.createElement('span');\n labelEl.className = 'bjs-ovl-image-crop-toggle-text';\n labelEl.textContent = label;\n labelWrap.appendChild(labelEl);\n if (hint) {\n var hintEl = document.createElement('span');\n hintEl.className = 'bjs-ovl-image-crop-toggle-hint';\n hintEl.textContent = hint;\n labelWrap.appendChild(hintEl);\n }\n var toggle = document.createElement('button');\n toggle.type = 'button';\n toggle.className = 'bjs-ovl-image-crop-toggle';\n toggle.setAttribute('role', 'switch');\n toggle.setAttribute('aria-label', label);\n var paint = function paint() {\n var on = !!_this3._aspectLocked;\n toggle.setAttribute('aria-checked', on ? 'true' : 'false');\n toggle.classList.toggle('is-on', on);\n };\n toggle.addEventListener('click', function (e) {\n e.preventDefault();\n _this3.setAspectLocked(!_this3._aspectLocked);\n // setAspectLocked fires notifySyncListeners → paint() runs\n // via the disposer below; but also paint synchronously for\n // immediate UI feedback regardless of subscribe wiring.\n paint();\n });\n row.appendChild(labelWrap);\n row.appendChild(toggle);\n paint();\n var listenerId = \"AspectLockRow:\".concat(++this._listenerSeq);\n var dispose = this.addSyncListener(listenerId, paint);\n return {\n row: row,\n dispose: dispose\n };\n }\n\n /** Build an ImageEffectControl — filter sliders (grayscale, sepia,\n * blur, brightness, contrast, saturate, hue-rotate, opacity) +\n * preview. Observer-aware factory; multiple instances coexist.\n * Used by the sidebar AND by ImageEffectPopoverOverlay so the on-\n * canvas Effects popover renders the SAME UI as the sidebar (no\n * duplicate slider math). */\n }, {\n key: \"buildEffectControl\",\n value: function buildEffectControl(label) {\n var _this4 = this;\n var listenerId = \"ImageEffectControl:\".concat(++this._listenerSeq);\n return new _ImageEffectControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](label || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.effects'), {\n src: this.transferMediaAbsUrl(this.src),\n current_effects: {\n grayscale: this.effect.grayscale || 0,\n sepia: this.effect.sepia || 0,\n invert: this.effect.invert || 0,\n blur: this.effect.blur || 0,\n brightness: this.effect.brightness || 100,\n contrast: this.effect.contrast || 100,\n saturate: this.effect.saturate || 100,\n hueRotate: this.effect.hueRotate || 0,\n opacity: this.effect.opacity || 100\n },\n subscribe: function subscribe(fn) {\n return _this4.addSyncListener(listenerId, fn);\n },\n readState: function readState() {\n return {\n grayscale: _this4.effect.grayscale || 0,\n sepia: _this4.effect.sepia || 0,\n invert: _this4.effect.invert || 0,\n blur: _this4.effect.blur || 0,\n brightness: _this4.effect.brightness || 100,\n contrast: _this4.effect.contrast || 100,\n saturate: _this4.effect.saturate || 100,\n hueRotate: _this4.effect.hueRotate || 0,\n opacity: _this4.effect.opacity || 100\n };\n }\n }, {\n setEffects: function setEffects(effects) {\n // Mutate IN PLACE so any holder of `this.effect`\n // reference (sidebar + popover instances) keeps its\n // ref intact (SA I13 R1).\n Object.assign(_this4.effect, {\n grayscale: effects.grayscale || 0,\n sepia: effects.sepia || 0,\n invert: effects.invert || 0,\n blur: effects.blur || 0,\n brightness: effects.brightness || 100,\n contrast: effects.contrast || 100,\n saturate: effects.saturate || 100,\n hueRotate: effects.hueRotate || 0,\n opacity: effects.opacity || 100\n });\n _this4.render();\n }\n });\n }\n\n /** Build an ImageCropControl — the rich crop editor (preview + focus\n * dot + aspect chips + custom ratio + zoom + focus X/Y + reset).\n * Same observer-aware factory pattern as buildDimensionControl —\n * multiple instances stay in sync via the `subscribe` capability. */\n }, {\n key: \"buildCropControl\",\n value: function buildCropControl(label) {\n var _this5 = this;\n // Unique listener name per instance — see buildDimensionControl.\n var listenerId = \"ImageCropControl:\".concat(++this._listenerSeq);\n return new _ImageCropControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](label || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.title'), {\n src: this.transferMediaAbsUrl(this.src),\n crop: this.crop,\n subscribe: function subscribe(fn) {\n return _this5.addSyncListener(listenerId, fn);\n }\n }, {\n setCrop: function setCrop(cropData) {\n var rx = parseInt(cropData.ratioX, 10);\n var ry = parseInt(cropData.ratioY, 10);\n if (!_this5.crop) _this5.crop = {};\n Object.assign(_this5.crop, {\n enabled: !!cropData.enabled,\n ratioX: rx >= 1 ? rx : 3,\n ratioY: ry >= 1 ? ry : 2,\n zoom: typeof cropData.zoom === 'number' ? cropData.zoom : 1,\n posX: typeof cropData.posX === 'number' ? cropData.posX : 50,\n posY: typeof cropData.posY === 'number' ? cropData.posY : 50\n });\n _this5.render();\n }\n });\n }\n }, {\n key: \"update\",\n value: function update() {\n if (this.domNode) {\n this.domNode.innerHTML = this.renderTemplate({\n src: this.transferMediaAbsUrl(this.src),\n alt: this.alt,\n url: this.url,\n target: this.target,\n effect: this.effect,\n crop: this.crop\n });\n }\n }\n\n /**\n * Canvas overlays — Image (Phase 1.4 + 2026-04-19 expand):\n * - ImageActionsOverlay (select) — Upload / Replace / Resize / Crop / Link pill row\n * - ImageCropInlineOverlay (edit) — crop enable toggle + chip grid + Done/Cancel\n * - ImageResizeInlineOverlay (edit) — width / height / aspect-lock + advanced max/min\n * - ImageResizeCornerOverlay × 4 (select) — NW/NE/SE/SW aspect-locked diagonal resize\n * - ImageEdgeResizerOverlay × 4 (select) — top/right/bottom/left single-axis resize\n *\n * Trigger mix:\n * - 'select' — Actions + 4 corners + 4 edges all mount on selection.\n * - 'edit' (named 'crop' / 'resize') — the two inline popups mount when\n * the Actions overlay dispatches enterEditMode('crop' / 'resize').\n * They are mutually exclusive (enterEditMode replaces the active mode).\n *\n * See docs/core/OVERLAY.md §7.2.\n */\n }, {\n key: \"getOverlays\",\n value: function getOverlays() {\n var _this6 = this;\n // Anchor function for the popover variants — reads the rect the\n // ImageActionsOverlay stashed when the user clicked Crop/Resize\n // (`element._lastActionAnchorRect`). Always returns a rect; the\n // popover falls back to a viewport-centered position if rect is\n // missing.\n var anchorTo = function anchorTo() {\n return _this6._lastActionAnchorRect || null;\n };\n return [new _overlays_ImageActionsOverlay_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"](this),\n // Edit-mode popups + popovers — both surfaces registered;\n // ImageActionsOverlay's SURFACE_MODE map decides which one\n // mounts on action click. Mode filter (BaseElement.mountOverlays\n // edit-mode filter, SA I13) ensures only the matching one mounts.\n new _overlays_ImageCropInlineOverlay_js__WEBPACK_IMPORTED_MODULE_14__[\"default\"](this), new _overlays_ImageCropPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](this, {\n anchorTo: anchorTo,\n side: 'right',\n width: 360\n }), new _overlays_ImageResizeInlineOverlay_js__WEBPACK_IMPORTED_MODULE_18__[\"default\"](this), new _overlays_ImageResizePopoverOverlay_js__WEBPACK_IMPORTED_MODULE_19__[\"default\"](this, {\n anchorTo: anchorTo,\n side: 'right',\n width: 320\n }), new _overlays_ImageEffectPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_20__[\"default\"](this, {\n anchorTo: anchorTo,\n side: 'right',\n width: 360,\n maxHeight: 540\n }),\n // Link popover (trigger 'edit', mode 'link-popover') — replaces\n // the legacy BuilderjsPopup.prompt() flow. Anchors next to the\n // action-bar Link pill (shares _lastActionAnchorRect with\n // crop/resize/effects). Generic primitive — any element with a\n // `.url` field can mount the same overlay.\n new _overlays_LinkPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_21__[\"default\"](this, {\n anchorTo: anchorTo,\n side: 'right',\n width: 380\n }),\n // Canvas resize handles — always mounted on select.\n new _overlays_ImageResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](this, {\n corner: 'nw'\n }), new _overlays_ImageResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](this, {\n corner: 'ne'\n }), new _overlays_ImageResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](this, {\n corner: 'se'\n }), new _overlays_ImageResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](this, {\n corner: 'sw'\n }), new _overlays_ImageEdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"](this, {\n edge: 'top'\n }), new _overlays_ImageEdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"](this, {\n edge: 'right'\n }), new _overlays_ImageEdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"](this, {\n edge: 'bottom'\n }), new _overlays_ImageEdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"](this, {\n edge: 'left'\n })];\n }\n\n /**\n * LinkConfigControl factory — full-feature link editor (Type / URL /\n * Target / Title / Advanced rel + download). Same class used by\n * ButtonElement, so both canvas elements share the exact same link\n * UX on sidebar AND popover.\n *\n * Called by getControls() (sidebar) and LinkPopoverOverlay._embedded\n * (canvas popover). Each call returns a FRESH control wired to this\n * element via subscribe/readState (SA I13). Edits mutate all 5 link\n * fields + call `applyLinkAttrs()`, which fires `notifySyncListeners()`\n * — the OTHER live instance re-reads and patches itself in place.\n */\n }, {\n key: \"buildLinkControl\",\n value: function buildLinkControl() {\n var _this7 = this;\n return new _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link'), {\n url: this.url,\n target: this.target,\n rel: this.rel,\n title: this.title,\n download: this.download\n }, {\n setLink: function setLink(_ref) {\n var url = _ref.url,\n target = _ref.target,\n rel = _ref.rel,\n title = _ref.title,\n download = _ref.download;\n _this7.url = url || '';\n _this7.target = target || '';\n _this7.rel = rel || '';\n _this7.title = title || '';\n _this7.download = download || '';\n _this7.applyLinkAttrs();\n }\n }, {\n subscribe: function subscribe(fn) {\n return _this7.addSyncListener('LinkConfigControl:' + Math.random().toString(36).slice(2, 7), fn);\n },\n readState: function readState() {\n return {\n url: _this7.url,\n target: _this7.target,\n rel: _this7.rel,\n title: _this7.title,\n download: _this7.download\n };\n }\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this8 = this;\n return [new _ImageControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.url'), {\n src: this.transferMediaAbsUrl(this.src),\n alt: this.alt,\n // Phase 1.8 (SA I13) — narrow capability tokens.\n // `subscribe` — register for state-change notifications.\n // `readState` — read fresh primitives (src/alt are not\n // refs, so a getter is required; object state like crop\n // is read via value.crop directly since it's a live ref).\n subscribe: function subscribe(fn) {\n return _this8.addSyncListener('ImageControl', fn);\n },\n readState: function readState() {\n return {\n src: _this8.transferMediaAbsUrl(_this8.src),\n alt: _this8.alt\n };\n }\n }, {\n setImage: function setImage(newSrc) {\n _this8.src = newSrc;\n _this8.render();\n },\n setAlt: function setAlt(alt) {\n _this8.alt = alt;\n _this8.render();\n }\n }),\n // Link — dual-view (sidebar + popover) sync via subscribe/readState.\n // See buildLinkControl() for the factory.\n this.buildLinkControl(), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat(\"align\", \"\"), {\n setValue: function setValue(value) {\n _this8.setFormat(\"align\", value);\n }\n }),\n // Collapsible IMAGE SIZE group (BORDERS-style header). One shared\n // info banner inside, then six DimensionControls in a single row\n // each. Removing the legacy dark SectionLabelControl.\n new _SectionGroupControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"]({\n title: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.image_size'),\n description: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.image_size_desc'),\n children: [new _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dimension.banner')), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.width'), 'width', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto']), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.height'), 'height', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto']), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.max_width'), 'max_width', ['px', '%', 'em', 'rem', 'vw']), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.max_height'), 'max_height', ['px', '%', 'em', 'rem', 'vh']), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.min_width'), 'min_width', ['px', '%', 'em', 'rem', 'vw']), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.min_height'), 'min_height', ['px', '%', 'em', 'rem', 'vh'])]\n }),\n // Effects control — Phase 1.8 (SA I13) factory. Sidebar instance.\n // Multi-surface: ImageEffectPopoverOverlay instantiates the same\n // factory and embeds the resulting domNode; both subscribe and\n // stay in sync via syncFromExternal.\n this.buildEffectControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.effects')),\n // Crop control — Phase 1.8 (SA I13) factory. Sidebar instance.\n // Multi-surface: popup overlay instantiates the SAME factory\n // and embeds the resulting domNode; both instances subscribe\n // to element state and stay in sync via syncFromExternal.\n this.buildCropControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.title')), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.settings'), {\n border_top_style: this.formatter.getFormat(\"border_top_style\", \"\"),\n border_top_width: this.formatter.getFormat(\"border_top_width\", \"\"),\n border_top_color: this.formatter.getFormat(\"border_top_color\", \"\"),\n border_bottom_style: this.formatter.getFormat(\"border_bottom_style\", \"\"),\n border_bottom_width: this.formatter.getFormat(\"border_bottom_width\", \"\"),\n border_bottom_color: this.formatter.getFormat(\"border_bottom_color\", \"\"),\n border_left_style: this.formatter.getFormat(\"border_left_style\", \"\"),\n border_left_width: this.formatter.getFormat(\"border_left_width\", \"\"),\n border_left_color: this.formatter.getFormat(\"border_left_color\", \"\"),\n border_right_style: this.formatter.getFormat(\"border_right_style\", \"\"),\n border_right_width: this.formatter.getFormat(\"border_right_width\", \"\"),\n border_right_color: this.formatter.getFormat(\"border_right_color\", \"\")\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this8.setFormat(\"border_top_style\", border_top_style);\n _this8.setFormat(\"border_top_width\", border_top_width);\n _this8.setFormat(\"border_top_color\", border_top_color);\n _this8.setFormat(\"border_bottom_style\", border_bottom_style);\n _this8.setFormat(\"border_bottom_width\", border_bottom_width);\n _this8.setFormat(\"border_bottom_color\", border_bottom_color);\n _this8.setFormat(\"border_left_style\", border_left_style);\n _this8.setFormat(\"border_left_width\", border_left_width);\n _this8.setFormat(\"border_left_color\", border_left_color);\n _this8.setFormat(\"border_right_style\", border_right_style);\n _this8.setFormat(\"border_right_width\", border_right_width);\n _this8.setFormat(\"border_right_color\", border_right_color);\n\n // re-render\n _this8.render();\n }\n }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.radius'), this.formatter.getFormat(\"border_radius\", 0), {\n setRadius: function setRadius(v) {\n _this8.setFormat(\"border_radius\", v);\n _this8.render();\n }\n })];\n }\n /* SELECTED EFFECTS */\n }, {\n key: \"addSelectedHighlight\",\n value: function addSelectedHighlight() {\n var _this9 = this;\n // render selected outbound\n if (!this.selectedBox) {\n this.selectedBox = document.createElement(\"div\");\n this.selectedBox.classList.add(\"selected-box\");\n\n // Append it to the body\n document.body.appendChild(this.selectedBox);\n\n //\n this.matchingDomNode(this.selectedBox, 5);\n }\n\n // Render actions\n if (!this.actionsBox) {\n this.actionsBox = document.createElement(\"div\");\n this.actionsBox.classList.add(\"actions-box\");\n this.actionsBox.classList.add(\"d-flex\");\n this.actionsBox.classList.add(\"align-items-center\");\n // Opt out of canvas-clip — toolbar pill must escape canvas\n // top edge. See BaseElement.addSelectedHighlight + OVERLAY.md §24.\n this.actionsBox.classList.add(\"bjs-ovl-no-clip\");\n // Append it to the body\n document.body.appendChild(this.actionsBox);\n //\n this.matchingDomNode(this.actionsBox, 5, function () {\n if (!_this9.actionsBox) {\n return;\n }\n\n // PLAN_EFFECT W1.2 (final) — single unified pill.\n // See BaseElement.js for the full rationale.\n var domRect = _this9.domNode.getBoundingClientRect();\n var iframe = _this9.domNode.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe.getBoundingClientRect();\n var absoluteTop = iframeRect.top + domRect.top;\n var absoluteLeft = iframeRect.left + domRect.left;\n var toolbar = {\n width: 240,\n height: 36\n };\n var gap = 14;\n\n // -1 px inset — aligns pill left with the selected-box\n // outline's visible left edge (outline-offset: -1 px).\n var pos = _this9.host.toolbarPositioner.compute({\n elementRect: {\n top: absoluteTop,\n left: absoluteLeft - 1,\n width: domRect.width,\n height: domRect.height\n },\n toolbar: toolbar,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight\n },\n gap: gap,\n preferredSide: 'above'\n });\n _this9.actionsBox.dataset.side = pos.side;\n _this9.actionsBox.dataset.didFlip = String(pos.didFlip);\n _this9.actionsBox.dataset.didClamp = String(pos.didClamp);\n Object.assign(_this9.actionsBox.style, {\n position: \"fixed\",\n top: \"\".concat(pos.top, \"px\"),\n left: \"\".concat(pos.left, \"px\")\n });\n });\n\n // Label\n this.actionsBoxLabel = document.createElement(\"h5\");\n this.actionsBoxLabel.classList.add(\"ms-2\");\n this.actionsBoxLabel.classList.add(\"m-0\");\n this.actionsBoxLabel.classList.add(\"text-light\");\n this.actionsBoxLabel.innerHTML = '<span class=\"d-flex align-items-center\"><span class=\"material-symbols-rounded me-2\">apps</span>' + this.getName() + \"</span>\";\n this.actionsBox.appendChild(this.actionsBoxLabel);\n this.actionsBoxInner = document.createElement(\"div\");\n this.actionsBoxInner.classList.add(\"actions-box-inner\");\n this.actionsBoxInner.classList.add(\"btn-group\");\n this.actionsBoxInner.classList.add(\"border\");\n this.actionsBoxInner.classList.add(\"ms-auto\");\n this.actionsBoxInner.classList.add(\"me-2\");\n this.actionsBoxInner = document.createElement(\"div\");\n this.actionsBoxInner.classList.add(\"actions-box-inner\");\n this.actionsBoxInner.classList.add(\"btn-group\");\n // this.actionsBoxInner.classList.add('border');\n this.actionsBoxInner.classList.add(\"ms-auto\");\n // Append it to the body\n this.actionsBox.appendChild(this.actionsBoxInner);\n this.getActions().forEach(function (action) {\n var actionButton = document.createElement(\"button\");\n actionButton.setAttribute(\"class\", \"element-action-item btn btn-light p-1 d-flex align-items-center\");\n actionButton.setAttribute(\"data-tooltip\", action.label);\n actionButton.setAttribute(\"aria-label\", action.label);\n actionButton.innerHTML = \"\\n <span class=\\\"material-symbols-rounded fs-5\\\">\" + action.icon + \"</span>\\n \";\n _this9.actionsBoxInner.appendChild(actionButton);\n\n // events\n actionButton.addEventListener(\"click\", function () {\n action.run();\n });\n });\n\n // PLAN_EFFECT W1.4 — focus-dim toggle (shared BaseElement helper).\n this._appendFocusDimToggle(this.actionsBoxInner);\n }\n\n // Add rainbow highlight around the first <img> (or fallback target)\n if (!this.imageHighlightBox) {\n this.imageHighlightBox = document.createElement('div');\n this.imageHighlightBox.classList.add('image-highlight-box');\n document.body.appendChild(this.imageHighlightBox);\n this.matchingDomNode(this.imageHighlightBox, 0, function () {\n if (!_this9.imageHighlightBox) return;\n var target = _this9._getHighlightTarget();\n if (!target) return;\n var domRect = target.getBoundingClientRect();\n var iframe = target.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe.getBoundingClientRect();\n var absoluteTop = iframeRect.top + domRect.top;\n var absoluteLeft = iframeRect.left + domRect.left;\n Object.assign(_this9.imageHighlightBox.style, {\n position: 'fixed',\n top: \"\".concat(absoluteTop, \"px\"),\n left: \"\".concat(absoluteLeft, \"px\"),\n width: \"\".concat(domRect.width, \"px\"),\n height: \"\".concat(domRect.height, \"px\"),\n borderRadius: getComputedStyle(target).borderRadius || '6px'\n });\n });\n\n // Add mouseenter/mouseleave to target for hover effect\n var highlightBox = this.imageHighlightBox;\n var imgTarget = this._getHighlightTarget();\n if (imgTarget) {\n // Remove ous listeners if any\n if (imgTarget._rainbowHoverHandler) {\n imgTarget.removeEventListener('mouseenter', imgTarget._rainbowHoverHandler.enter);\n imgTarget.removeEventListener('mouseleave', imgTarget._rainbowHoverHandler.leave);\n }\n // Add new listeners\n var enter = function enter() {\n return highlightBox.classList.add('hover');\n };\n var leave = function leave() {\n return highlightBox.classList.remove('hover');\n };\n imgTarget.addEventListener('mouseenter', enter);\n imgTarget.addEventListener('mouseleave', leave);\n imgTarget._rainbowHoverHandler = {\n enter: enter,\n leave: leave\n };\n }\n }\n }\n }, {\n key: \"removeSelectedHighlight\",\n value: function removeSelectedHighlight() {\n // remove selected outbound\n if (this.selectedBox) {\n this.selectedBox.remove();\n }\n this.selectedBox = null;\n\n // remove selected actions\n if (this.actionsBox) {\n this.actionsBox.remove();\n }\n this.actionsBox = null;\n\n // remove image highlight\n if (this.imageHighlightBox) {\n this.imageHighlightBox.remove();\n }\n this.imageHighlightBox = null;\n\n // Remove hover listeners from image\n var imgTarget = this._getHighlightTarget();\n if (imgTarget && imgTarget._rainbowHoverHandler) {\n imgTarget.removeEventListener('mouseenter', imgTarget._rainbowHoverHandler.enter);\n imgTarget.removeEventListener('mouseleave', imgTarget._rainbowHoverHandler.leave);\n imgTarget._rainbowHoverHandler = null;\n }\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var _data$alt, _data$url, _data$target, _data$rel, _data$title, _data$download;\n var e = new ImageElement(data.template, data.src, (_data$alt = data.alt) !== null && _data$alt !== void 0 ? _data$alt : \"\", (_data$url = data.url) !== null && _data$url !== void 0 ? _data$url : \"\", (_data$target = data.target) !== null && _data$target !== void 0 ? _data$target : \"\");\n e.rel = (_data$rel = data.rel) !== null && _data$rel !== void 0 ? _data$rel : '';\n e.title = (_data$title = data.title) !== null && _data$title !== void 0 ? _data$title : '';\n e.download = (_data$download = data.download) !== null && _data$download !== void 0 ? _data$download : '';\n\n // Handle formats (W0.2c — via BaseElement.parseFormats helper)\n this.parseFormats(e, data);\n if (data.effect) {\n var _data$effect$grayscal, _data$effect$sepia, _data$effect$invert, _data$effect$blur, _data$effect$brightne, _data$effect$contrast, _data$effect$saturate, _data$effect$hueRotat, _data$effect$opacity;\n e.effect = {\n grayscale: (_data$effect$grayscal = data.effect.grayscale) !== null && _data$effect$grayscal !== void 0 ? _data$effect$grayscal : null,\n sepia: (_data$effect$sepia = data.effect.sepia) !== null && _data$effect$sepia !== void 0 ? _data$effect$sepia : null,\n invert: (_data$effect$invert = data.effect.invert) !== null && _data$effect$invert !== void 0 ? _data$effect$invert : null,\n blur: (_data$effect$blur = data.effect.blur) !== null && _data$effect$blur !== void 0 ? _data$effect$blur : null,\n brightness: (_data$effect$brightne = data.effect.brightness) !== null && _data$effect$brightne !== void 0 ? _data$effect$brightne : null,\n contrast: (_data$effect$contrast = data.effect.contrast) !== null && _data$effect$contrast !== void 0 ? _data$effect$contrast : null,\n saturate: (_data$effect$saturate = data.effect.saturate) !== null && _data$effect$saturate !== void 0 ? _data$effect$saturate : null,\n hueRotate: (_data$effect$hueRotat = data.effect.hueRotate) !== null && _data$effect$hueRotat !== void 0 ? _data$effect$hueRotat : null,\n opacity: (_data$effect$opacity = data.effect.opacity) !== null && _data$effect$opacity !== void 0 ? _data$effect$opacity : null\n };\n }\n if (data.crop) {\n // Migration: convert legacy `aspectRatio` string ('16:9', 'free', ...)\n // into ratioX/ratioY integers. Old data in the wild predates the ratio model.\n var rx = typeof data.crop.ratioX === 'number' ? data.crop.ratioX : null;\n var ry = typeof data.crop.ratioY === 'number' ? data.crop.ratioY : null;\n if ((rx === null || ry === null) && typeof data.crop.aspectRatio === 'string') {\n var m = data.crop.aspectRatio.match(/^(\\d+):(\\d+)$/);\n if (m) {\n rx = parseInt(m[1], 10);\n ry = parseInt(m[2], 10);\n }\n }\n // Final defaults if still missing (e.g. legacy 'free' or empty)\n if (!rx || rx < 1) rx = 3;\n if (!ry || ry < 1) ry = 2;\n e.crop = {\n enabled: !!data.crop.enabled,\n ratioX: rx,\n ratioY: ry,\n zoom: typeof data.crop.zoom === 'number' ? data.crop.zoom : 1,\n posX: typeof data.crop.posX === 'number' ? data.crop.posX : 50,\n posY: typeof data.crop.posY === 'number' ? data.crop.posY : 50\n };\n }\n return e;\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageElement.js?");
/***/ }),
/***/ "./src/includes/ImageTextBottomWidget.js":
/*!***********************************************!*\
!*** ./src/includes/ImageTextBottomWidget.js ***!
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ImageTextBottomWidget = /*#__PURE__*/function (_BaseWidget) {\n function ImageTextBottomWidget() {\n var _this;\n _classCallCheck(this, ImageTextBottomWidget);\n _this = _callSuper(this, ImageTextBottomWidget); // Call the parent class constructor\n\n //\n var img = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 270.23 84.36'%3E%3Crect width='270.23' height='84.36' fill='%23f6f6f4'/%3E%3Cpath d='M123.15,57.18c-.86,0-1.58-.29-2.16-.87s-.87-1.3-.87-2.16v-23.94c0-.86.29-1.58.87-2.16s1.3-.87,2.16-.87h12.19c.27,0,.49.09.67.27s.27.4.27.67-.09.49-.27.67-.4.27-.67.27h-12.19c-.34,0-.61.11-.83.32-.22.22-.32.49-.32.83v23.94c0,.34.11.61.32.83.22.22.49.32.83.32h23.94c.34,0,.61-.11.83-.32.22-.22.32-.49.32-.83v-12.19c0-.27.09-.49.27-.67s.4-.27.67-.27.49.09.67.27.27.4.27.67v12.19c0,.86-.29,1.58-.87,2.16s-1.3.87-2.16.87h-23.94ZM125.31,50.4h19.62l-6.06-8.08-5.62,7.1-3.75-4.51-4.18,5.48ZM144.49,32.81h-2.81c-.27,0-.49-.09-.67-.27s-.27-.4-.27-.67.09-.49.27-.67.4-.27.67-.27h2.81v-2.81c0-.27.09-.49.27-.67s.4-.27.67-.27.49.09.67.27.27.4.27.67v2.81h2.81c.27,0,.49.09.67.27s.27.4.27.67-.09.49-.27.67-.4.27-.67.27h-2.81v2.81c0,.27-.09.49-.27.67s-.4.27-.67.27-.49-.09-.67-.27-.27-.4-.27-.67v-2.81Z' fill='%23afafae'/%3E%3C/svg%3E\");\n img.formatter.parseFormats({\n \"width\": \"100%\",\n \"padding_top\": 17\n });\n var h2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n h2.formatter.parseFormats({\n \"padding_bottom\": 12\n });\n var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n p.formatter.parseFormats({\n \"padding_bottom\": 17\n });\n var button = new ButtonElement('Button', 'Learn More');\n button.formatter.parseFormats({\n \"align\": \"left\",\n \"font_size\": 13,\n \"text_color\": \"#FFFFFF\",\n \"text_align\": \"center\",\n \"background_color\": \"#000000\",\n \"padding_top\": 8,\n \"padding_right\": 16,\n \"padding_bottom\": 8,\n \"padding_left\": 16,\n \"border_top_width\": 0,\n \"border_right_width\": 0,\n \"border_bottom_width\": 0,\n \"border_left_width\": 0,\n \"border_radius\": 0\n });\n\n //\n _this.block.appendElements([h2, p, button, img]);\n return _this;\n }\n _inherits(ImageTextBottomWidget, _BaseWidget);\n return _createClass(ImageTextBottomWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image_text_bottom');\n }\n }, {\n key: \"getImageUrl\",\n value: function getImageUrl() {\n return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 110'%3E%0A %3Crect width='180' height='110' fill='%23F7F7F7'/%3E%0A %3Crect x='14' y='14' width='72' height='7' rx='3.5' fill='%23C0C0C0'/%3E%0A %3Crect x='14' y='28' width='140' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='14' y='40' width='44' height='10' rx='3' fill='%23404040'/%3E%0A %3Crect x='14' y='58' width='152' height='46' rx='5' fill='%23EEEEEE'/%3E%0A %3Ccircle cx='46' cy='74' r='7' fill='%23D8D8D8'/%3E%0A %3Cpolygon points='60,94 84,70 108,94' fill='%23D0D0D0'/%3E%0A %3Cpolygon points='96,94 114,78 132,94' fill='%23DCDCDC'/%3E%0A%3C/svg%3E\";\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'image';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageTextBottomWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageTextBottomWidget.js?");
/***/ }),
/***/ "./src/includes/ImageTextDoubleWidget.js":
/*!***********************************************!*\
!*** ./src/includes/ImageTextDoubleWidget.js ***!
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ImageTextDoubleWidget = /*#__PURE__*/function (_BaseWidget) {\n function ImageTextDoubleWidget() {\n var _this;\n _classCallCheck(this, ImageTextDoubleWidget);\n _this = _callSuper(this, ImageTextDoubleWidget); // Call the parent class constructor\n\n //\n var grid = new GridElement('Grid');\n grid.cell_gap = 20;\n var cell1 = new CellElement('Cell');\n cell1.formatter.setFormat('width', 50);\n var cell2 = new CellElement('Cell');\n cell2.formatter.setFormat('width', 50);\n grid.appendCells([cell1, cell2]);\n _this.block.appendElements([grid]);\n\n //\n var img = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 134.73 71.64'%3E%3Crect width='134.73' height='71.64' fill='%23f6f6f4'/%3E%3Cpath d='M57.79,47.82c-.69,0-1.27-.23-1.73-.69s-.69-1.04-.69-1.73v-19.15c0-.69.23-1.27.69-1.73s1.04-.69,1.73-.69h9.75c.21,0,.39.07.53.22s.22.32.22.54-.07.39-.22.53-.32.21-.53.21h-9.75c-.27,0-.49.09-.66.26-.17.17-.26.39-.26.66v19.15c0,.27.09.49.26.66.17.17.39.26.66.26h19.15c.27,0,.49-.09.66-.26.17-.17.26-.39.26-.66v-9.75c0-.21.07-.39.22-.53s.32-.22.54-.22.39.07.53.22.21.32.21.53v9.75c0,.69-.23,1.27-.69,1.73s-1.04.69-1.73.69h-19.15ZM59.52,42.4h15.69l-4.85-6.46-4.5,5.68-3-3.61-3.35,4.38ZM74.87,28.32h-2.25c-.21,0-.39-.07-.53-.22s-.22-.32-.22-.54.07-.39.22-.53.32-.21.53-.21h2.25v-2.25c0-.21.07-.39.22-.53s.32-.22.54-.22.39.07.53.22.21.32.21.53v2.25h2.25c.21,0,.39.07.53.22s.22.32.22.54-.07.39-.22.53-.32.21-.53.21h-2.25v2.25c0,.21-.07.39-.22.53s-.32.22-.54.22-.39-.07-.53-.22-.21-.32-.21-.53v-2.25Z' fill='%23afafae'/%3E%3C/svg%3E\");\n img.formatter.parseFormats({\n \"width\": \"100%\"\n });\n var h2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n h2.formatter.parseFormats({\n \"padding_bottom\": 12,\n \"padding_top\": 12\n });\n var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n p.formatter.parseFormats({\n \"padding_bottom\": 17\n });\n var button = new ButtonElement('Button', 'Learn More');\n button.formatter.parseFormats({\n \"align\": \"left\",\n \"font_size\": 13,\n \"text_color\": \"#FFFFFF\",\n \"text_align\": \"center\",\n \"background_color\": \"#000000\",\n \"padding_top\": 8,\n \"padding_right\": 16,\n \"padding_bottom\": 8,\n \"padding_left\": 16,\n \"border_top_width\": 0,\n \"border_right_width\": 0,\n \"border_bottom_width\": 0,\n \"border_left_width\": 0,\n \"border_radius\": 0\n });\n\n //\n var img_2 = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 134.73 71.64'%3E%3Crect width='134.73' height='71.64' fill='%23f6f6f4'/%3E%3Cpath d='M57.79,47.82c-.69,0-1.27-.23-1.73-.69s-.69-1.04-.69-1.73v-19.15c0-.69.23-1.27.69-1.73s1.04-.69,1.73-.69h9.75c.21,0,.39.07.53.22s.22.32.22.54-.07.39-.22.53-.32.21-.53.21h-9.75c-.27,0-.49.09-.66.26-.17.17-.26.39-.26.66v19.15c0,.27.09.49.26.66.17.17.39.26.66.26h19.15c.27,0,.49-.09.66-.26.17-.17.26-.39.26-.66v-9.75c0-.21.07-.39.22-.53s.32-.22.54-.22.39.07.53.22.21.32.21.53v9.75c0,.69-.23,1.27-.69,1.73s-1.04.69-1.73.69h-19.15ZM59.52,42.4h15.69l-4.85-6.46-4.5,5.68-3-3.61-3.35,4.38ZM74.87,28.32h-2.25c-.21,0-.39-.07-.53-.22s-.22-.32-.22-.54.07-.39.22-.53.32-.21.53-.21h2.25v-2.25c0-.21.07-.39.22-.53s.32-.22.54-.22.39.07.53.22.21.32.21.53v2.25h2.25c.21,0,.39.07.53.22s.22.32.22.54-.07.39-.22.53-.32.21-.53.21h-2.25v2.25c0,.21-.07.39-.22.53s-.32.22-.54.22-.39-.07-.53-.22-.21-.32-.21-.53v-2.25Z' fill='%23afafae'/%3E%3C/svg%3E\");\n img_2.formatter.parseFormats({\n \"width\": \"100%\"\n });\n var h2_2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n h2_2.formatter.parseFormats({\n \"padding_bottom\": 12,\n \"padding_top\": 12\n });\n var p_2 = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n p_2.formatter.parseFormats({\n \"padding_bottom\": 17\n });\n var button_2 = new ButtonElement('Button', 'Learn More');\n button_2.formatter.parseFormats({\n \"align\": \"left\",\n \"font_size\": 13,\n \"text_color\": \"#FFFFFF\",\n \"text_align\": \"center\",\n \"background_color\": \"#000000\",\n \"padding_top\": 8,\n \"padding_right\": 16,\n \"padding_bottom\": 8,\n \"padding_left\": 16,\n \"border_top_width\": 0,\n \"border_right_width\": 0,\n \"border_bottom_width\": 0,\n \"border_left_width\": 0,\n \"border_radius\": 0\n });\n\n //\n var block1 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n block1.appendElements([img, h2, p, button]);\n var block2 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n block2.appendElements([img_2, h2_2, p_2, button_2]);\n\n //\n cell1.appendBlock(block1);\n cell2.appendBlock(block2);\n return _this;\n }\n _inherits(ImageTextDoubleWidget, _BaseWidget);\n return _createClass(ImageTextDoubleWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image_text_double');\n }\n }, {\n key: \"getImageUrl\",\n value: function getImageUrl() {\n return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 210 120'%3E%0A %3Crect width='210' height='120' fill='%23F7F7F7'/%3E%0A %3Crect x='14' y='12' width='84' height='44' rx='4' fill='%23EEEEEE'/%3E%0A %3Ccircle cx='34' cy='26' r='5' fill='%23D8D8D8'/%3E%0A %3Cpolygon points='32,46 44,30 56,46' fill='%23D0D0D0'/%3E%0A %3Cpolygon points='50,46 60,36 70,46' fill='%23DCDCDC'/%3E%0A %3Crect x='14' y='64' width='56' height='7' rx='3.5' fill='%23C0C0C0'/%3E%0A %3Crect x='14' y='78' width='84' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='14' y='88' width='68' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='14' y='102' width='36' height='10' rx='3' fill='%23404040'/%3E%0A %3Crect x='112' y='12' width='84' height='44' rx='4' fill='%23EEEEEE'/%3E%0A %3Ccircle cx='132' cy='26' r='5' fill='%23D8D8D8'/%3E%0A %3Cpolygon points='130,46 142,30 154,46' fill='%23D0D0D0'/%3E%0A %3Cpolygon points='148,46 158,36 168,46' fill='%23DCDCDC'/%3E%0A %3Crect x='112' y='64' width='56' height='7' rx='3.5' fill='%23C0C0C0'/%3E%0A %3Crect x='112' y='78' width='84' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='112' y='88' width='68' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='112' y='102' width='36' height='10' rx='3' fill='%23404040'/%3E%0A%3C/svg%3E\";\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'image';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageTextDoubleWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageTextDoubleWidget.js?");
/***/ }),
/***/ "./src/includes/ImageTextLeftWidget.js":
/*!*********************************************!*\
!*** ./src/includes/ImageTextLeftWidget.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ImageTextLeftWidget = /*#__PURE__*/function (_BaseWidget) {\n function ImageTextLeftWidget() {\n var _this;\n _classCallCheck(this, ImageTextLeftWidget);\n _this = _callSuper(this, ImageTextLeftWidget); // Call the parent class constructor\n\n //\n var grid = new GridElement('Grid');\n grid.cell_gap = 20;\n var cell1 = new CellElement('Cell');\n // Image cell — content-sized (intrinsic width from the image).\n cell1.formatter.setFormat('width', 'auto');\n var cell2 = new CellElement('Cell');\n // Text cell — `fill` is the explicit \"absorb remaining space\" primitive\n // (`flex: 1 1 0; min-width: 0`). Do NOT use `'100%'` here: that compiles\n // to `flex: 0 0 calc(100% - gapShare); min-width: 0`, a fixed-basis,\n // no-shrink cell. Paired with a sibling `auto` cell, the percentage\n // basis exceeds the row width → text cell overflows past the right\n // edge and the auto cell shrinks toward zero (image disappears).\n cell2.formatter.setFormat('width', 'fill');\n grid.appendCells([cell1, cell2]);\n _this.block.appendElements([grid]);\n\n //\n var img = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 101.23 140.64'%3E%3Crect width='101.23' height='140.64' fill='%23f6f6f4'/%3E%3Cpath d='M34.96,89.94c-1.13,0-2.07-.38-2.83-1.13s-1.13-1.7-1.13-2.83v-31.31c0-1.13.38-2.07,1.13-2.83s1.7-1.13,2.83-1.13h15.94c.35,0,.64.12.87.35s.35.53.35.87-.12.64-.35.87-.53.35-.87.35h-15.94c-.44,0-.8.14-1.09.42-.28.28-.42.64-.42,1.09v31.31c0,.44.14.8.42,1.09.28.28.64.42,1.09.42h31.31c.44,0,.8-.14,1.09-.42.28-.28.42-.64.42-1.09v-15.94c0-.35.12-.64.35-.87s.53-.35.87-.35.64.12.87.35.35.53.35.87v15.94c0,1.13-.38,2.07-1.13,2.83s-1.7,1.13-2.83,1.13h-31.31ZM37.79,81.07h25.65l-7.92-10.56-7.36,9.29-4.9-5.9-5.47,7.17ZM62.88,58.06h-3.68c-.35,0-.64-.12-.87-.35s-.35-.53-.35-.87.12-.64.35-.87.53-.35.87-.35h3.68v-3.68c0-.35.12-.64.35-.87s.53-.35.87-.35.64.12.87.35.35.53.35.87v3.68h3.68c.35,0,.64.12.87.35s.35.53.35.87-.12.64-.35.87-.53.35-.87.35h-3.68v3.68c0,.35-.12.64-.35.87s-.53.35-.87.35-.64-.12-.87-.35-.35-.53-.35-.87v-3.68Z' fill='%23afafae'/%3E%3C/svg%3E\");\n img.formatter.parseFormats({\n \"height\": 300\n });\n var h2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n h2.formatter.parseFormats({\n \"padding_bottom\": 12\n });\n var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n p.formatter.parseFormats({\n \"padding_bottom\": 17\n });\n var button = new ButtonElement('Button', 'Learn More');\n button.formatter.parseFormats({\n \"align\": \"left\",\n \"font_size\": 13,\n \"text_color\": \"#FFFFFF\",\n \"text_align\": \"center\",\n \"background_color\": \"#000000\",\n \"padding_top\": 8,\n \"padding_right\": 16,\n \"padding_bottom\": 8,\n \"padding_left\": 16,\n \"border_top_width\": 0,\n \"border_right_width\": 0,\n \"border_bottom_width\": 0,\n \"border_left_width\": 0,\n \"border_radius\": 0\n });\n\n //\n var block1 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n block1.appendElements([img]);\n var block2 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n block2.appendElements([h2, p, button]);\n\n //\n cell1.appendBlock(block1);\n cell2.appendBlock(block2);\n return _this;\n }\n _inherits(ImageTextLeftWidget, _BaseWidget);\n return _createClass(ImageTextLeftWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image_text_left');\n }\n }, {\n key: \"getImageUrl\",\n value: function getImageUrl() {\n return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 88'%3E%3Crect width='200' height='88' fill='%23F7F7F7'/%3E%3Crect x='14' y='14' width='72' height='60' rx='5' fill='%23EEEEEE'/%3E%3Ccircle cx='34' cy='32' r='6' fill='%23D8D8D8'/%3E%3Cpolygon points='30,58 44,40 58,58' fill='%23D0D0D0'/%3E%3Cpolygon points='50,58 60,46 70,58' fill='%23DCDCDC'/%3E%3Crect x='100' y='18' width='72' height='8' rx='4' fill='%23C0C0C0'/%3E%3Crect x='100' y='34' width='86' height='5' rx='2.5' fill='%23DEDEDE'/%3E%3Crect x='100' y='45' width='70' height='5' rx='2.5' fill='%23DEDEDE'/%3E%3Crect x='100' y='60' width='40' height='10' rx='3' fill='%23404040'/%3E%3C/svg%3E\";\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'image';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageTextLeftWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageTextLeftWidget.js?");
/***/ }),
/***/ "./src/includes/ImageTextRightWidget.js":
/*!**********************************************!*\
!*** ./src/includes/ImageTextRightWidget.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ImageTextRightWidget = /*#__PURE__*/function (_BaseWidget) {\n function ImageTextRightWidget() {\n var _this;\n _classCallCheck(this, ImageTextRightWidget);\n _this = _callSuper(this, ImageTextRightWidget); // Call the parent class constructor\n\n //\n var grid = new GridElement('Grid');\n grid.cell_gap = 20;\n var cell1 = new CellElement('Cell');\n // Image cell — content-sized (intrinsic width from the image).\n cell1.formatter.setFormat('width', 'auto');\n var cell2 = new CellElement('Cell');\n // Text cell — `fill` is the explicit \"absorb remaining space\" primitive\n // (`flex: 1 1 0; min-width: 0`). Do NOT use `'100%'` here: that compiles\n // to `flex: 0 0 calc(100% - gapShare); min-width: 0`, a fixed-basis,\n // no-shrink cell. Paired with a sibling `auto` cell, the percentage\n // basis exceeds the row width → text cell overflows past the right\n // edge and the auto cell shrinks toward zero (image disappears).\n cell2.formatter.setFormat('width', 'fill');\n // Order = [text, image] so the text cell renders on the LEFT and the\n // image cell renders on the RIGHT (Image-Text-RIGHT layout).\n grid.appendCells([cell2, cell1]);\n _this.block.appendElements([grid]);\n\n //\n var img = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 101.23 140.64'%3E%3Crect width='101.23' height='140.64' fill='%23f6f6f4'/%3E%3Cpath d='M34.96,89.94c-1.13,0-2.07-.38-2.83-1.13s-1.13-1.7-1.13-2.83v-31.31c0-1.13.38-2.07,1.13-2.83s1.7-1.13,2.83-1.13h15.94c.35,0,.64.12.87.35s.35.53.35.87-.12.64-.35.87-.53.35-.87.35h-15.94c-.44,0-.8.14-1.09.42-.28.28-.42.64-.42,1.09v31.31c0,.44.14.8.42,1.09.28.28.64.42,1.09.42h31.31c.44,0,.8-.14,1.09-.42.28-.28.42-.64.42-1.09v-15.94c0-.35.12-.64.35-.87s.53-.35.87-.35.64.12.87.35.35.53.35.87v15.94c0,1.13-.38,2.07-1.13,2.83s-1.7,1.13-2.83,1.13h-31.31ZM37.79,81.07h25.65l-7.92-10.56-7.36,9.29-4.9-5.9-5.47,7.17ZM62.88,58.06h-3.68c-.35,0-.64-.12-.87-.35s-.35-.53-.35-.87.12-.64.35-.87.53-.35.87-.35h3.68v-3.68c0-.35.12-.64.35-.87s.53-.35.87-.35.64.12.87.35.35.53.35.87v3.68h3.68c.35,0,.64.12.87.35s.35.53.35.87-.12.64-.35.87-.53.35-.87.35h-3.68v3.68c0,.35-.12.64-.35.87s-.53.35-.87.35-.64-.12-.87-.35-.35-.53-.35-.87v-3.68Z' fill='%23afafae'/%3E%3C/svg%3E\");\n img.formatter.parseFormats({\n \"height\": 300\n });\n var h2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n h2.formatter.parseFormats({\n \"padding_bottom\": 12\n });\n var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n p.formatter.parseFormats({\n \"padding_bottom\": 17\n });\n var button = new ButtonElement('Button', 'Learn More');\n button.formatter.parseFormats({\n \"align\": \"left\",\n \"font_size\": 13,\n \"text_color\": \"#FFFFFF\",\n \"text_align\": \"center\",\n \"background_color\": \"#000000\",\n \"padding_top\": 8,\n \"padding_right\": 16,\n \"padding_bottom\": 8,\n \"padding_left\": 16,\n \"border_top_width\": 0,\n \"border_right_width\": 0,\n \"border_bottom_width\": 0,\n \"border_left_width\": 0,\n \"border_radius\": 0\n });\n\n //\n var block1 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n block1.appendElements([img]);\n var block2 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n block2.appendElements([h2, p, button]);\n\n //\n cell1.appendBlock(block1);\n cell2.appendBlock(block2);\n return _this;\n }\n _inherits(ImageTextRightWidget, _BaseWidget);\n return _createClass(ImageTextRightWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image_text_right');\n }\n }, {\n key: \"getImageUrl\",\n value: function getImageUrl() {\n return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 88'%3E%0A %3Crect width='200' height='88' fill='%23F7F7F7'/%3E%0A %3Crect x='14' y='18' width='72' height='8' rx='4' fill='%23C0C0C0'/%3E%0A %3Crect x='14' y='34' width='86' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='14' y='45' width='70' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='14' y='60' width='40' height='10' rx='3' fill='%23404040'/%3E%0A %3Crect x='114' y='14' width='72' height='60' rx='5' fill='%23EEEEEE'/%3E%0A %3Ccircle cx='134' cy='32' r='6' fill='%23D8D8D8'/%3E%0A %3Cpolygon points='130,58 144,40 158,58' fill='%23D0D0D0'/%3E%0A %3Cpolygon points='150,58 160,46 170,58' fill='%23DCDCDC'/%3E%0A%3C/svg%3E\";\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'image';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageTextRightWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageTextRightWidget.js?");
/***/ }),
/***/ "./src/includes/ImageTextTopWidget.js":
/*!********************************************!*\
!*** ./src/includes/ImageTextTopWidget.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ImageTextTopWidget = /*#__PURE__*/function (_BaseWidget) {\n function ImageTextTopWidget() {\n var _this;\n _classCallCheck(this, ImageTextTopWidget);\n _this = _callSuper(this, ImageTextTopWidget); // Call the parent class constructor\n\n //\n var img = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 270.23 84.36'%3E%3Crect width='270.23' height='84.36' fill='%23f6f6f4'/%3E%3Cpath d='M123.15,57.18c-.86,0-1.58-.29-2.16-.87s-.87-1.3-.87-2.16v-23.94c0-.86.29-1.58.87-2.16s1.3-.87,2.16-.87h12.19c.27,0,.49.09.67.27s.27.4.27.67-.09.49-.27.67-.4.27-.67.27h-12.19c-.34,0-.61.11-.83.32-.22.22-.32.49-.32.83v23.94c0,.34.11.61.32.83.22.22.49.32.83.32h23.94c.34,0,.61-.11.83-.32.22-.22.32-.49.32-.83v-12.19c0-.27.09-.49.27-.67s.4-.27.67-.27.49.09.67.27.27.4.27.67v12.19c0,.86-.29,1.58-.87,2.16s-1.3.87-2.16.87h-23.94ZM125.31,50.4h19.62l-6.06-8.08-5.62,7.1-3.75-4.51-4.18,5.48ZM144.49,32.81h-2.81c-.27,0-.49-.09-.67-.27s-.27-.4-.27-.67.09-.49.27-.67.4-.27.67-.27h2.81v-2.81c0-.27.09-.49.27-.67s.4-.27.67-.27.49.09.67.27.27.4.27.67v2.81h2.81c.27,0,.49.09.67.27s.27.4.27.67-.09.49-.27.67-.4.27-.67.27h-2.81v2.81c0,.27-.09.49-.27.67s-.4.27-.67.27-.49-.09-.67-.27-.27-.4-.27-.67v-2.81Z' fill='%23afafae'/%3E%3C/svg%3E\");\n img.formatter.parseFormats({\n \"width\": \"100%\",\n \"padding_bottom\": 10\n });\n var h2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n h2.formatter.parseFormats({\n \"padding_bottom\": 12\n });\n var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n p.formatter.parseFormats({\n \"padding_bottom\": 17\n });\n var button = new ButtonElement('Button', 'Learn More');\n button.formatter.parseFormats({\n \"align\": \"left\",\n \"font_size\": 13,\n \"text_color\": \"#FFFFFF\",\n \"text_align\": \"center\",\n \"background_color\": \"#000000\",\n \"padding_top\": 8,\n \"padding_right\": 16,\n \"padding_bottom\": 8,\n \"padding_left\": 16,\n \"border_top_width\": 0,\n \"border_right_width\": 0,\n \"border_bottom_width\": 0,\n \"border_left_width\": 0,\n \"border_radius\": 0\n });\n\n //\n _this.block.appendElements([img, h2, p, button]);\n return _this;\n }\n _inherits(ImageTextTopWidget, _BaseWidget);\n return _createClass(ImageTextTopWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image_text_top');\n }\n }, {\n key: \"getImageUrl\",\n value: function getImageUrl() {\n return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 110'%3E%0A %3Crect width='180' height='110' fill='%23F7F7F7'/%3E%0A %3Crect x='14' y='12' width='152' height='46' rx='5' fill='%23EEEEEE'/%3E%0A %3Ccircle cx='46' cy='28' r='7' fill='%23D8D8D8'/%3E%0A %3Cpolygon points='60,48 84,24 108,48' fill='%23D0D0D0'/%3E%0A %3Cpolygon points='96,48 114,32 132,48' fill='%23DCDCDC'/%3E%0A %3Crect x='14' y='68' width='72' height='7' rx='3.5' fill='%23C0C0C0'/%3E%0A %3Crect x='14' y='82' width='140' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='14' y='94' width='44' height='10' rx='3' fill='%23404040'/%3E%0A%3C/svg%3E\";\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'image';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageTextTopWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageTextTopWidget.js?");
/***/ }),
/***/ "./src/includes/ImageWidget.js":
/*!*************************************!*\
!*** ./src/includes/ImageWidget.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ImageElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ImageElement.js */ \"./src/includes/ImageElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar ImageWidget = /*#__PURE__*/function (_BaseWidget) {\n function ImageWidget() {\n var _this;\n _classCallCheck(this, ImageWidget);\n _this = _callSuper(this, ImageWidget); // Call the parent class constructor\n _this.elements = [];\n\n // Add an ImageElement to the widget\n var image = new _ImageElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Image');\n\n // Append the new element to the block\n _this.block.appendElements([image]);\n return _this;\n }\n _inherits(ImageWidget, _BaseWidget);\n return _createClass(ImageWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'image';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageWidget.js?");
/***/ }),
/***/ "./src/includes/InfoBannerControl.js":
/*!*******************************************!*\
!*** ./src/includes/InfoBannerControl.js ***!
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\n/**\n * InfoBannerControl — lightweight informational surface for settings panels.\n *\n * Renders a single tinted banner with an icon and short guidance text. Styling\n * uses the `.bjs-info-banner` tokens so it inherits theme-aware colours.\n *\n * Usage:\n * new InfoBannerControl('Use px for email. % for responsive web pages.')\n * new InfoBannerControl(text, { icon: 'ⓘ' })\n */\nvar InfoBannerControl = /*#__PURE__*/_createClass(function InfoBannerControl() {\n var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$icon = _ref.icon,\n icon = _ref$icon === void 0 ? 'ⓘ' : _ref$icon;\n _classCallCheck(this, InfoBannerControl);\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-info-banner');\n this.domNode.innerHTML = \"\\n <span class=\\\"bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">\".concat(icon, \"</span>\\n <span class=\\\"bjs-info-banner-text\\\">\").concat(text, \"</span>\\n \");\n});\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InfoBannerControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/InfoBannerControl.js?");
/***/ }),
/***/ "./src/includes/InlineSanitizer.js":
/*!*****************************************!*\
!*** ./src/includes/InlineSanitizer.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ BLOCK_LEVEL_TAGS: () => (/* binding */ BLOCK_LEVEL_TAGS),\n/* harmony export */ EMAIL_SAFE_TAG_MAP: () => (/* binding */ EMAIL_SAFE_TAG_MAP),\n/* harmony export */ INLINE_TAG_WHITELIST: () => (/* binding */ INLINE_TAG_WHITELIST),\n/* harmony export */ NORMALIZE_TAG_MAP: () => (/* binding */ NORMALIZE_TAG_MAP),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * InlineSanitizer — T9 whitelist primitive for inline text content.\n *\n * BuilderJS is a full HTML5 page builder; email is one downgrade consumer\n * among many (page / site / form / popup / ad / email). The sanitizer has\n * three entry points corresponding to the three write paths each inline\n * text surface touches:\n *\n * 1. `sanitize(html, { mode })` — paste pipeline. Parses an untrusted\n * HTML string (clipboard contents, pasted MS Word / Google Docs /\n * Outlook / Notion), strips everything not in the T9 PAGE whitelist,\n * removes Office mso-* attrs, and returns a clean HTML string. The\n * W2.2 paste path (`Paste`, `Paste Plain`, `Paste and Match Style`)\n * routes every clipboard read through this.\n *\n * 2. `normalize(rootNode)` — in-place pass after every `execCommand`.\n * Canonicalises Safari/Chrome/Firefox markup divergence (`<b>` →\n * `<strong>`, `<i>` → `<em>`, redundant nested `<span>` merged).\n * Called from the W1.1 toolbar apply handlers so the element's\n * serialised state is deterministic regardless of which browser\n * the user edited in.\n *\n * 3. `emit(rootNode, { mode })` — serializer. Returns the canonical\n * HTML string a caller writes out. Mode `'page'` preserves the full\n * T9 PAGE whitelist verbatim (semantic tags survive round-trip).\n * Mode `'email-safe'` applies the EMAIL downgrade table — semantic\n * tags flatten to `<span style>`, `<ruby>`/`<rt>`/`<rp>` collapse\n * to base text, inline `<img>` rejected. Every element whose\n * container resolves `getOutputMode() === 'email-safe'` uses this\n * mode; everyone else gets full page mode.\n *\n * HARD RULE T9 (TEXT_INLINE_PLAN §0.2): inline content lives INSIDE a\n * block element. Block tags (`<p>`, `<div>`, `<h1-h6>`, `<ul>`, `<ol>`,\n * `<li>`, `<blockquote>`, `<pre>`, `<hr>`, `<table>` and friends) are\n * forbidden at the inline level in BOTH modes. `sanitize()` unwraps\n * them (keeps text content, drops the tag). Container media\n * (`<video>`, `<audio>`, `<iframe>`, `<canvas>`, `<embed>`, `<object>`)\n * and raw `<svg>` are rejected — the content is dropped entirely since\n * a text-only \"script stub\" makes no sense for those. Scripting/meta\n * (`<script>`, `<style>`, `<link>`, `<meta>`, `<base>`, `<noscript>`)\n * is dropped for security.\n *\n * The sanitizer is pure: zero DOM mutation on the input HTML string,\n * zero side effects on the outer document. `normalize()` IS in-place\n * by design (it mutates its rootNode argument) — that is the contract.\n */\n\n/** T9 PAGE whitelist — every tag the inline toolbar UI can produce. */\nvar INLINE_TAG_WHITELIST = Object.freeze(new Set([\n// Structural\n'span', 'a',\n// Bold / italic / decorations\n'strong', 'b', 'em', 'i', 'u', 's', 'del', 'ins', 'mark', 'sub', 'sup',\n// Code / documentation\n'code', 'samp', 'kbd', 'var',\n// Type scale + citations\n'small', 'abbr', 'cite', 'dfn', 'q',\n// Machine-readable\n'time', 'data',\n// Bidi + Asian-language\n'bdi', 'bdo', 'ruby', 'rt', 'rp',\n// Line breaks + zero-width break\n'br', 'wbr',\n// Inline media\n'img']));\n\n/** Tags canonicalised by `normalize()` → replacement. */\nvar NORMALIZE_TAG_MAP = Object.freeze({\n b: 'strong',\n i: 'em'\n});\n\n/**\n * HTML5 block-level tags that auto-close an open `<p>` / `<h1..h6>` / `<li>` /\n * `<dd>` / `<dt>` when encountered by the fragment parser. Inside an\n * inline-edit host (`<p>`, `<h*>`) these MUST NEVER appear — otherwise\n * setting `host.innerHTML = …` round-trips through the HTML5 fragment parser\n * which silently closes the host before the block tag, kicking the block\n * tag's content out of the host as a sibling and stripping the inline style\n * on the host from the visible content.\n *\n * Set membership matches the WHATWG HTML \"close-on-p\" element list.\n * Lowercase tag names.\n *\n * Consumed by `_unwrapBlockLevel(root)` — walks descendants of an\n * inline-edit host and replaces every block-level wrapper with its\n * children, inserting a `<br>` separator BEFORE the lifted content so the\n * user's visual line-break (Enter key) survives round-trip.\n *\n * Root-cause incident: 2026-05-20 Ben-Ami Car Wash & Detail (email\n * campaign builder). Chrome's contenteditable default-paragraph-separator\n * is `'div'`, so every Enter inside a `<p inline-edit=\"text\">` inserted a\n * `<div>` block-level child. On the next full re-render (delete-sibling-\n * block cascade) the `<p>`'s inline `font-weight` / `text-align` /\n * `font-family` styles vanished because the parser kicked the `<div>`\n * blocks out of the `<p>`. See docs/BUILDER.md §9.4.\n */\nvar BLOCK_LEVEL_TAGS = Object.freeze(new Set(['address', 'article', 'aside', 'blockquote', 'details', 'dialog', 'dir', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'ul', 'li', 'dt', 'dd']));\n\n/**\n * EMAIL downgrade table — applied by `emit({ mode: 'email-safe' })`.\n * Each entry says: \"when emitting an X tag for email, replace with Y\".\n * `null` replacement means \"flatten to text\" (reject the tag, keep\n * children).\n */\nvar EMAIL_SAFE_TAG_MAP = Object.freeze({\n // Bold/italic/decorations — Outlook 2007+ strips semantic tags inconsistently.\n strong: {\n tag: 'span',\n style: 'font-weight:bold'\n },\n b: {\n tag: 'span',\n style: 'font-weight:bold'\n },\n em: {\n tag: 'span',\n style: 'font-style:italic'\n },\n i: {\n tag: 'span',\n style: 'font-style:italic'\n },\n u: {\n tag: 'span',\n style: 'text-decoration:underline'\n },\n mark: {\n tag: 'span',\n style: 'background-color:#ffff00'\n },\n ins: {\n tag: 'span',\n style: 'text-decoration:underline'\n },\n del: {\n tag: 'span',\n style: 'text-decoration:line-through'\n },\n // Semantic tags — strip, keep text + inline style carried over.\n abbr: {\n tag: 'span',\n style: null\n },\n cite: {\n tag: 'span',\n style: null\n },\n dfn: {\n tag: 'span',\n style: null\n },\n q: {\n tag: 'span',\n style: null\n },\n time: {\n tag: 'span',\n style: null\n },\n data: {\n tag: 'span',\n style: null\n },\n kbd: {\n tag: 'span',\n style: null\n },\n \"var\": {\n tag: 'span',\n style: null\n },\n samp: {\n tag: 'span',\n style: null\n },\n // Bidi — keep dir attr so clients that respect it still align correctly.\n bdi: {\n tag: 'span',\n style: null,\n keepDirAttr: true\n },\n bdo: {\n tag: 'span',\n style: null,\n keepDirAttr: true\n },\n // Ruby annotations — email strips these; flatten to base text only.\n ruby: null,\n // flatten children\n rt: {\n drop: true\n },\n // drop the annotation text entirely\n rp: {\n drop: true\n },\n // drop the bracket markers entirely\n // Word-break hint — inconsistent across email clients; strip.\n wbr: {\n drop: true\n },\n // Inline image — produces render breaks in Outlook. Route to\n // ImageElement block. In emit, we REPLACE with an HTML comment so\n // the loss is visible to the caller rather than silent.\n img: {\n drop: true,\n trace: '<!-- inline img removed (email mode): use ImageElement -->'\n }\n});\n\n/**\n * Tags whose shell AND content must be dropped entirely (container\n * media + scripting). `sanitize()` rips these without keeping children.\n */\nvar DANGEROUS_TAGS = Object.freeze(new Set(['script', 'style', 'link', 'meta', 'base', 'noscript', 'video', 'audio', 'iframe', 'canvas', 'embed', 'object', 'svg', 'input', 'select', 'textarea', 'button', 'fieldset', 'legend', 'datalist', 'output', 'progress', 'meter', 'keygen', 'slot', 'template']));\n\n/**\n * Office / Google Docs / Outlook clipboard noise — tags that appear in\n * pasted content but carry no semantic value. Dropped in `sanitize()`\n * (shell removed, children kept so paragraph text survives).\n */\nvar OFFICE_NOISE_TAGS = Object.freeze(new Set(['o:p', 'w:sdt', 'w:sdtpr', 'w:sdtendpr', 'w:sdtcontent', 'm:t', 'm:r', 'xml']));\n\n/**\n * Attributes allowed on sanitised inline tags. Anything not listed is\n * stripped. `style` is allowed but heavily filtered per {@link FILTERED_STYLE_PROPS}.\n */\nvar ALLOWED_ATTRS = Object.freeze({\n a: new Set(['href', 'target', 'rel', 'download', 'title', 'aria-label']),\n img: new Set(['src', 'alt', 'width', 'height', 'title']),\n span: new Set(['style', 'class', 'dir', 'data-merge-tag', 'contenteditable', 'data-bjs-inline-text']),\n abbr: new Set(['title', 'style']),\n time: new Set(['datetime', 'style']),\n data: new Set(['value', 'style']),\n bdi: new Set(['dir', 'style']),\n bdo: new Set(['dir', 'style'])\n});\nvar UNIVERSAL_ALLOWED_ATTRS = Object.freeze(new Set(['style', 'class', 'dir']));\n\n/**\n * Inline CSS properties the sanitizer retains after paste. Everything\n * else (including Office `mso-*`, `font-family` — we own font family\n * via W3.1 FontPopoverOverlay, so pasted fonts would fight the toolbar)\n * is stripped.\n */\nvar FILTERED_STYLE_PROPS = Object.freeze(new Set(['color', 'background-color', 'font-weight', 'font-style', 'font-size', 'text-decoration', 'text-decoration-line', 'text-decoration-color', 'text-decoration-style', 'text-align', 'letter-spacing', 'line-height', 'vertical-align']));\nvar InlineSanitizer = /*#__PURE__*/function () {\n function InlineSanitizer() {\n _classCallCheck(this, InlineSanitizer);\n }\n return _createClass(InlineSanitizer, null, [{\n key: \"INLINE_TAG_WHITELIST\",\n get:\n /**\n * Expose the whitelists as static properties too — tests introspect\n * these directly (no import gymnastics).\n */\n function get() {\n return INLINE_TAG_WHITELIST;\n }\n }, {\n key: \"NORMALIZE_TAG_MAP\",\n get: function get() {\n return NORMALIZE_TAG_MAP;\n }\n }, {\n key: \"EMAIL_SAFE_TAG_MAP\",\n get: function get() {\n return EMAIL_SAFE_TAG_MAP;\n }\n\n /**\n * Parse an untrusted HTML string, strip every tag not in the inline\n * whitelist, drop Office noise + mso-* attrs + disallowed styles,\n * and return a clean HTML string in PAGE or EMAIL mode.\n *\n * @param {string} html\n * @param {Object} [opts]\n * @param {'page'|'email-safe'} [opts.mode='page']\n * @returns {string}\n */\n }, {\n key: \"sanitize\",\n value: function sanitize(html) {\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n if (html === null || html === undefined) return '';\n if (typeof html !== 'string') {\n throw new TypeError('InlineSanitizer.sanitize: html must be a string');\n }\n var mode = opts.mode === 'email-safe' ? 'email-safe' : 'page';\n\n // Pre-parse text cleanup:\n // 1. ALL HTML comments (general, non-greedy) — covers both\n // Office conditional comments (`<!--[if gte mso 9]>...<![endif]-->`)\n // and descriptive author comments. Using a specialized\n // conditional-comment regex FIRST was a trap: when a\n // descriptive comment CONTAINED the literal text `<!--[if ...]>`,\n // the conditional regex would greedy-match from that inner\n // open to the later `<![endif]-->`, consuming the descriptive\n // comment's own `-->` terminator — leaving a dangling open\n // `<!--` that DOMParser treated as an unterminated comment\n // wrapping the rest of the document. The general\n // `<!--[\\s\\S]*?-->` regex handles both shapes cleanly because\n // it always anchors to the NEAREST terminator. Caught in the\n // W0.5 Word-2019 fixture test (2026-04-20).\n // 2. XML / DOCTYPE shells from paste clipboards.\n var cleanSource = html.replace(/<!--[\\s\\S]*?-->/g, '').replace(/<\\?xml[\\s\\S]*?\\?>/gi, '').replace(/<!DOCTYPE[^>]*>/gi, '');\n var doc = new DOMParser().parseFromString(\"<div id=\\\"__bjs_sanitize_root\\\">\".concat(cleanSource, \"</div>\"), 'text/html');\n var root = doc.getElementById('__bjs_sanitize_root');\n if (!root) return '';\n InlineSanitizer._walkClean(root);\n if (mode === 'email-safe') {\n InlineSanitizer._walkEmailDowngrade(root);\n }\n return root.innerHTML;\n }\n\n /**\n * Canonicalize browser-divergent markup in-place. `<b>` → `<strong>`,\n * `<i>` → `<em>`, consecutive nested `<span>` with no attributes\n * merged. Called after every execCommand so the serialised state is\n * deterministic.\n *\n * Mutates rootNode in place. Safe to call repeatedly — idempotent\n * after first pass.\n *\n * @param {HTMLElement} rootNode\n * @returns {HTMLElement} the same rootNode\n */\n }, {\n key: \"normalize\",\n value: function normalize(rootNode) {\n if (!rootNode || rootNode.nodeType !== 1) {\n throw new TypeError('InlineSanitizer.normalize: rootNode must be an HTMLElement');\n }\n // Order matters:\n // 1. Unwrap block-level descendants FIRST — the `<div>`s Chrome\n // inserts for Enter contain inline children we want to keep.\n // Doing this before _normalizeTags lets the canonicalize pass\n // see the lifted children at the right depth.\n // 2. Canonicalise `<b>→<strong>` / `<i>→<em>`.\n // 3. Collapse attribute-less / nested `<span>`s — runs LAST so\n // any empty spans produced by step 1 are also removed.\n InlineSanitizer._unwrapBlockLevel(rootNode);\n InlineSanitizer._normalizeTags(rootNode);\n InlineSanitizer._collapseEmptySpans(rootNode);\n return rootNode;\n }\n\n /**\n * Emit the canonical HTML for a root node in the chosen mode. PAGE\n * mode preserves the full whitelist verbatim (round-trip invariant).\n * EMAIL mode applies the downgrade table — semantic tags become\n * `<span style>`, ruby annotations flatten, inline `<img>` rejected.\n *\n * Does NOT mutate rootNode. Caller gets a string.\n *\n * @param {HTMLElement} rootNode\n * @param {Object} [opts]\n * @param {'page'|'email-safe'} [opts.mode='page']\n * @returns {string}\n */\n }, {\n key: \"emit\",\n value: function emit(rootNode) {\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n if (!rootNode || rootNode.nodeType !== 1) {\n throw new TypeError('InlineSanitizer.emit: rootNode must be an HTMLElement');\n }\n var mode = opts.mode === 'email-safe' ? 'email-safe' : 'page';\n if (mode === 'page') return rootNode.innerHTML;\n\n // Clone so we don't mutate the caller's DOM.\n var clone = rootNode.cloneNode(true);\n InlineSanitizer._walkEmailDowngrade(clone);\n return clone.innerHTML;\n }\n\n /* ── Private — shared walkers ───────────────────────────────────── */\n\n /**\n * Walk rootNode descendants. For each element:\n * - If tag is DANGEROUS → remove the element (drop content too).\n * - If tag is OFFICE_NOISE → unwrap (keep children).\n * - If tag is NOT in INLINE_TAG_WHITELIST → unwrap (block tag; keep children).\n * - Else → prune attributes to ALLOWED_ATTRS for that tag +\n * UNIVERSAL, filter inline style to FILTERED_STYLE_PROPS,\n * preserve merge-tag chips verbatim.\n */\n }, {\n key: \"_walkClean\",\n value: function _walkClean(node) {\n // Iterate snapshot because unwrap/remove mutates the live child list.\n var children = Array.from(node.children);\n for (var _i = 0, _children = children; _i < _children.length; _i++) {\n var el = _children[_i];\n InlineSanitizer._walkClean(el); // depth-first — attr + style handled after recurse\n var tag = el.tagName.toLowerCase();\n if (DANGEROUS_TAGS.has(tag)) {\n el.remove();\n continue;\n }\n if (OFFICE_NOISE_TAGS.has(tag) || tag.includes(':')) {\n // Namespaced Office/Word tags (`o:p`, `w:sdt`, etc.) and\n // plain OFFICE_NOISE_TAGS all unwrap.\n InlineSanitizer._unwrap(el);\n continue;\n }\n\n // Preserve merge-tag chip as-is (contenteditable=false + data-merge-tag).\n if (tag === 'span' && el.getAttribute('contenteditable') === 'false' && el.hasAttribute('data-merge-tag')) {\n // Still filter other attrs + style for hygiene.\n InlineSanitizer._pruneAttributes(el, tag);\n continue;\n }\n if (!INLINE_TAG_WHITELIST.has(tag)) {\n // Block tag or anything else not in whitelist — unwrap.\n InlineSanitizer._unwrap(el);\n continue;\n }\n InlineSanitizer._pruneAttributes(el, tag);\n }\n }\n\n /** In-place attribute prune + style filter for a whitelisted element. */\n }, {\n key: \"_pruneAttributes\",\n value: function _pruneAttributes(el, tag) {\n var allowed = ALLOWED_ATTRS[tag] || UNIVERSAL_ALLOWED_ATTRS;\n var attrs = Array.from(el.attributes);\n for (var _i2 = 0, _attrs = attrs; _i2 < _attrs.length; _i2++) {\n var a = _attrs[_i2];\n var name = a.name.toLowerCase();\n // Drop mso-* / w:* / office attrs unconditionally.\n if (name.startsWith('mso-') || name.startsWith('w:') || name.startsWith('o:')) {\n el.removeAttribute(a.name);\n continue;\n }\n // Keep if allowed OR universal allowed.\n if (allowed.has(name) || UNIVERSAL_ALLOWED_ATTRS.has(name)) continue;\n el.removeAttribute(a.name);\n }\n var style = el.getAttribute('style');\n if (style) {\n var filtered = InlineSanitizer._filterStyle(style);\n if (filtered) {\n el.setAttribute('style', filtered);\n } else {\n el.removeAttribute('style');\n }\n }\n }\n\n /** Filter an inline `style` string to FILTERED_STYLE_PROPS + drop mso-* props. */\n }, {\n key: \"_filterStyle\",\n value: function _filterStyle(styleStr) {\n var parts = styleStr.split(';');\n var kept = [];\n var _iterator = _createForOfIteratorHelper(parts),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var raw = _step.value;\n var seg = raw.trim();\n if (!seg) continue;\n var colonIdx = seg.indexOf(':');\n if (colonIdx < 0) continue;\n var prop = seg.slice(0, colonIdx).trim().toLowerCase();\n var val = seg.slice(colonIdx + 1).trim();\n if (!prop || !val) continue;\n if (prop.startsWith('mso-')) continue;\n if (prop === 'font-family') continue; // W3.1 owns font family\n if (!FILTERED_STYLE_PROPS.has(prop)) continue;\n kept.push(\"\".concat(prop, \": \").concat(val));\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n return kept.join('; ');\n }\n\n /** Replace `el` with its children in its parent, preserving order. */\n }, {\n key: \"_unwrap\",\n value: function _unwrap(el) {\n var parent = el.parentNode;\n if (!parent) return;\n while (el.firstChild) parent.insertBefore(el.firstChild, el);\n parent.removeChild(el);\n }\n\n /* ── Private — normalize helpers ────────────────────────────────── */\n }, {\n key: \"_normalizeTags\",\n value: function _normalizeTags(root) {\n // `<b>` → `<strong>`, `<i>` → `<em>`. We do this by creating a\n // replacement element + moving children, since setAttribute\n // cannot rename a tag in place.\n for (var _i3 = 0, _Object$entries = Object.entries(NORMALIZE_TAG_MAP); _i3 < _Object$entries.length; _i3++) {\n var _Object$entries$_i = _slicedToArray(_Object$entries[_i3], 2),\n from = _Object$entries$_i[0],\n to = _Object$entries$_i[1];\n var matches = root.querySelectorAll(from);\n var _iterator2 = _createForOfIteratorHelper(matches),\n _step2;\n try {\n for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n var el = _step2.value;\n var replacement = el.ownerDocument.createElement(to);\n // Preserve attributes (post-normalize pass, attrs are\n // trusted — we assume sanitize already ran).\n for (var _i4 = 0, _Array$from = Array.from(el.attributes); _i4 < _Array$from.length; _i4++) {\n var a = _Array$from[_i4];\n replacement.setAttribute(a.name, a.value);\n }\n while (el.firstChild) replacement.appendChild(el.firstChild);\n el.parentNode.replaceChild(replacement, el);\n }\n } catch (err) {\n _iterator2.e(err);\n } finally {\n _iterator2.f();\n }\n }\n }\n\n /**\n * Depth-first unwrap of every block-level descendant. Each removed\n * wrapper leaves a `<br>` separator behind so a user's visual line\n * break (Enter inside contenteditable, paste-with-paragraphs) round-\n * trips as a single inline `<br>` instead of an invalid `<div>` /\n * `<p>` inside `<p>`.\n *\n * Rules (preserves round-trip invariants):\n * - If the block is the FIRST child of its parent AND has no prior\n * sibling text → no `<br>` (avoids a leading blank line).\n * - If the previous sibling is already a `<br>` → no `<br>` (avoids\n * stacking).\n * - Block's element children are recursed FIRST so nested blocks\n * are flattened depth-first.\n * - Attributes on the block (`style`, `class`) are DROPPED. Users\n * style at the inline-edit host (`<p style>`) level via the\n * formatter; inline range-level styles live on whitelisted inline\n * tags (`<span style>` / `<strong>` / `<em>`). A user-introduced\n * `<div style=\"…\">` is treated as \"structural noise\" — the visual\n * style on a Chrome auto-inserted `<div>` is always the\n * contenteditable default (no useful authoring intent), so\n * stripping it never destroys real authoring.\n *\n * Idempotent.\n */\n }, {\n key: \"_unwrapBlockLevel\",\n value: function _unwrapBlockLevel(root) {\n var doc = root.ownerDocument;\n if (!doc) return;\n var _walk = function walk(parent) {\n var children = Array.from(parent.childNodes);\n for (var _i5 = 0, _children2 = children; _i5 < _children2.length; _i5++) {\n var child = _children2[_i5];\n if (child.nodeType !== 1) continue; // ELEMENT_NODE\n if (!BLOCK_LEVEL_TAGS.has(child.tagName.toLowerCase())) {\n _walk(child);\n continue;\n }\n // Recurse INTO the block first so nested blocks flatten.\n _walk(child);\n // Decide whether to insert a <br> separator before lifting.\n var prev = child.previousSibling;\n var hasMeaningfulPrev = prev !== null && !(prev.nodeType === 1 && prev.tagName.toLowerCase() === 'br');\n if (hasMeaningfulPrev) {\n var br = doc.createElement('br');\n child.parentNode.insertBefore(br, child);\n }\n // Lift children out of the block, in document order.\n while (child.firstChild) {\n child.parentNode.insertBefore(child.firstChild, child);\n }\n child.parentNode.removeChild(child);\n }\n };\n _walk(root);\n }\n }, {\n key: \"_collapseEmptySpans\",\n value: function _collapseEmptySpans(root) {\n // Remove `<span>` with zero attributes, unwrap `<span>` nested\n // inside another `<span>` when both carry no attributes.\n // Idempotent — multiple passes converge to a fixed point.\n var changed = true;\n while (changed) {\n changed = false;\n var spans = root.querySelectorAll('span');\n var _iterator3 = _createForOfIteratorHelper(spans),\n _step3;\n try {\n for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n var span = _step3.value;\n if (span.attributes.length > 0) continue;\n // No attrs — unwrap (keep children as siblings).\n InlineSanitizer._unwrap(span);\n changed = true;\n }\n } catch (err) {\n _iterator3.e(err);\n } finally {\n _iterator3.f();\n }\n }\n }\n\n /* ── Private — email downgrade walker ───────────────────────────── */\n }, {\n key: \"_walkEmailDowngrade\",\n value: function _walkEmailDowngrade(node) {\n // Iterate snapshot because we restructure the tree.\n var children = Array.from(node.children);\n for (var _i6 = 0, _children3 = children; _i6 < _children3.length; _i6++) {\n var el = _children3[_i6];\n InlineSanitizer._walkEmailDowngrade(el);\n var tag = el.tagName.toLowerCase();\n // `tag in EMAIL_SAFE_TAG_MAP` — distinguishes \"not in map\"\n // (skip, tag stays) from \"explicitly null\" (unwrap, for ruby).\n // `if (!map)` would treat null as skip, a subtle bug caught in\n // W0.5 test 17 — ruby kept its shell instead of flattening.\n if (!(tag in EMAIL_SAFE_TAG_MAP)) continue;\n var map = EMAIL_SAFE_TAG_MAP[tag];\n if (map === null) {\n // Ruby — flatten children (unwrap).\n InlineSanitizer._unwrap(el);\n continue;\n }\n if (map.drop) {\n // rt/rp/wbr/img — drop entirely. If `trace`, leave a comment.\n if (map.trace) {\n var comment = el.ownerDocument.createComment(map.trace.replace(/^<!--\\s*|\\s*-->$/g, ''));\n el.parentNode.replaceChild(comment, el);\n } else {\n el.remove();\n }\n continue;\n }\n if (map.tag) {\n var replacement = el.ownerDocument.createElement(map.tag);\n // Merge styles: caller-provided downgrade style + any\n // inline style already on the element (post-sanitize).\n var existingStyle = el.getAttribute('style') || '';\n var downgradeStyle = map.style || '';\n var combined = [existingStyle, downgradeStyle].filter(Boolean).map(function (s) {\n return s.replace(/;\\s*$/, '');\n }).join('; ');\n if (combined) replacement.setAttribute('style', combined);\n // Preserve class + dir if requested.\n if (el.hasAttribute('class')) replacement.setAttribute('class', el.getAttribute('class'));\n if (map.keepDirAttr && el.hasAttribute('dir')) {\n replacement.setAttribute('dir', el.getAttribute('dir'));\n }\n while (el.firstChild) replacement.appendChild(el.firstChild);\n el.parentNode.replaceChild(replacement, el);\n }\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InlineSanitizer);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/InlineSanitizer.js?");
/***/ }),
/***/ "./src/includes/InnerPaddingControl.js":
/*!*********************************************!*\
!*** ./src/includes/InnerPaddingControl.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * InnerPaddingControl — 4-side numeric editor for **intrinsic-shape**\n * padding. Sibling of `PaddingMarginControl`, deliberately NOT a\n * subclass. The two controls serve semantically different purposes:\n *\n * | Control | Use case |\n * | ---------------------- | ------------------------------------------------ |\n * | PaddingMarginControl | LAYOUT padding — space around child content in a |\n * | | container (Block / Cell / Page). Has pin toggle |\n * | | + canvas visualiser bus. |\n * | InnerPaddingControl | INTRINSIC padding — shapes the element's own |\n * | | size (Button width/height via `padding: 12 24`, |\n * | | Alert box inner space, Table-cell padding, form |\n * | | input breathing room). No pin, no bus. Callback |\n * | | only. |\n *\n * Mixing them is a bug. See BUILDER.md \"RULE B — Padding semantic\n * separation\" (2026-04-19, W3.8b).\n *\n * DOM reuses `.bjs-pm-*` primitive classes so CSS stays shared and the\n * visual design is identical; `InnerPaddingControl` just omits the pin\n * toggle slot and swaps the info-banner copy.\n */\nvar InnerPaddingControl = /*#__PURE__*/function () {\n /**\n * @param {string} label\n * @param {object} values initial { top, right, bottom, left }\n * @param {object} callback { setValues(values) }\n */\n function InnerPaddingControl(label, values, callback) {\n _classCallCheck(this, InnerPaddingControl);\n this.label = label;\n this.top = values.top !== undefined ? values.top : null;\n this.bottom = values.bottom !== undefined ? values.bottom : null;\n this.left = values.left !== undefined ? values.left : null;\n this.right = values.right !== undefined ? values.right : null;\n this.callback = callback;\n this.domNode = document.createElement('div');\n this._buildDom();\n this._bindEvents();\n this._syncPreview();\n }\n return _createClass(InnerPaddingControl, [{\n key: \"_buildDom\",\n value: function _buildDom() {\n var _this = this;\n var side = function side(name, labelKey) {\n var value = _this[name];\n var display = value === null ? '' : value;\n var nullClass = value === null ? 'is-null' : '';\n return \"\\n <div class=\\\"bjs-pm-side\\\" data-side=\\\"\".concat(name, \"\\\">\\n <label class=\\\"bjs-pm-side-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey), \"</label>\\n <div class=\\\"bjs-pm-side-stepper\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"\").concat(name, \"-clear\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('padding.clear'), \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('padding.clear'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">close</span>\\n </button>\\n <input type=\\\"number\\\" class=\\\"bjs-text-input bjs-pm-input \").concat(nullClass, \"\\\" name=\\\"\").concat(name, \"\\\" value=\\\"\").concat(display, \"\\\" placeholder=\\\"--\\\" min=\\\"0\\\" step=\\\"1\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey), \"\\\">\\n <div class=\\\"bjs-vstepper\\\" role=\\\"group\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-vstepper-btn\\\" data-control=\\\"\").concat(name, \"-increase\\\" aria-label=\\\"+\\\">\\n <span class=\\\"material-symbols-rounded\\\">arrow_drop_up</span>\\n </button>\\n <button type=\\\"button\\\" class=\\\"bjs-vstepper-btn\\\" data-control=\\\"\").concat(name, \"-decrease\\\" aria-label=\\\"\\u2212\\\">\\n <span class=\\\"material-symbols-rounded\\\">arrow_drop_down</span>\\n </button>\\n </div>\\n </div>\\n </div>\\n \");\n };\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-stack bjs-pm-control bjs-pm-control--inner\\\">\\n <div class=\\\"bjs-pm-label-row\\\" style=\\\"display:flex;align-items:center;gap:8px;\\\">\\n <label class=\\\"bjs-control-label\\\" style=\\\"margin:0;\\\">\".concat(this.label, \"</label>\\n </div>\\n <div class=\\\"bjs-info-banner bjs-info-banner--flush\\\" role=\\\"note\\\">\\n <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">info</span>\\n <span class=\\\"bjs-info-banner-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('inner_padding.help'), \"</span>\\n </div>\\n <div class=\\\"bjs-pm-body\\\">\\n <div class=\\\"bjs-pm-grid\\\">\\n \").concat(side('top', 'padding.top'), \"\\n \").concat(side('left', 'padding.left'), \"\\n \").concat(side('right', 'padding.right'), \"\\n \").concat(side('bottom', 'padding.bottom'), \"\\n </div>\\n <div class=\\\"bjs-pm-preview\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"bjs-pm-preview-outer\\\" data-control=\\\"preview-outer\\\">\\n <div class=\\\"bjs-pm-preview-inner\\\" data-control=\\\"preview-inner\\\"></div>\\n </div>\\n </div>\\n </div>\\n </div>\\n \");\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this2 = this;\n ['top', 'right', 'bottom', 'left'].forEach(function (position) {\n var clearBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-clear\\\"]\"));\n var decreaseBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-decrease\\\"]\"));\n var increaseBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-increase\\\"]\"));\n var input = _this2.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n clearBtn.addEventListener('click', function () {\n return _this2.clearValue(position);\n });\n decreaseBtn.addEventListener('click', function () {\n return _this2.updateValue(position, -5);\n });\n increaseBtn.addEventListener('click', function () {\n return _this2.updateValue(position, 5);\n });\n input.addEventListener('input', function (e) {\n return _this2.setValue(position, e.target.value);\n });\n input.addEventListener('focus', function () {\n return _this2._syncPreview();\n });\n });\n }\n }, {\n key: \"clearValue\",\n value: function clearValue(position) {\n this[position] = null;\n var input = this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n input.value = '';\n input.classList.add('is-null');\n this.callback.setValues(this.getValues());\n this._syncPreview();\n }\n }, {\n key: \"updateValue\",\n value: function updateValue(position, delta) {\n var currentValue = this[position] === null ? 0 : this[position];\n this[position] = Math.max(0, currentValue + delta);\n var input = this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n input.value = this[position];\n input.classList.remove('is-null');\n this.callback.setValues(this.getValues());\n this._syncPreview();\n }\n }, {\n key: \"setValue\",\n value: function setValue(position, value) {\n if (value === '' || value === null || value === undefined) {\n this[position] = null;\n this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\")).classList.add('is-null');\n } else {\n this[position] = Math.max(0, parseInt(value) || 0);\n this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\")).classList.remove('is-null');\n }\n this.callback.setValues(this.getValues());\n this._syncPreview();\n }\n }, {\n key: \"getValues\",\n value: function getValues() {\n return {\n top: this.top,\n bottom: this.bottom,\n left: this.left,\n right: this.right\n };\n }\n\n // Identical preview scaling as PaddingMarginControl — 50px ≈ 10px inset,\n // capped 22px so opposing sides can't collapse the inner box.\n }, {\n key: \"_syncPreview\",\n value: function _syncPreview() {\n var inner = this.domNode.querySelector('[data-control=\"preview-inner\"]');\n if (!inner) return;\n var clamp = function clamp(v) {\n var n = v == null ? 0 : parseInt(v, 10) || 0;\n return Math.max(0, Math.min(22, Math.round(n / 5)));\n };\n inner.style.top = clamp(this.top) + 'px';\n inner.style.right = clamp(this.right) + 'px';\n inner.style.bottom = clamp(this.bottom) + 'px';\n inner.style.left = clamp(this.left) + 'px';\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InnerPaddingControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/InnerPaddingControl.js?");
/***/ }),
/***/ "./src/includes/LabelElement.js":
/*!**************************************!*\
!*** ./src/includes/LabelElement.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _RadiosControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./RadiosControl.js */ \"./src/includes/RadiosControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar LabelElement = /*#__PURE__*/function (_BaseElement) {\n function LabelElement(template, text) {\n var _this;\n _classCallCheck(this, LabelElement);\n _this = _callSuper(this, LabelElement); // Call the parent class constructor\n _this.template = template;\n _this.text = text;\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['text'];\n\n // Inline edit\n // W0.2b note: LabelElement does NOT call registerInlineEdit('text').\n // Label.template.html intentionally omits the inline-edit=\"text\" attr\n // (labels render `<label><%- text %></label>` only — no editable\n // surface). Users edit a Label's text via the sidebar RichTextControl.\n // Pre-W0.2b this element declared `inlineEditParams = ['text']` but\n // the per-element wire silently no-op'd because the template had no\n // matching node. The strict W0.2b guards correctly surface this; the\n // honest fix is to drop the dead declaration. If a future ship makes\n // Label inline-editable on canvas, add `inline-edit=\"text\"` to\n // Label.template.html FIRST then add `registerInlineEdit('text')` here.\n\n // Formatter\n _this.formatter = new Formatter({\n // text styles\n font_family: null,\n font_weight: null,\n font_size: null,\n text_color: null,\n link_color: null,\n paragraph_spacing: null,\n text_align: 'left',\n // left, center, right,\n line_height: null,\n letter_spacing: null,\n text_direction: \"ltr\",\n // ltr, rtl\n\n // background\n background_color: null,\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n // spacing\n padding_top: 0,\n padding_right: 0,\n padding_bottom: 0,\n padding_left: 0,\n // border\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_width: null,\n border_left_style: null,\n border_left_color: null,\n // border radius\n border_radius: 0\n });\n return _this;\n }\n _inherits(LabelElement, _BaseElement);\n return _createClass(LabelElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.label');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter + text auto-merged (W0.2c); see W0.2b note above re: no inline-edit\n this.domNode.innerHTML = this.renderTemplate({});\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(LabelElement, \"getData\", this, 3)([])), {}, {\n text: this.text\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this,\n _this$host;\n // W3.1 — bus wiring for dual-view sync with FontPopoverOverlay.\n var busOpts = function busOpts(key) {\n var _this2$host;\n return {\n bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n elementUid: _this2.id,\n formatterKey: key\n };\n };\n return [\n // TEXT_INLINE_PLAN W8 (2026-04-24) — RichTextControl retired.\n // Canvas inline-edit = text surface; sidebar = config panel only.\n new FontFamilyControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('font_family', value);\n _this2.render();\n }\n }, busOpts('font_family')), new FontWeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('font_weight', value);\n _this2.render();\n }\n }, busOpts('font_weight')), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('font_size', value);\n _this2.render();\n }\n }, _objectSpread({\n defaultValue: 16,\n minValue: 8,\n maxValue: 72,\n suffix: 'px',\n allowZero: false\n }, busOpts('font_size'))), new ColorPickerControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('text_color', value);\n _this2.render();\n }\n }), new ColorPickerControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('link_color', value);\n _this2.render();\n }\n }), new AlignControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_alignment'), this.formatter.getFormat('text_align'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('text_align', value);\n _this2.render();\n }\n }, ['left', 'justify', 'center', 'right'], {\n bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n elementUid: this.id,\n formatterKey: 'text_align'\n }), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('paragraph_spacing', value);\n _this2.render();\n }\n }, {\n defaultValue: 0,\n minValue: 0,\n maxValue: 50,\n suffix: 'px',\n allowZero: true\n }), new LineHeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('line_height', value);\n _this2.render();\n }\n }), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('letter_spacing', value);\n _this2.render();\n }\n }, {\n defaultValue: 0,\n minValue: -5,\n maxValue: 10,\n step: 0.1,\n suffix: 'px',\n allowZero: true,\n allowNegative: true\n }), new TextDirectionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('text_direction', value);\n _this2.render();\n }\n }), new BackgroundControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n color: this.formatter.getFormat('background_color'),\n image: this.formatter.getFormat('background_image'),\n position: this.formatter.getFormat('background_position'),\n size: this.formatter.getFormat('background_size'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n }, {\n setBackground: function setBackground(values) {\n _this2.formatter.setFormat('background_color', values.color);\n _this2.formatter.setFormat('background_image', values.image);\n _this2.formatter.setFormat('background_position', values.position);\n _this2.formatter.setFormat('background_size', values.size);\n _this2.formatter.setFormat('background_repeat', values.repeat);\n _this2.render();\n }\n }, {\n features: ['color', 'image', 'size', 'repeat', 'gradient']\n }), new BorderControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style'),\n border_top_width: this.formatter.getFormat('border_top_width'),\n border_top_color: this.formatter.getFormat('border_top_color'),\n border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n border_left_style: this.formatter.getFormat('border_left_style'),\n border_left_width: this.formatter.getFormat('border_left_width'),\n border_left_color: this.formatter.getFormat('border_left_color'),\n border_right_style: this.formatter.getFormat('border_right_style'),\n border_right_width: this.formatter.getFormat('border_right_width'),\n border_right_color: this.formatter.getFormat('border_right_color')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this2.formatter.setFormat('border_top_style', border_top_style);\n _this2.formatter.setFormat('border_top_width', border_top_width);\n _this2.formatter.setFormat('border_top_color', border_top_color);\n _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this2.formatter.setFormat('border_left_style', border_left_style);\n _this2.formatter.setFormat('border_left_width', border_left_width);\n _this2.formatter.setFormat('border_left_color', border_left_color);\n _this2.formatter.setFormat('border_right_style', border_right_style);\n _this2.formatter.setFormat('border_right_width', border_right_width);\n _this2.formatter.setFormat('border_right_color', border_right_color);\n\n // re-render\n _this2.render();\n }\n }), new BorderRadiusControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n setRadius: function setRadius(v) {\n _this2.formatter.setFormat('border_radius', v);\n _this2.render();\n }\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.text), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LabelElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LabelElement.js?");
/***/ }),
/***/ "./src/includes/LegacyHeadingAliasElement.js":
/*!***************************************************!*\
!*** ./src/includes/LegacyHeadingAliasElement.js ***!
\***************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\nvar LegacyHeadingAliasElement = /*#__PURE__*/function (_HeadingElement) {\n function LegacyHeadingAliasElement(template, text) {\n _classCallCheck(this, LegacyHeadingAliasElement);\n return _callSuper(this, LegacyHeadingAliasElement, ['Heading', (this instanceof LegacyHeadingAliasElement ? this.constructor : void 0).headingType, text]);\n }\n _inherits(LegacyHeadingAliasElement, _HeadingElement);\n return _createClass(LegacyHeadingAliasElement, [{\n key: \"getClassName\",\n value: function getClassName() {\n return 'HeadingElement';\n }\n }, {\n key: \"getName\",\n value: function getName() {\n return this.constructor.headingLabel;\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n // W0.2c: legacy aliases create a HeadingElement (forced type), not\n // an instance of `this`, so we use HeadingElement.parseFormats\n // (inherited via BaseElement) directly.\n var element = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]('Heading', this.headingType, data.text || this.headingLabel);\n return _HeadingElement_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].parseFormats(element, data);\n }\n }]);\n}(_HeadingElement_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\nLegacyHeadingAliasElement.headingType = 'h1';\nLegacyHeadingAliasElement.headingLabel = 'Heading 1';\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LegacyHeadingAliasElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LegacyHeadingAliasElement.js?");
/***/ }),
/***/ "./src/includes/LetterSpacingControl.js":
/*!**********************************************!*\
!*** ./src/includes/LetterSpacingControl.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar LetterSpacingControl = /*#__PURE__*/function () {\n function LetterSpacingControl(label, value, callback) {\n _classCallCheck(this, LetterSpacingControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n // Initialize properties\n this.label = label; // Label for the text control\n this.value = value; // Initial /* left | center | right */\n this.callback = callback; // Callback function to handle input changes\n\n // Create the main container element\n this.domNode = document.createElement(\"div\");\n\n //\n this.render(); // Call the render method to create the UI\n }\n return _createClass(LetterSpacingControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n this.domNode.innerHTML = \"<div class=\\\"py-2 ps-3 pe-3 w-100 d-flex align-items-center justify-content-between\\\">\\n <label for=\\\"\".concat(this.id, \"\\\" class=\\\"form-label fw-semibold mb-0 me-3\\\">\").concat(this.label, \"</label>\\n\\n <div class=\\\"input-group flex-nowrap w-25 \\\" role=\\\"group\\\" aria-label=\\\"\").concat(this.label, \"\\\" style=\\\"min-width:140px; height: 32px;\\\">\\n <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"reduction\\\" type=\\\"button\\\">-</button>\\n <input id=\\\"\").concat(this.id, \"\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-control text-center\\\" style=\\\"font-size: 0.875em;\\\" readonly>\\n <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"increment\\\" type=\\\"button\\\">+</button>\\n </div>\\n </div>\");\n var decrease = this.domNode.querySelector('[role=\"reduction\"]');\n var increase = this.domNode.querySelector('[role=\"increment\"]');\n var input = this.domNode.querySelector(\"#\".concat(this.id));\n var step = 1;\n var changeValue = function changeValue(delta) {\n var numeric = parseFloat(_this.value);\n if (isNaN(numeric)) numeric = 0;\n numeric = numeric + delta;\n numeric = Math.max(0, numeric);\n numeric = Math.round(numeric * 10) / 10;\n _this.setValue(numeric);\n };\n if (decrease) {\n decrease.addEventListener('click', function (e) {\n e.preventDefault();\n changeValue(-step);\n });\n }\n if (increase) {\n increase.addEventListener('click', function (e) {\n e.preventDefault();\n changeValue(step);\n });\n }\n\n // allow direct programmatic update keeping UI in sync\n this._inputNode = input;\n\n // normalize initial display\n // this.setValue(this.value === undefined ? 0 : this.value);\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n // Method to set value programmatically\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.value = newValue;\n var input = this.domNode.querySelector('input');\n if (input) {\n input.value = this.value;\n }\n\n // Support both function and object with setValue\n if (typeof this.callback === 'function') {\n this.callback(this.value);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(this.value);\n }\n }\n\n // Method to get current value\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LetterSpacingControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LetterSpacingControl.js?");
/***/ }),
/***/ "./src/includes/LineHeightControl.js":
/*!*******************************************!*\
!*** ./src/includes/LineHeightControl.js ***!
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar LineHeightControl = /*#__PURE__*/function () {\n function LineHeightControl(label, value, callback) {\n _classCallCheck(this, LineHeightControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = value;\n this.callback = callback;\n this.presets = [{\n name: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.line_1_2'),\n value: 1.2\n }, {\n name: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.line_1_5'),\n value: 1.5\n }, {\n name: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.line_1_8'),\n value: 1.8\n }, {\n name: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.line_2'),\n value: 2\n }];\n this.domNode = document.createElement(\"div\");\n this.render();\n }\n\n // Does the current value match one of the four preset buckets?\n return _createClass(LineHeightControl, [{\n key: \"_isPreset\",\n value: function _isPreset(v) {\n if (v === null || v === undefined || v === '') return false;\n return this.presets.some(function (p) {\n return String(p.value) === String(v);\n });\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this = this;\n // A preset is \"custom\" when the stored value is numeric but not one of\n // the four preset values. Empty/null → \"not set\".\n var isPresetValue = this._isPreset(this.value);\n var isCustomValue = this.value !== null && this.value !== undefined && this.value !== '' && !isPresetValue;\n var customValue = isCustomValue ? this.value : 1.5;\n var optionsHtml = [\"<option value=\\\"\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_weight.not_set'), \"</option>\")].concat(_toConsumableArray(this.presets.map(function (p) {\n var selected = String(p.value) === String(_this.value) ? ' selected' : '';\n return \"<option value=\\\"\".concat(p.value, \"\\\"\").concat(selected, \">\").concat(p.name, \"</option>\");\n })), [\"<option value=\\\"__custom__\\\"\".concat(isCustomValue ? ' selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.custom'), \"</option>\")]).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-select\\\">\\n <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"\\\" name=\\\"line-height\\\">\").concat(optionsHtml, \"</select>\\n <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n </div>\\n </div>\\n </div>\\n <div class=\\\"bjs-control-row bjs-line-height-custom\\\"\").concat(isCustomValue ? '' : ' hidden', \">\\n <div class=\\\"bjs-control-label\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.custom'), \"</span></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-number-input\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-action=\\\"dec\\\" aria-label=\\\"Decrease\\\">\\u2212</button>\\n <input type=\\\"number\\\" class=\\\"bjs-number-value\\\" step=\\\"0.1\\\" min=\\\"0.1\\\" max=\\\"10\\\" value=\\\"\").concat(customValue, \"\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-action=\\\"inc\\\" aria-label=\\\"Increase\\\">+</button>\\n </div>\\n </div>\\n </div>\\n \");\n this._bindEvents();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this2 = this;\n this.selectEl = this.domNode.querySelector('select');\n this.customRow = this.domNode.querySelector('.bjs-line-height-custom');\n this.numberInput = this.customRow.querySelector('input.bjs-number-value');\n var dec = this.customRow.querySelector('[data-action=\"dec\"]');\n var inc = this.customRow.querySelector('[data-action=\"inc\"]');\n this.selectEl.addEventListener('change', function (e) {\n var raw = e.target.value;\n if (raw === '__custom__') {\n _this2.customRow.hidden = false;\n _this2.value = parseFloat(_this2.numberInput.value) || 1.5;\n _this2._fireCallback(_this2.value);\n try {\n _this2.numberInput.focus();\n } catch (err) {}\n } else if (raw === '') {\n _this2.customRow.hidden = true;\n _this2.value = null;\n _this2._fireCallback(null);\n } else {\n _this2.customRow.hidden = true;\n _this2.value = parseFloat(raw);\n _this2._fireCallback(_this2.value);\n }\n });\n var commitNumber = function commitNumber() {\n var n = parseFloat(_this2.numberInput.value);\n if (isNaN(n)) n = 1.5;\n n = Math.max(0.1, Math.min(10, +n.toFixed(2)));\n _this2.numberInput.value = n;\n _this2.value = n;\n _this2._fireCallback(n);\n };\n this.numberInput.addEventListener('input', function () {\n var raw = _this2.numberInput.value;\n if (raw === '' || raw === '-') return;\n var n = parseFloat(raw);\n if (!isNaN(n)) {\n _this2.value = n;\n _this2._fireCallback(n);\n }\n });\n this.numberInput.addEventListener('blur', commitNumber);\n this.numberInput.addEventListener('keydown', function (e) {\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n _this2._step(+0.1);\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n _this2._step(-0.1);\n }\n });\n dec.addEventListener('click', function (e) {\n e.preventDefault();\n _this2._step(-0.1);\n });\n inc.addEventListener('click', function (e) {\n e.preventDefault();\n _this2._step(+0.1);\n });\n }\n }, {\n key: \"_step\",\n value: function _step(delta) {\n var n = parseFloat(this.numberInput.value) || 1.5;\n n = Math.max(0.1, Math.min(10, +(n + delta).toFixed(2)));\n this.numberInput.value = n;\n this.value = n;\n this._fireCallback(n);\n }\n }, {\n key: \"_fireCallback\",\n value: function _fireCallback(val) {\n if (typeof this.callback === 'function') {\n this.callback(val);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(val);\n }\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.value = newValue;\n this.render();\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LineHeightControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LineHeightControl.js?");
/***/ }),
/***/ "./src/includes/LinkColorControl.js":
/*!******************************************!*\
!*** ./src/includes/LinkColorControl.js ***!
\******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar LinkColorControl = /*#__PURE__*/function () {\n function LinkColorControl(label, value, callback) {\n _classCallCheck(this, LinkColorControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n // Initialize properties\n this.label = label; // Label for the text control\n this.value = value; // Initial /* left | center | right */\n this.callback = callback; // Callback function to handle input changes\n\n // Create the main container element\n this.domNode = document.createElement(\"div\");\n\n //\n this.render(); // Call the render method to create the UI\n }\n return _createClass(LinkColorControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n this.domNode.innerHTML = \"<div class=\\\"py-2 ps-3 pe-3 w-100 d-flex align-items-center justify-content-between\\\">\\n <label for=\\\"\".concat(this.id, \"\\\" class=\\\"form-label fw-semibold mb-0 me-3 small\\\">\").concat(this.label, \"</label>\\n\\n <div class=\\\"d-flex align-items-center border rounded p-1 ps-2 border-default\\\" style=\\\"gap:4px;min-width:140px; max-width:140px; max-height: 32px;\\\">\\n <input id=\\\"\").concat(this.id, \"_color\\\" type=\\\"color\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-control rounded form-control-color\\\">\\n <input id=\\\"\").concat(this.id, \"_hex\\\" type=\\\"text\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-control border-none text-center small\\\" style=\\\"height: 28px;font-size:0.875em !important;\\\" />\\n </div>\\n </div>\\n <style>\\n #\").concat(this.id, \"_color {\\n border: none;\\n padding: 0;\\n width: 31px;\\n height: 20px;\\n }\\n #\").concat(this.id, \"_hex {\\n border: none;\\n text-align: center;\\n }\\n </style>\\n \");\n\n // nodes\n this.colorInput = this.domNode.querySelector(\"#\".concat(this.id, \"_color\"));\n this.hexInput = this.domNode.querySelector(\"#\".concat(this.id, \"_hex\"));\n\n // sync handlers\n var notify = function notify(val) {\n _this.value = val;\n if (typeof _this.callback === \"function\") {\n _this.callback(val);\n } else if (_this.callback && typeof _this.callback.setValue === \"function\") {\n _this.callback.setValue(val);\n }\n };\n this.colorInput.addEventListener(\"input\", function (e) {\n var v = e.target.value;\n _this.hexInput.value = v;\n notify(v);\n });\n this.hexInput.addEventListener(\"change\", function (e) {\n var v = e.target.value.trim();\n if (!v.startsWith(\"#\")) v = \"#\" + v;\n // basic validation to 3/6 hex chars\n if (/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(v)) {\n _this.colorInput.value = v;\n _this.hexInput.value = v;\n notify(v);\n } else {\n // revert to last known good\n _this.hexInput.value = _this.value;\n }\n });\n\n // keep UI in sync if value was set programmatically before render\n // this.setValue(this.value);\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n // Method to set value programmatically\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.value = newValue;\n var input = this.domNode.querySelector(\"input\");\n if (input) {\n input.value = this.value;\n }\n\n // Support both function and object with setValue\n if (typeof this.callback === \"function\") {\n this.callback(this.value);\n } else if (this.callback && typeof this.callback.setValue === \"function\") {\n this.callback.setValue(this.value);\n }\n }\n\n // Method to get current value\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LinkColorControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LinkColorControl.js?");
/***/ }),
/***/ "./src/includes/LinkConfigControl.js":
/*!*******************************************!*\
!*** ./src/includes/LinkConfigControl.js ***!
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * LinkConfigControl — unified \"where does this click go?\" composite.\n *\n * Design decisions (Phase 2.9/2.10 — 2026-04-17):\n * - **Type-first UX**: user picks what kind of link (Web URL / Email /\n * Phone / Anchor) and the control shows type-appropriate fields.\n * Beats a bare URL field because `mailto:` / `tel:` / `#anchor` are\n * first-class CTAs, not URL variants users think in.\n * - **`rel=\"noopener noreferrer\"` auto-added** whenever `target=_blank`.\n * OWASP-recommended reverse-tabnabbing prevention — no user toggle, just\n * a correct default.\n * - **Advanced section collapsed by default**. Most links only need\n * URL + target + title. Power features (`rel=nofollow|sponsored|ugc`,\n * `download` filename) live in a `.bjs-group` expander.\n * - **Failure-state audit (§2.8 C)**: every URL/email/phone/anchor is\n * validated + errors surface via `.bjs-text-input.is-error` +\n * `.bjs-link-error`.\n * - **Uniform sidebar edges (§Composition rule #6)**: every child is a\n * top-level `.bjs-*` primitive in a bare `<div>` wrapper — no double\n * padding from an outer `.bjs-control-stack`.\n *\n * Shared by ButtonElement + LinkElement (+ callable by any future element\n * with a link action — ImageElement's existing LinkInputControl is a\n * simpler ancestor of this one).\n *\n * Constructor: `new LinkConfigControl(label, values, callback)`\n * label — control section header (e.g. \"Link\")\n * values — { url, target, rel, title, download }\n * (no `type` — derived from url pattern on mount; user can\n * switch type via dropdown to get type-specific fields)\n * callback — { setLink: ({url, target, rel, title, download}) => void }\n * fires whenever ANY field changes, after validation passes.\n * Caller stores these on the element (not formatter) —\n * they're link semantics, not visual styles.\n */\nvar LinkConfigControl = /*#__PURE__*/function () {\n function LinkConfigControl(label, values, callback, caps) {\n var _this = this;\n _classCallCheck(this, LinkConfigControl);\n this.id = '_lc_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.callback = callback || {};\n\n // Seed state from incoming values (+ derive type from URL pattern)\n var _ref = values || {},\n url = _ref.url,\n target = _ref.target,\n rel = _ref.rel,\n title = _ref.title,\n download = _ref.download,\n ariaLabel = _ref.ariaLabel;\n this.state = {\n url: url || '',\n target: target || '',\n // '' | '_blank'\n title: title || '',\n download: download || '',\n // W4.3 — a11y-critical. Rendered as <a aria-label=\"…\">; consumers\n // set it when the visible link text doesn't convey the action\n // (e.g. icon-only link, \"Click here\"-style CTA).\n ariaLabel: ariaLabel || '',\n relFlags: this._parseUserRelFlags(rel || ''),\n // W4.3 — UTM builder state. Seeded from URL query params on\n // _hydrateFieldsFromUrl; rebuilt into the URL on _buildUrlForType.\n utm: {\n source: '',\n medium: '',\n campaign: '',\n term: '',\n content: ''\n }\n };\n this.state.type = this._deriveType(this.state.url);\n // Split fields derived from URL for editing per type\n this._hydrateFieldsFromUrl();\n\n // Dual-view sync — Phase 1.8 capability tokens (SA I13).\n // `caps.subscribe(fn)` registers us with the element; `caps.readState()`\n // returns fresh { url, target, rel, title, download }. Fires whenever\n // the element mutates link state via ANY surface (sidebar, popover,\n // programmatic). Idempotent: setValue just re-hydrates state — if the\n // payload matches the currently-rendered state, the render() is still\n // cheap (no external ref replacement, user caret lives inside the\n // newly-built inputs so focus is preserved across edits from OTHER\n // surfaces but not from keystrokes inside this control — those go\n // through our own debounced input handler, never through the sync path).\n if (caps && typeof caps.subscribe === 'function' && typeof caps.readState === 'function') {\n this._readState = caps.readState;\n this._disposeSync = caps.subscribe(function () {\n return _this._syncFromExternal();\n });\n }\n this.domNode = document.createElement('div');\n this.render();\n }\n\n /** Idempotent re-hydrate triggered by element.notifySyncListeners().\n * MUST NOT fire `_commit` (would ping back → infinite loop). */\n return _createClass(LinkConfigControl, [{\n key: \"_syncFromExternal\",\n value: function _syncFromExternal() {\n if (!this._readState) return;\n var next = this._readState() || {};\n var same = next.url === this.state.url && next.target === this.state.target && next.title === this.state.title && next.download === this.state.download && (next.ariaLabel || '') === (this.state.ariaLabel || '');\n if (same) return; // idempotent no-op (SA I13a)\n this._muteCommit = true;\n try {\n this.setValue(next);\n } finally {\n this._muteCommit = false;\n }\n }\n\n /** Called by Builder.renderElementControls at control-swap time (SA I14).\n * Disposer is required — leaking subscriptions into orphaned controls\n * leads to phantom writes into panels that no longer exist (SA I13c). */\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this._disposeSync) {\n try {\n this._disposeSync();\n } catch (_) {/* no-op */}\n this._disposeSync = null;\n }\n this._readState = null;\n }\n\n // ─── URL parsing / building ─────────────────────────────────────────\n }, {\n key: \"_deriveType\",\n value: function _deriveType(url) {\n if (!url) return 'web';\n var s = url.trim();\n if (/^mailto:/i.test(s)) return 'email';\n if (/^tel:/i.test(s)) return 'phone';\n // A bare `#` (common default-placeholder for \"no link yet\") counts\n // as empty/web, not anchor. Only `#some-id` is a real anchor link.\n if (/^#.+/.test(s)) return 'anchor';\n return 'web';\n }\n }, {\n key: \"_hydrateFieldsFromUrl\",\n value: function _hydrateFieldsFromUrl() {\n var _this$state = this.state,\n url = _this$state.url,\n type = _this$state.type;\n // Defaults for each type's edit fields. Treat a bare `#` (common\n // \"no link yet\" placeholder in legacy button samples) as empty —\n // avoids tripping web-URL validation on the first panel open.\n var webSeed = type === 'web' && url !== '#' ? url : '';\n this.state.web = {\n url: webSeed\n };\n this.state.email = {\n to: '',\n subject: '',\n body: ''\n };\n this.state.phone = {\n number: ''\n };\n this.state.anchor = {\n id: ''\n };\n // Reset UTM state from scratch every hydrate — the \"seed fields\n // from URL\" contract owns the whole state for this type.\n this.state.utm = {\n source: '',\n medium: '',\n campaign: '',\n term: '',\n content: ''\n };\n if (type === 'web' && webSeed) {\n // W4.3 UTM — extract utm_* params from the web URL. Leave the\n // URL's displayed value with the params still in it (user\n // expects to see the full URL they pasted); the UTM fields\n // mirror them. When the user edits either surface, _buildUrl\n // rebuilds the URL from base + UTM state at commit time.\n var qIdx = webSeed.indexOf('?');\n if (qIdx !== -1) {\n try {\n var params = new URLSearchParams(webSeed.slice(qIdx + 1));\n var utmSource = params.get('utm_source');\n var utmMedium = params.get('utm_medium');\n var utmCampaign = params.get('utm_campaign');\n var utmTerm = params.get('utm_term');\n var utmContent = params.get('utm_content');\n if (utmSource) this.state.utm.source = utmSource;\n if (utmMedium) this.state.utm.medium = utmMedium;\n if (utmCampaign) this.state.utm.campaign = utmCampaign;\n if (utmTerm) this.state.utm.term = utmTerm;\n if (utmContent) this.state.utm.content = utmContent;\n } catch (_) {/* malformed query — leave UTM empty */}\n }\n } else if (type === 'email' && url) {\n var m = url.match(/^mailto:([^?]*)(?:\\?(.*))?$/i);\n if (m) {\n this.state.email.to = m[1] || '';\n if (m[2]) {\n var _params = new URLSearchParams(m[2]);\n this.state.email.subject = _params.get('subject') || '';\n this.state.email.body = _params.get('body') || '';\n }\n }\n } else if (type === 'phone' && url) {\n this.state.phone.number = url.replace(/^tel:/i, '');\n } else if (type === 'anchor' && url) {\n this.state.anchor.id = url.replace(/^#/, '');\n }\n }\n }, {\n key: \"_buildUrlForType\",\n value: function _buildUrlForType() {\n switch (this.state.type) {\n case 'web':\n return this._buildWebUrlWithUtm();\n case 'email':\n {\n var _this$state$email = this.state.email,\n to = _this$state$email.to,\n subject = _this$state$email.subject,\n body = _this$state$email.body;\n if (!to) return '';\n var params = new URLSearchParams();\n if (subject) params.set('subject', subject);\n if (body) params.set('body', body);\n var qs = params.toString();\n return 'mailto:' + to + (qs ? '?' + qs : '');\n }\n case 'phone':\n {\n var n = this.state.phone.number.trim();\n return n ? 'tel:' + n.replace(/\\s+/g, '') : '';\n }\n case 'anchor':\n {\n var id = this.state.anchor.id.trim().replace(/^#/, '');\n return id ? '#' + id : '';\n }\n }\n return '';\n }\n\n /**\n * W4.3 — rebuild a web URL with UTM params merged in. Strips any\n * existing utm_* params from the base URL (so the user's UTM fields\n * are the single source of truth) + appends only the UTM fields that\n * are non-empty. Preserves every OTHER existing query param (e.g.\n * `?ref=newsletter` stays; `?utm_source=old` gets overwritten by the\n * UTM field's current value if set, or dropped entirely if empty).\n */\n }, {\n key: \"_buildWebUrlWithUtm\",\n value: function _buildWebUrlWithUtm() {\n var raw = this.state.web && this.state.web.url || '';\n if (!raw) return '';\n var utm = this.state.utm || {};\n var utmEntries = Object.entries({\n utm_source: utm.source,\n utm_medium: utm.medium,\n utm_campaign: utm.campaign,\n utm_term: utm.term,\n utm_content: utm.content\n }).filter(function (_ref2) {\n var _ref3 = _slicedToArray(_ref2, 2),\n v = _ref3[1];\n return v && String(v).trim();\n });\n\n // If no UTM fields AND no utm_* in raw URL, short-circuit.\n var qIdx = raw.indexOf('?');\n var hashIdx = raw.indexOf('#');\n var basePart = raw;\n var queryPart = '';\n var hashPart = '';\n if (hashIdx !== -1) {\n hashPart = raw.slice(hashIdx);\n basePart = raw.slice(0, hashIdx);\n }\n var bQIdx = basePart.indexOf('?');\n if (bQIdx !== -1) {\n queryPart = basePart.slice(bQIdx + 1);\n basePart = basePart.slice(0, bQIdx);\n }\n\n // Strip existing utm_* from the query (the UTM state is authoritative).\n var params;\n try {\n params = new URLSearchParams(queryPart);\n } catch (_) {\n params = new URLSearchParams();\n }\n for (var _i = 0, _arr = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']; _i < _arr.length; _i++) {\n var key = _arr[_i];\n params[\"delete\"](key);\n }\n // Append UTM fields that are non-empty.\n var _iterator = _createForOfIteratorHelper(utmEntries),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var _step$value = _slicedToArray(_step.value, 2),\n _key = _step$value[0],\n value = _step$value[1];\n params.set(_key, String(value).trim());\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n var qs = params.toString();\n return basePart + (qs ? '?' + qs : '') + hashPart;\n }\n\n /** Returns true if any UTM field is populated. Drives the \"Clear UTM\"\n * button visibility + the UTM summary chip. */\n }, {\n key: \"_hasUtm\",\n value: function _hasUtm() {\n var u = this.state.utm || {};\n return !!(u.source || u.medium || u.campaign || u.term || u.content);\n }\n\n // ─── Rel handling ───────────────────────────────────────────────────\n\n // User-toggleable rel flags. Security flags (`noopener`, `noreferrer`)\n // are NOT in this list — they auto-attach whenever `target=_blank`\n // per OWASP reverse-tabnabbing guidance, and making them user-\n // toggleable would let a user accidentally disable them. Keep the\n // auto-path as the single source of truth.\n //\n // W4.3 (2026-04-24) — extended from 3 to 5: added `bookmark` (signal\n // the link is a permalink to a section anchor, useful for docs /\n // TOC-style UIs) + `author` (the link points to the author's page,\n // common on bylines + pull-quotes).\n }, {\n key: \"_parseUserRelFlags\",\n value: function _parseUserRelFlags(rel) {\n var tokens = rel.toLowerCase().split(/\\s+/).filter(Boolean);\n return LinkConfigControl.USER_REL_FLAGS.filter(function (f) {\n return tokens.includes(f);\n });\n }\n }, {\n key: \"_computeRel\",\n value: function _computeRel() {\n // User-toggled + auto-security (noopener noreferrer when _blank)\n var auto = this.state.type === 'web' && this.state.target === '_blank' ? ['noopener', 'noreferrer'] : [];\n var all = [].concat(_toConsumableArray(this.state.relFlags), auto);\n return all.join(' ').trim();\n }\n\n // ─── Validation ─────────────────────────────────────────────────────\n }, {\n key: \"_validate\",\n value: function _validate() {\n var errors = {};\n var s = this.state;\n if (s.type === 'web') {\n var v = s.web.url.trim();\n if (v && !/^(https?:\\/\\/|\\/|\\.{0,2}\\/|blob:|data:)/i.test(v)) {\n errors.web = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.err_web_url');\n }\n } else if (s.type === 'email') {\n var _v = s.email.to.trim();\n if (_v && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(_v)) {\n errors.email = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.err_email');\n }\n } else if (s.type === 'phone') {\n var _v2 = s.phone.number.trim();\n if (_v2 && !/^[+()\\d\\s-]+$/.test(_v2)) {\n errors.phone = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.err_phone');\n }\n } else if (s.type === 'anchor') {\n var _v3 = s.anchor.id.trim();\n if (_v3 && !/^[A-Za-z][\\w-]*$/.test(_v3.replace(/^#/, ''))) {\n errors.anchor = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.err_anchor');\n }\n }\n return errors;\n }\n\n // ─── Fire callback ──────────────────────────────────────────────────\n }, {\n key: \"_commit\",\n value: function _commit() {\n if (this._muteCommit) return; // suppress during _syncFromExternal\n var errors = this._validate();\n this._renderErrors(errors);\n if (Object.keys(errors).length > 0) return; // swallow — don't propagate bad state\n\n var url = this._buildUrlForType();\n this.state.url = url;\n var rel = this._computeRel();\n this._renderAutoRelHint();\n var payload = {\n url: url,\n target: this.state.type === 'web' ? this.state.target : '',\n // target only meaningful for web\n rel: rel,\n title: this.state.title,\n download: this.state.download,\n // W4.3 — optional a11y override. Consumers apply as `aria-label`\n // on the rendered `<a>`; empty string means \"let the visible\n // link text provide the label\" (browser default).\n ariaLabel: this.state.ariaLabel || ''\n };\n if (typeof this.callback.setLink === 'function') this.callback.setLink(payload);else if (typeof this.callback === 'function') this.callback(payload);\n }\n\n // ─── Render ─────────────────────────────────────────────────────────\n }, {\n key: \"render\",\n value: function render() {\n var _this2 = this;\n var t = this.state.type;\n var relHtml = LinkConfigControl.USER_REL_FLAGS.map(function (flag) {\n return \"\\n <label class=\\\"bjs-checkbox\\\" data-rel-label=\\\"\".concat(flag, \"\\\">\\n <input type=\\\"checkbox\\\" class=\\\"bjs-checkbox-input\\\" value=\\\"\").concat(flag, \"\\\" \").concat(_this2.state.relFlags.includes(flag) ? 'checked' : '', \">\\n <span class=\\\"bjs-checkbox-box\\\" aria-hidden=\\\"true\\\"></span>\\n <span>\").concat(flag, \"</span>\\n </label>\\n \");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-info-banner\\\" role=\\\"note\\\">\\n <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">link</span>\\n <span class=\\\"bjs-info-banner-text\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.banner'), \"</span>\\n </div>\\n\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_type\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.type'), \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-select\\\">\\n <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"_type\\\" data-control=\\\"type\\\">\\n <option value=\\\"web\\\" \").concat(t === 'web' ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.type_web'), \"</option>\\n <option value=\\\"email\\\" \").concat(t === 'email' ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.type_email'), \"</option>\\n <option value=\\\"phone\\\" \").concat(t === 'phone' ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.type_phone'), \"</option>\\n <option value=\\\"anchor\\\" \").concat(t === 'anchor' ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.type_anchor'), \"</option>\\n </select>\\n <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n </div>\\n </div>\\n </div>\\n\\n <!-- WEB -->\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"web\\\" \").concat(t === 'web' ? '' : 'hidden', \">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_web\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.url'), \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-link-input\\\">\\n <input type=\\\"url\\\"\\n id=\\\"\").concat(this.id, \"_web\\\"\\n data-field=\\\"web.url\\\"\\n class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.url_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.web.url), \"\\\"\\n autocomplete=\\\"url\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"clear-web\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.clear'), \"\\\"\\n \").concat(this.state.web.url ? '' : 'hidden', \">\\n <span class=\\\"material-symbols-rounded\\\">close</span>\\n </button>\\n </div>\\n <span class=\\\"bjs-link-error\\\" data-error=\\\"web\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n </div>\\n </div>\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"web\\\" \").concat(t === 'web' ? '' : 'hidden', \">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_target\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.target'), \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-select\\\">\\n <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"_target\\\" data-control=\\\"target\\\">\\n <option value=\\\"\\\" \").concat(!this.state.target ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.target_self'), \"</option>\\n <option value=\\\"_blank\\\" \").concat(this.state.target === '_blank' ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.target_blank'), \"</option>\\n </select>\\n <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n </div>\\n </div>\\n </div>\\n\\n <!-- EMAIL -->\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"email\\\" \").concat(t === 'email' ? '' : 'hidden', \">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_email_to\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.email_to'), \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"email\\\" id=\\\"\").concat(this.id, \"_email_to\\\" data-field=\\\"email.to\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.email_to_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.email.to), \"\\\">\\n <span class=\\\"bjs-link-error\\\" data-error=\\\"email\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n </div>\\n </div>\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"email\\\" \").concat(t === 'email' ? '' : 'hidden', \">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_email_subject\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.email_subject'), \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_email_subject\\\" data-field=\\\"email.subject\\\" class=\\\"bjs-text-input\\\"\\n value=\\\"\").concat(this._escAttr(this.state.email.subject), \"\\\">\\n </div>\\n </div>\\n <div class=\\\"bjs-control-stack\\\" data-type-view=\\\"email\\\" \").concat(t === 'email' ? '' : 'hidden', \">\\n <label class=\\\"bjs-control-label\\\" for=\\\"\").concat(this.id, \"_email_body\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.email_body'), \"</span></label>\\n <div class=\\\"bjs-control-input\\\">\\n <textarea id=\\\"\").concat(this.id, \"_email_body\\\" data-field=\\\"email.body\\\" class=\\\"bjs-textarea\\\" rows=\\\"3\\\">\").concat(this._escAttr(this.state.email.body), \"</textarea>\\n </div>\\n </div>\\n\\n <!-- PHONE -->\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"phone\\\" \").concat(t === 'phone' ? '' : 'hidden', \">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_phone\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.phone_number'), \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"tel\\\" id=\\\"\").concat(this.id, \"_phone\\\" data-field=\\\"phone.number\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.phone_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.phone.number), \"\\\">\\n <span class=\\\"bjs-link-error\\\" data-error=\\\"phone\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n </div>\\n </div>\\n\\n <!-- ANCHOR -->\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"anchor\\\" \").concat(t === 'anchor' ? '' : 'hidden', \">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_anchor\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.anchor_id'), \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_anchor\\\" data-field=\\\"anchor.id\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.anchor_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.anchor.id), \"\\\">\\n <span class=\\\"bjs-link-error\\\" data-error=\\\"anchor\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n </div>\\n </div>\\n\\n <!-- TITLE (always visible) -->\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_title\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.title'), \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_title\\\" data-field=\\\"title\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.title_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.title), \"\\\">\\n </div>\\n </div>\\n\\n <!-- ARIA-LABEL (always visible \\u2014 W4.3) -->\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_aria\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.aria_label'), \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_aria\\\" data-field=\\\"ariaLabel\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.aria_label_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.ariaLabel || ''), \"\\\">\\n </div>\\n </div>\\n\\n <!-- AUTO-REL HINT (only when target=_blank) -->\\n <div class=\\\"bjs-info-banner bjs-info-banner--success bjs-link-auto-rel\\\"\\n \").concat(this.state.type === 'web' && this.state.target === '_blank' ? '' : 'hidden', \">\\n <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">shield</span>\\n <span class=\\\"bjs-info-banner-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.auto_rel_notice'), \"</span>\\n </div>\\n\\n <!-- ADVANCED (collapsed by default) -->\\n <div class=\\\"bjs-group is-collapsed\\\" data-group=\\\"advanced\\\">\\n <div class=\\\"bjs-group-header\\\" role=\\\"button\\\" tabindex=\\\"0\\\" aria-expanded=\\\"false\\\">\\n <div>\\n <span class=\\\"bjs-group-header-title\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.advanced'), \"</span>\\n <span class=\\\"bjs-group-header-desc\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.advanced_desc'), \"</span>\\n </div>\\n <span class=\\\"material-symbols-rounded bjs-group-header-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n </div>\\n <div class=\\\"bjs-group-body\\\">\\n <div class=\\\"bjs-control-stack\\\">\\n <label class=\\\"bjs-control-label\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.rel'), \"</span></label>\\n <div class=\\\"bjs-control-input\\\" style=\\\"flex-direction: column; align-items: stretch; gap: var(--bjs-space-2);\\\">\\n \").concat(relHtml, \"\\n </div>\\n </div>\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\">\\n <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_dl\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.download'), \"</span></label></div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_dl\\\" data-field=\\\"download\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.download_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.download), \"\\\">\\n </div>\\n </div>\\n\\n <!-- UTM BUILDER (web-only, W4.3) -->\\n \").concat(t === 'web' ? \"\\n <div class=\\\"bjs-control-stack bjs-link-utm\\\" data-group=\\\"utm\\\">\\n <label class=\\\"bjs-control-label\\\" style=\\\"display:flex; align-items:center; justify-content:space-between;\\\">\\n <span>\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm'), \"</span>\\n <button type=\\\"button\\\" class=\\\"bjs-btn bjs-btn--ghost bjs-link-utm-clear\\\"\\n data-control=\\\"utm-clear\\\"\\n \").concat(this._hasUtm() ? '' : 'hidden', \"\\n style=\\\"font-size:11px; padding:2px 8px;\\\">\\n \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_clear'), \"\\n </button>\\n </label>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_utm_source\\\" data-field=\\\"utm.source\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_source_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.utm.source), \"\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_source_placeholder'), \"\\\">\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_utm_medium\\\" data-field=\\\"utm.medium\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_medium_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.utm.medium), \"\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_medium_placeholder'), \"\\\">\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_utm_campaign\\\" data-field=\\\"utm.campaign\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_campaign_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.utm.campaign), \"\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_campaign_placeholder'), \"\\\">\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_utm_term\\\" data-field=\\\"utm.term\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_term_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.utm.term), \"\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_term_placeholder'), \"\\\">\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_utm_content\\\" data-field=\\\"utm.content\\\" class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_content_placeholder'), \"\\\"\\n value=\\\"\").concat(this._escAttr(this.state.utm.content), \"\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_content_placeholder'), \"\\\">\\n </div>\\n </div>\\n \") : '', \"\\n </div>\\n </div>\\n \");\n this._bindEvents();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this3 = this;\n var root = this.domNode;\n\n // Type change → swap views\n root.querySelector('[data-control=\"type\"]').addEventListener('change', function (e) {\n _this3.state.type = e.target.value;\n // Re-render so per-type fields swap; preserve existing state\n _this3.render();\n _this3._commit();\n });\n\n // Target change\n var targetSel = root.querySelector('[data-control=\"target\"]');\n if (targetSel) {\n targetSel.addEventListener('change', function (e) {\n _this3.state.target = e.target.value;\n _this3._commit();\n });\n }\n\n // Per-field inputs (debounced onInput + commit onBlur)\n this._wireFieldInput(root, 'input[data-field=\"web.url\"]', function (v) {\n _this3.state.web.url = v;\n }, true);\n this._wireFieldInput(root, 'input[data-field=\"email.to\"]', function (v) {\n _this3.state.email.to = v;\n }, true);\n this._wireFieldInput(root, 'input[data-field=\"email.subject\"]', function (v) {\n _this3.state.email.subject = v;\n });\n this._wireFieldInput(root, 'textarea[data-field=\"email.body\"]', function (v) {\n _this3.state.email.body = v;\n });\n this._wireFieldInput(root, 'input[data-field=\"phone.number\"]', function (v) {\n _this3.state.phone.number = v;\n }, true);\n this._wireFieldInput(root, 'input[data-field=\"anchor.id\"]', function (v) {\n _this3.state.anchor.id = v;\n }, true);\n this._wireFieldInput(root, 'input[data-field=\"title\"]', function (v) {\n _this3.state.title = v;\n });\n this._wireFieldInput(root, 'input[data-field=\"download\"]', function (v) {\n _this3.state.download = v;\n });\n this._wireFieldInput(root, 'input[data-field=\"ariaLabel\"]', function (v) {\n _this3.state.ariaLabel = v;\n });\n\n // W4.3 — UTM builder fields (web-only, present in DOM only when\n // type === 'web'). Debounced commit via _wireFieldInput rebuilds\n // the web URL with utm_* params merged via _buildWebUrlWithUtm.\n this._wireFieldInput(root, 'input[data-field=\"utm.source\"]', function (v) {\n _this3.state.utm.source = v;\n _this3._toggleUtmClearBtn();\n });\n this._wireFieldInput(root, 'input[data-field=\"utm.medium\"]', function (v) {\n _this3.state.utm.medium = v;\n _this3._toggleUtmClearBtn();\n });\n this._wireFieldInput(root, 'input[data-field=\"utm.campaign\"]', function (v) {\n _this3.state.utm.campaign = v;\n _this3._toggleUtmClearBtn();\n });\n this._wireFieldInput(root, 'input[data-field=\"utm.term\"]', function (v) {\n _this3.state.utm.term = v;\n _this3._toggleUtmClearBtn();\n });\n this._wireFieldInput(root, 'input[data-field=\"utm.content\"]', function (v) {\n _this3.state.utm.content = v;\n _this3._toggleUtmClearBtn();\n });\n\n // W4.3 — \"Clear UTM\" button wipes all 5 UTM fields + rebuilds URL\n // without utm_* params. Commits immediately (not debounced) since\n // the action is explicit.\n var utmClear = root.querySelector('[data-control=\"utm-clear\"]');\n if (utmClear) {\n utmClear.addEventListener('click', function () {\n _this3.state.utm = {\n source: '',\n medium: '',\n campaign: '',\n term: '',\n content: ''\n };\n // Clear visible inputs so the user sees state reset immediately.\n ['source', 'medium', 'campaign', 'term', 'content'].forEach(function (k) {\n var inp = root.querySelector(\"input[data-field=\\\"utm.\".concat(k, \"\\\"]\"));\n if (inp) inp.value = '';\n });\n utmClear.setAttribute('hidden', '');\n _this3._commit();\n });\n }\n\n // Clear web URL\n var clearWeb = root.querySelector('[data-control=\"clear-web\"]');\n if (clearWeb) {\n clearWeb.addEventListener('click', function () {\n var inp = root.querySelector('input[data-field=\"web.url\"]');\n if (inp) inp.value = '';\n _this3.state.web.url = '';\n clearWeb.setAttribute('hidden', '');\n _this3._commit();\n });\n }\n\n // Rel checkboxes\n root.querySelectorAll('[data-rel-label] input[type=\"checkbox\"]').forEach(function (cb) {\n cb.addEventListener('change', function () {\n var flag = cb.value;\n var idx = _this3.state.relFlags.indexOf(flag);\n if (cb.checked && idx === -1) _this3.state.relFlags.push(flag);\n if (!cb.checked && idx !== -1) _this3.state.relFlags.splice(idx, 1);\n _this3._commit();\n });\n });\n\n // Advanced group collapse toggle\n var group = root.querySelector('[data-group=\"advanced\"]');\n if (group) {\n var header = group.querySelector('.bjs-group-header');\n var toggle = function toggle() {\n group.classList.toggle('is-collapsed');\n header.setAttribute('aria-expanded', (!group.classList.contains('is-collapsed')).toString());\n };\n header.addEventListener('click', toggle);\n header.addEventListener('keydown', function (e) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggle();\n }\n });\n }\n }\n }, {\n key: \"_wireFieldInput\",\n value: function _wireFieldInput(root, selector, apply) {\n var _this4 = this;\n var alsoClearErrorOnInput = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n var el = root.querySelector(selector);\n if (!el) return;\n var debounceId = null;\n var commit = function commit() {\n if (debounceId) clearTimeout(debounceId);\n debounceId = null;\n _this4._commit();\n };\n el.addEventListener('input', function () {\n apply(el.value);\n if (alsoClearErrorOnInput) {\n el.classList.remove('is-error');\n var errType = el.dataset.field.split('.')[0];\n var errSpan = root.querySelector(\"[data-error=\\\"\".concat(errType, \"\\\"]\"));\n if (errSpan) errSpan.textContent = '';\n }\n if (debounceId) clearTimeout(debounceId);\n debounceId = setTimeout(commit, 350);\n\n // Toggle clear button visibility for web URL\n if (el.dataset.field === 'web.url') {\n var clr = root.querySelector('[data-control=\"clear-web\"]');\n if (clr) {\n if (el.value) clr.removeAttribute('hidden');else clr.setAttribute('hidden', '');\n }\n }\n });\n el.addEventListener('blur', commit);\n }\n }, {\n key: \"_renderErrors\",\n value: function _renderErrors(errors) {\n var _this5 = this;\n ['web', 'email', 'phone', 'anchor'].forEach(function (kind) {\n var input = _this5.domNode.querySelector(\"[data-field^=\\\"\".concat(kind, \"\\\"]\"));\n var errSpan = _this5.domNode.querySelector(\"[data-error=\\\"\".concat(kind, \"\\\"]\"));\n if (!input || !errSpan) return;\n if (errors[kind]) {\n input.classList.add('is-error');\n errSpan.textContent = errors[kind];\n } else {\n input.classList.remove('is-error');\n errSpan.textContent = '';\n }\n });\n }\n }, {\n key: \"_renderAutoRelHint\",\n value: function _renderAutoRelHint() {\n var hint = this.domNode.querySelector('.bjs-link-auto-rel');\n if (!hint) return;\n var show = this.state.type === 'web' && this.state.target === '_blank';\n if (show) hint.removeAttribute('hidden');else hint.setAttribute('hidden', '');\n }\n\n /** W4.3 — keep the \"Clear UTM\" button visible only while UTM state\n * is non-empty. Called on every UTM field input. */\n }, {\n key: \"_toggleUtmClearBtn\",\n value: function _toggleUtmClearBtn() {\n var btn = this.domNode.querySelector('[data-control=\"utm-clear\"]');\n if (!btn) return;\n if (this._hasUtm()) btn.removeAttribute('hidden');else btn.setAttribute('hidden', '');\n }\n }, {\n key: \"_escAttr\",\n value: function _escAttr(s) {\n return String(s !== null && s !== void 0 ? s : '').replace(/\"/g, '"');\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n // Called by element when data changes from outside\n }, {\n key: \"setValue\",\n value: function setValue(values) {\n var _ref4 = values || {},\n url = _ref4.url,\n target = _ref4.target,\n rel = _ref4.rel,\n title = _ref4.title,\n download = _ref4.download,\n ariaLabel = _ref4.ariaLabel;\n this.state.url = url || '';\n this.state.target = target || '';\n this.state.title = title || '';\n this.state.download = download || '';\n this.state.ariaLabel = ariaLabel || '';\n this.state.relFlags = this._parseUserRelFlags(rel || '');\n this.state.type = this._deriveType(this.state.url);\n this._hydrateFieldsFromUrl();\n this.render();\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return {\n url: this._buildUrlForType(),\n target: this.state.type === 'web' ? this.state.target : '',\n rel: this._computeRel(),\n title: this.state.title,\n download: this.state.download,\n ariaLabel: this.state.ariaLabel || ''\n };\n }\n }]);\n}();\n_defineProperty(LinkConfigControl, \"USER_REL_FLAGS\", ['nofollow', 'sponsored', 'ugc', 'bookmark', 'author']);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LinkConfigControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LinkConfigControl.js?");
/***/ }),
/***/ "./src/includes/LinkElement.js":
/*!*************************************!*\
!*** ./src/includes/LinkElement.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./LinkConfigControl.js */ \"./src/includes/LinkConfigControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\nvar LinkElement = /*#__PURE__*/function (_BaseElement) {\n function LinkElement(template, text, url) {\n var _this;\n _classCallCheck(this, LinkElement);\n _this = _callSuper(this, LinkElement);\n _this.template = template;\n _this.text = text;\n // Link semantics — same shape as ButtonElement. Stored on the\n // element, not the formatter (attribute-level, not visual).\n _this.url = url || '';\n _this.target = '';\n _this.rel = '';\n _this.title = '';\n _this.download = '';\n // W4.3 — optional a11y override for assistive tech. Serialized\n // in getData + applied via `applyLinkAttrs` as `aria-label`.\n _this.ariaLabel = '';\n _this.domNode = null;\n _this.requiredTemplateKeys = ['url'];\n\n // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n _this.registerInlineEdit('text');\n _this.formatter = new Formatter({\n font_family: null,\n font_weight: null,\n font_size: null,\n text_color: null,\n link_color: null,\n paragraph_spacing: null,\n text_align: null,\n line_height: null,\n letter_spacing: null,\n text_direction: null,\n text_decoration: null\n });\n return _this;\n }\n _inherits(LinkElement, _BaseElement);\n return _createClass(LinkElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.link');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter + text auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n url: this.url || '#',\n target: this.target,\n rel: this.rel,\n title: this.title,\n download: this.download\n });\n }\n }, {\n key: \"applyFormatStyles\",\n value: function applyFormatStyles() {\n if (!this.domNode) {\n this.render();\n return;\n }\n var a = this.domNode.querySelector('a');\n if (!a) {\n this.render();\n return;\n }\n a.setAttribute('style', \"display: block;\".concat(this.formatter.toStyleStringAll()));\n }\n }, {\n key: \"applyLinkAttrs\",\n value: function applyLinkAttrs() {\n if (!this.domNode) {\n this.render();\n return;\n }\n var a = this.domNode.querySelector('a');\n if (!a) {\n this.render();\n return;\n }\n a.setAttribute('href', this.url || '#');\n if (this.target) a.setAttribute('target', this.target);else a.removeAttribute('target');\n if (this.rel) a.setAttribute('rel', this.rel);else a.removeAttribute('rel');\n if (this.title) a.setAttribute('title', this.title);else a.removeAttribute('title');\n if (this.download) a.setAttribute('download', this.download);else a.removeAttribute('download');\n if (this.ariaLabel) a.setAttribute('aria-label', this.ariaLabel);else a.removeAttribute('aria-label');\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(LinkElement, \"getData\", this, 3)([])), {}, {\n text: this.text,\n url: this.url,\n target: this.target,\n rel: this.rel,\n title: this.title,\n download: this.download,\n ariaLabel: this.ariaLabel\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this,\n _this$host;\n var setFmt = function setFmt(key) {\n return function (value) {\n _this2.formatter.setFormat(key, value);\n _this2.applyFormatStyles();\n };\n };\n // W3.1 — bus wiring for dual-view sync with FontPopoverOverlay.\n var busOpts = function busOpts(key) {\n var _this2$host;\n return {\n bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n elementUid: _this2.id,\n formatterKey: key\n };\n };\n return [new TextControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text'), this.text, {\n setText: function setText(text) {\n _this2.text = text;\n var a = _this2.domNode && _this2.domNode.querySelector('a');\n if (a) a.innerHTML = text;else _this2.render();\n }\n }), new _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link'), {\n url: this.url,\n target: this.target,\n rel: this.rel,\n title: this.title,\n download: this.download,\n ariaLabel: this.ariaLabel\n }, {\n setLink: function setLink(_ref) {\n var url = _ref.url,\n target = _ref.target,\n rel = _ref.rel,\n title = _ref.title,\n download = _ref.download,\n ariaLabel = _ref.ariaLabel;\n _this2.url = url || '';\n _this2.target = target || '';\n _this2.rel = rel || '';\n _this2.title = title || '';\n _this2.download = download || '';\n _this2.ariaLabel = ariaLabel || '';\n _this2.applyLinkAttrs();\n }\n }), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n setValue: setFmt('font_family')\n }, busOpts('font_family')), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n setValue: setFmt('font_weight')\n }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n setValue: setFmt('font_size')\n }, _objectSpread({\n defaultValue: 16,\n minValue: 8,\n maxValue: 72,\n suffix: 'px',\n allowZero: false\n }, busOpts('font_size'))), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n setValue: setFmt('text_color')\n }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n setValue: setFmt('link_color')\n }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('text_align'), {\n setValue: setFmt('text_align')\n }, ['left', 'justify', 'center', 'right'], {\n bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n elementUid: this.id,\n formatterKey: 'text_align'\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n setValue: setFmt('paragraph_spacing')\n }, {\n defaultValue: 0,\n minValue: 0,\n maxValue: 50,\n suffix: 'px',\n allowZero: true\n }), new _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n setValue: setFmt('line_height')\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n setValue: setFmt('letter_spacing')\n }, {\n defaultValue: 0,\n minValue: -5,\n maxValue: 10,\n step: 0.1,\n suffix: 'px',\n allowZero: true,\n allowNegative: true\n }), new _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n setValue: setFmt('text_direction')\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var e = new this(data.template, data.text, data.url || '');\n e.target = data.target || '';\n e.rel = data.rel || '';\n e.title = data.title || '';\n e.download = data.download || '';\n e.ariaLabel = data.ariaLabel || '';\n return this.parseFormats(e, data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LinkElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LinkElement.js?");
/***/ }),
/***/ "./src/includes/ListControl.js":
/*!*************************************!*\
!*** ./src/includes/ListControl.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui/sortable.js */ \"./src/includes/ui/sortable.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n/**\n * ListControl — generic [{label, url}] editor used by MenuElement + ListElement.\n *\n * 2026-04-17 audit: migrated from Bootstrap accordion to `.bjs-list--plain`\n * primitive (dark mode, tokens, no bootstrap collapse).\n *\n * 2026-04-18 Phase-3 W6.2: drag-reorder via shared bjsSortable, shift/\n * cmd-click multi-select + bulk toolbar, inline \"+\" insert slots.\n *\n * 2026-04-19 W3.8c (BUILDER.md RULE A cleanup): Control no longer holds\n * an Element reference. Callers pass `{ getDomNode: () => this.domNode }`\n * — a hook that late-binds to the element's current canvas domNode. The\n * hook is used only for **on-canvas item highlighting** (drawing a\n * floating box over the rendered `<li>` when the user expands a sidebar\n * row). Late-binding preserves the previous re-render-safe behaviour —\n * if the element's `this.render()` replaces its domNode between control\n * construction and highlight use, the next `getDomNode()` call returns\n * the fresh node. Window (iframe defaultView) stays shared across\n * re-renders so scroll/resize listener cleanup is stable.\n */\nvar ListControl = /*#__PURE__*/function () {\n /**\n * @param {string} label\n * @param {Array<{label:string,url:string}>} items\n * @param {{ setItems: (items) => void }} callback\n * @param {object} [opts]\n * @param {() => HTMLElement|null} [opts.getDomNode] late-bound hook\n * returning the host element's current canvas domNode. Required\n * to enable item highlighting. Absent → highlight is a no-op.\n */\n function ListControl(label, items, callback) {\n var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n _classCallCheck(this, ListControl);\n this.label = label;\n this.items = items;\n this.callback = callback;\n // W3.8c — RULE A compliance: primitives + hooks, no element ref.\n this._getDomNode = typeof opts.getDomNode === 'function' ? opts.getDomNode : null;\n this.domNode = document.createElement('div');\n this._multiSelected = new Set();\n this.render();\n }\n\n /** Late-bind the element's current canvas domNode (can be null). */\n return _createClass(ListControl, [{\n key: \"_hostDomNode\",\n value: function _hostDomNode() {\n return this._getDomNode ? this._getDomNode() : null;\n }\n }, {\n key: \"_t\",\n value: function _t(key, fallback) {\n try {\n var v = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key);\n return v && v !== key ? v : fallback;\n } catch (_e) {\n return fallback;\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this = this;\n // Prune stale multi-select indices (a remove shrinks items before\n // the set is cleared on user Clear click).\n this._multiSelected = new Set(Array.from(this._multiSelected).filter(function (i) {\n return i >= 0 && i < _this.items.length;\n }));\n var itemsHtml = this.items.map(function (item, index) {\n var safeLabel = (item.label || '').replace(/\"/g, '"');\n var safeUrl = (item.url || '').replace(/\"/g, '"');\n var displayName = item.label || \"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.item_fallback'), \" #\").concat(index + 1);\n var isMulti = _this._multiSelected.has(index) ? ' is-multi-selected' : '';\n return \"\\n <li class=\\\"bjs-list-item\".concat(isMulti, \"\\\" data-index=\\\"\").concat(index, \"\\\" aria-expanded=\\\"false\\\">\\n <button class=\\\"bjs-list-item-handle\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.reorder'), \"\\\" type=\\\"button\\\" tabindex=\\\"0\\\">\\u2261</button>\\n <span class=\\\"bjs-list-item-label\\\" data-control=\\\"display-label\\\" data-index=\\\"\").concat(index, \"\\\">\").concat(displayName, \"</span>\\n <div class=\\\"bjs-list-item-actions\\\">\\n <button class=\\\"bjs-icon-btn bjs-list-item-expand\\\" type=\\\"button\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.edit'), \"\\\" data-control=\\\"expand\\\" data-index=\\\"\").concat(index, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">expand_more</span>\\n </button>\\n <button class=\\\"bjs-icon-btn bjs-icon-btn--danger\\\" type=\\\"button\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.delete'), \"\\\" data-control=\\\"remove-item\\\" data-index=\\\"\").concat(index, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">delete</span>\\n </button>\\n </div>\\n <section class=\\\"bjs-list-item-body\\\">\\n <div class=\\\"bjs-list-field\\\">\\n <label class=\\\"bjs-list-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.label'), \"</label>\\n <input type=\\\"text\\\" class=\\\"bjs-list-field-input\\\" value=\\\"\").concat(safeLabel, \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"label\\\">\\n </div>\\n <div class=\\\"bjs-list-field\\\">\\n <label class=\\\"bjs-list-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.url'), \"</label>\\n <input type=\\\"text\\\" class=\\\"bjs-list-field-input\\\" value=\\\"\").concat(safeUrl, \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"url\\\">\\n </div>\\n </section>\\n </li>\\n \");\n }).join('');\n\n // Inline insert slots — one between each pair of items plus one before\n // the first and one after the last. Absolute-positioned overlays so\n // they don't take flex space. Visible on hover of the slot zone only.\n var slotsHtml = '';\n if (this.items.length > 0) {\n for (var i = 0; i <= this.items.length; i++) {\n slotsHtml += \"\\n <div class=\\\"bjs-list-insert-slot\\\" data-slot-index=\\\"\".concat(i, \"\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-list-insert-slot-btn\\\" data-control=\\\"insert-at\\\" data-index=\\\"\").concat(i, \"\\\" aria-label=\\\"\").concat(this._t('list.insert_here', 'Insert here'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">add</span>\\n </button>\\n </div>\\n \");\n }\n }\n var bulkHtml = this._renderBulkBar();\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-list bjs-list--plain\\\">\\n <header class=\\\"bjs-list-header\\\">\\n <span class=\\\"bjs-list-title\\\">\".concat(this.label, \"</span>\\n <button class=\\\"bjs-btn\\\" type=\\\"button\\\" data-control=\\\"add-item\\\">\\n <span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px;margin-right:2px\\\">add</span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.add'), \"\\n </button>\\n </header>\\n <div class=\\\"bjs-list-body\\\">\\n <ol class=\\\"bjs-list-items\\\">\\n \").concat(itemsHtml, \"\\n </ol>\\n \").concat(slotsHtml, \"\\n </div>\\n \").concat(bulkHtml, \"\\n </div>\\n \");\n this._bindEvents();\n this._positionInsertSlots();\n this._bindSortable();\n }\n }, {\n key: \"_renderBulkBar\",\n value: function _renderBulkBar() {\n var n = this._multiSelected.size;\n if (n < 1) return '';\n var label = this._t('list.bulk_selected', '{n} selected').replace('{n}', String(n));\n return \"\\n <div class=\\\"bjs-list-bulk\\\" role=\\\"status\\\" data-count=\\\"\".concat(n, \"\\\">\\n <span class=\\\"bjs-list-bulk-count\\\">\").concat(label, \"</span>\\n <span class=\\\"bjs-list-bulk-actions\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-list-bulk-btn\\\" data-control=\\\"bulk-delete\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">delete</span>\\n <span>\").concat(this._t('list.bulk_delete', 'Delete'), \"</span>\\n </button>\\n <button type=\\\"button\\\" class=\\\"bjs-list-bulk-btn bjs-list-bulk-btn--ghost\\\" data-control=\\\"bulk-clear\\\">\\n \").concat(this._t('list.bulk_clear', 'Clear'), \"\\n </button>\\n </span>\\n </div>\\n \");\n }\n\n /** Position the inline insert-slot buttons on the real gap midpoints —\n * similar to GridControl._positionSlots but vertical. Keeps the \"+\"\n * centered on the border between two items regardless of per-item\n * height (an expanded item is taller than a collapsed one). */\n }, {\n key: \"_positionInsertSlots\",\n value: function _positionInsertSlots() {\n var body = this.domNode.querySelector('.bjs-list-body');\n var ol = this.domNode.querySelector('.bjs-list-items');\n if (!body || !ol) return;\n var items = Array.from(ol.querySelectorAll(':scope > .bjs-list-item'));\n var slots = Array.from(body.querySelectorAll(':scope > .bjs-list-insert-slot'));\n if (!items.length || slots.length !== items.length + 1) return;\n var bodyRect = body.getBoundingClientRect();\n if (bodyRect.width === 0) return;\n var olRect = ol.getBoundingClientRect();\n slots.forEach(function (slot, i) {\n slot.style.left = \"\".concat(olRect.left - bodyRect.left, \"px\");\n slot.style.width = \"\".concat(olRect.width, \"px\");\n var yPx;\n if (i === 0) {\n yPx = items[0].getBoundingClientRect().top - bodyRect.top - 4;\n } else if (i === items.length) {\n yPx = items[items.length - 1].getBoundingClientRect().bottom - bodyRect.top + 4;\n } else {\n var prev = items[i - 1].getBoundingClientRect();\n var next = items[i].getBoundingClientRect();\n yPx = (prev.bottom + next.top) / 2 - bodyRect.top;\n }\n slot.style.top = \"\".concat(yPx, \"px\");\n });\n }\n }, {\n key: \"_bindSortable\",\n value: function _bindSortable() {\n var _this2 = this;\n if (this._sortable && typeof this._sortable.destroy === 'function') {\n try {\n this._sortable.destroy();\n } catch (_e) {}\n }\n var ol = this.domNode.querySelector('.bjs-list-items');\n if (!ol) return;\n this._sortable = (0,_ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__.bjsSortable)(ol, {\n itemSelector: '.bjs-list-item',\n handleSelector: '.bjs-list-item-handle',\n onReorder: function onReorder(from, to) {\n var _this2$items$splice = _this2.items.splice(from, 1),\n _this2$items$splice2 = _slicedToArray(_this2$items$splice, 1),\n moved = _this2$items$splice2[0];\n var adjusted = to > from ? to - 1 : to;\n _this2.items.splice(adjusted, 0, moved);\n // Reset multi-select — indices become ambiguous after reorder.\n _this2._multiSelected.clear();\n _this2.render();\n _this2.callback && _this2.callback.setItems(_this2.items);\n }\n });\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this3 = this;\n var add = this.domNode.querySelector('[data-control=\"add-item\"]');\n if (add) {\n add.addEventListener('click', function () {\n _this3.items.push({\n label: '',\n url: ''\n });\n _this3.render();\n _this3.callback && _this3.callback.setItems(_this3.items);\n });\n }\n\n // Inline insert-at slots — click to insert a blank item at position N.\n this.domNode.querySelectorAll('[data-control=\"insert-at\"]').forEach(function (btn) {\n btn.addEventListener('click', function (e) {\n e.stopPropagation();\n var idx = parseInt(btn.getAttribute('data-index'), 10);\n if (isNaN(idx)) return;\n _this3.items.splice(idx, 0, {\n label: '',\n url: ''\n });\n _this3._multiSelected.clear();\n _this3.render();\n _this3.callback && _this3.callback.setItems(_this3.items);\n });\n });\n this.domNode.querySelectorAll('.bjs-list-item').forEach(function (li) {\n var index = parseInt(li.dataset.index, 10);\n\n // Shift/Cmd-click on the collapsed-row label zone → multi-select.\n // Plain click still expands via the expand button below.\n var labelEl = li.querySelector('[data-control=\"display-label\"]');\n if (labelEl) {\n labelEl.addEventListener('click', function (e) {\n if (!e.shiftKey && !e.metaKey && !e.ctrlKey) return;\n e.preventDefault();\n e.stopPropagation();\n _this3._toggleMulti(index, e.shiftKey);\n });\n }\n var expandBtn = li.querySelector('[data-control=\"expand\"]');\n if (expandBtn) {\n expandBtn.addEventListener('click', function (e) {\n e.stopPropagation();\n var expanded = li.getAttribute('aria-expanded') === 'true';\n li.setAttribute('aria-expanded', expanded ? 'false' : 'true');\n var caret = expandBtn.querySelector('.material-symbols-rounded');\n if (caret) caret.textContent = expanded ? 'expand_more' : 'expand_less';\n if (!expanded) _this3.highlightListItem(index);else _this3.removeListItemHighlight(index);\n // Re-run slot positioning — expanded item height changes.\n requestAnimationFrame(function () {\n return _this3._positionInsertSlots();\n });\n });\n }\n var removeBtn = li.querySelector('[data-control=\"remove-item\"]');\n if (removeBtn) {\n removeBtn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this3.removeListItemHighlight(index);\n _this3.items.splice(index, 1);\n _this3._multiSelected.clear();\n _this3.render();\n _this3.callback && _this3.callback.setItems(_this3.items);\n });\n }\n li.querySelectorAll('input[data-field]').forEach(function (input) {\n input.addEventListener('input', function (e) {\n var field = e.target.getAttribute('data-field');\n var i = parseInt(e.target.getAttribute('data-index'), 10);\n _this3.items[i][field] = e.target.value;\n // Update the collapsed row label in-place\n if (field === 'label') {\n var disp = _this3.domNode.querySelector(\"[data-control=\\\"display-label\\\"][data-index=\\\"\".concat(i, \"\\\"]\"));\n if (disp) disp.textContent = e.target.value || \"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.item_fallback'), \" #\").concat(i + 1);\n }\n _this3.callback && _this3.callback.setItems(_this3.items);\n });\n });\n });\n\n // Keyboard reorder on focused handle — ArrowUp / ArrowDown swap with\n // neighbor. Mirrors GridControl's handle keyboard shortcuts for a11y.\n this.domNode.querySelectorAll('.bjs-list-item-handle').forEach(function (handle) {\n handle.addEventListener('keydown', function (e) {\n if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;\n var li = handle.closest('.bjs-list-item');\n if (!li) return;\n var idx = parseInt(li.dataset.index, 10);\n var target = e.key === 'ArrowUp' ? idx - 1 : idx + 1;\n if (target < 0 || target >= _this3.items.length) return;\n e.preventDefault();\n var _this3$items$splice = _this3.items.splice(idx, 1),\n _this3$items$splice2 = _slicedToArray(_this3$items$splice, 1),\n moved = _this3$items$splice2[0];\n _this3.items.splice(target, 0, moved);\n _this3._multiSelected.clear();\n _this3.render();\n _this3.callback && _this3.callback.setItems(_this3.items);\n requestAnimationFrame(function () {\n var newHandle = _this3.domNode.querySelector(\".bjs-list-item[data-index=\\\"\".concat(target, \"\\\"] .bjs-list-item-handle\"));\n if (newHandle && typeof newHandle.focus === 'function') newHandle.focus();\n });\n });\n });\n\n // Bulk bar\n var bulkDelete = this.domNode.querySelector('[data-control=\"bulk-delete\"]');\n if (bulkDelete) {\n bulkDelete.addEventListener('click', function () {\n return _this3._bulkDelete();\n });\n }\n var bulkClear = this.domNode.querySelector('[data-control=\"bulk-clear\"]');\n if (bulkClear) {\n bulkClear.addEventListener('click', function () {\n _this3._multiSelected.clear();\n _this3.render();\n });\n }\n }\n }, {\n key: \"_toggleMulti\",\n value: function _toggleMulti(index, isShift) {\n if (isShift && this._multiSelected.size > 0) {\n // Range-select: fill from the lowest existing selection up to\n // clicked index (or down, whichever reaches).\n var existing = Array.from(this._multiSelected);\n var anchor = existing.reduce(function (a, b) {\n return Math.abs(b - index) < Math.abs(a - index) ? b : a;\n }, existing[0]);\n var _ref = anchor < index ? [anchor, index] : [index, anchor],\n _ref2 = _slicedToArray(_ref, 2),\n lo = _ref2[0],\n hi = _ref2[1];\n for (var i = lo; i <= hi; i++) this._multiSelected.add(i);\n } else {\n if (this._multiSelected.has(index)) this._multiSelected[\"delete\"](index);else this._multiSelected.add(index);\n }\n this.render();\n }\n }, {\n key: \"_bulkDelete\",\n value: function _bulkDelete() {\n var _this4 = this;\n if (this._multiSelected.size === 0) return;\n var descending = Array.from(this._multiSelected).sort(function (a, b) {\n return b - a;\n });\n descending.forEach(function (i) {\n return _this4.items.splice(i, 1);\n });\n this._multiSelected.clear();\n this.render();\n this.callback && this.callback.setItems(this.items);\n }\n }, {\n key: \"highlightListItem\",\n value: function highlightListItem(index) {\n var host = this._hostDomNode();\n if (!host) return;\n var liElements = host.querySelectorAll('li');\n var liElement = liElements[index];\n if (!liElement) return;\n var highlightBox = document.createElement('div');\n highlightBox.classList.add('li-highlight-box', 'active-item-highlight');\n document.body.appendChild(highlightBox);\n if (!this.itemHighlightBoxes) this.itemHighlightBoxes = {};\n this.itemHighlightBoxes[index] = highlightBox;\n var updatePosition = function updatePosition() {\n if (!highlightBox || !liElement) return;\n var domRect = liElement.getBoundingClientRect();\n var iframe = liElement.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe.getBoundingClientRect();\n Object.assign(highlightBox.style, {\n position: 'fixed',\n top: \"\".concat(iframeRect.top + domRect.top, \"px\"),\n left: \"\".concat(iframeRect.left + domRect.left, \"px\"),\n width: \"\".concat(domRect.width, \"px\"),\n height: \"\".concat(domRect.height, \"px\"),\n borderRadius: getComputedStyle(liElement).borderRadius || '6px'\n });\n };\n updatePosition();\n var win = host.ownerDocument.defaultView;\n win.addEventListener('scroll', updatePosition, true);\n win.addEventListener('resize', updatePosition);\n highlightBox._updatePosition = updatePosition;\n // Pin the window used so removal uses the same reference even\n // if the host domNode gets swapped during a re-render (iframe\n // defaultView is stable within an editing session; this is\n // belt-and-suspenders for future iframe recreation scenarios).\n highlightBox._win = win;\n }\n }, {\n key: \"removeListItemHighlight\",\n value: function removeListItemHighlight(index) {\n if (!this.itemHighlightBoxes || !this.itemHighlightBoxes[index]) return;\n var highlightBox = this.itemHighlightBoxes[index];\n if (highlightBox._updatePosition) {\n var win = highlightBox._win || (this._hostDomNode() ? this._hostDomNode().ownerDocument.defaultView : null);\n if (win) {\n win.removeEventListener('scroll', highlightBox._updatePosition, true);\n win.removeEventListener('resize', highlightBox._updatePosition);\n }\n }\n highlightBox.remove();\n delete this.itemHighlightBoxes[index];\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ListControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ListControl.js?");
/***/ }),
/***/ "./src/includes/ListElement.js":
/*!*************************************!*\
!*** ./src/includes/ListElement.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _ListControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ListControl.js */ \"./src/includes/ListControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar ListElement = /*#__PURE__*/function (_BaseElement) {\n function ListElement(template, items) {\n var _this;\n _classCallCheck(this, ListElement);\n _this = _callSuper(this, ListElement); // Call the parent class constructor\n _this.template = template;\n _this.items = items;\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['items'];\n\n // formats\n _this.formats = {\n background_color: null,\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n padding_top: 0,\n padding_right: 0,\n padding_bottom: 0,\n padding_left: 0\n };\n return _this;\n }\n _inherits(ListElement, _BaseElement);\n return _createClass(ListElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.list');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // ListElement has no formatter; pass items + legacy `formats` field\n var htmlContent = this.renderTemplate({\n items: this.items,\n formats: this.formats\n });\n this.domNode.innerHTML = htmlContent;\n var bgImageValue = this.getFormat('background_image');\n if (bgImageValue && bgImageValue.toString().trim() !== \"\") {\n var bgImage = bgImageValue.toString().replace(/\\s*!important\\s*/, \"\").trim();\n bgImage = this.transferMediaAbsUrl(bgImage);\n this.domNode.style.backgroundImage = \"url('\".concat(bgImage, \"')\");\n\n // Set background position\n var position = this.getFormat('background_position', 'center');\n this.domNode.style.backgroundPosition = position;\n\n // Set background size\n var size = this.getFormat('background_size', '100').toString().replace(/\\s*!important\\s*/, \"\").trim();\n if (!isNaN(parseFloat(size)) && isFinite(size)) {\n size = parseFloat(size) + '%';\n }\n this.domNode.style.backgroundSize = size;\n\n // Set background repeat\n var repeat = this.getFormat('background_repeat', 'no-repeat').toString();\n this.domNode.style.backgroundRepeat = repeat;\n } else {\n // Explicitly clear background image and related styles\n this.domNode.style.backgroundImage = \"\";\n this.domNode.style.backgroundPosition = \"\";\n this.domNode.style.backgroundSize = \"\";\n this.domNode.style.backgroundRepeat = \"\";\n }\n\n // Apply background color\n var bgColor = this.getFormat('background_color');\n if (bgColor) {\n this.domNode.style.backgroundColor = bgColor;\n }\n }\n }, {\n key: \"getData\",\n value: function getData() {\n // ListElement uses legacy `formats` field (not formatter) — pass it\n // explicitly. super.getData() returns name + template (no formats key\n // because there's no this.formatter).\n return _objectSpread(_objectSpread({}, _superPropGet(ListElement, \"getData\", this, 3)([])), {}, {\n items: this.items,\n formats: this.formats\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this;\n return [new _ListControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.list_items'), this.items.map(function (item) {\n return {\n label: item\n };\n }), {\n setItems: function setItems(items) {\n _this2.items = items.map(function (item) {\n return item.label;\n });\n _this2.render();\n }\n },\n // W3.8c — RULE A: primitives + hooks only.\n {\n getDomNode: function getDomNode() {\n return _this2.domNode;\n }\n })];\n }\n }, {\n key: \"setFormat\",\n value: function setFormat(key, value) {\n this.formats[key] = value;\n }\n }, {\n key: \"getFormat\",\n value: function getFormat(key) {\n var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n return this.formats[key] !== undefined ? this.formats[key] : defaultValue;\n }\n }, {\n key: \"_getHighlightTarget\",\n value: function _getHighlightTarget() {\n if (!this.domNode) return null;\n var ul = this.domNode.querySelector('ul');\n if (ul) return ul;\n var ol = this.domNode.querySelector('ol');\n if (ol) return ol;\n return this.domNode;\n }\n\n /* SELECTED EFFECTS */\n }, {\n key: \"addSelectedHighlight\",\n value: function addSelectedHighlight() {\n var _this3 = this;\n // render selected outbound\n if (!this.selectedBox) {\n this.selectedBox = document.createElement(\"div\");\n this.selectedBox.classList.add(\"selected-box\");\n document.body.appendChild(this.selectedBox);\n this.matchingDomNode(this.selectedBox);\n }\n\n // Render actions\n if (!this.actionsBox) {\n this.actionsBox = document.createElement(\"div\");\n this.actionsBox.classList.add(\"actions-box\");\n this.actionsBox.classList.add(\"d-flex\");\n this.actionsBox.classList.add(\"align-items-center\");\n // Opt out of canvas-clip — toolbar pill must escape canvas\n // top edge. See BaseElement.addSelectedHighlight + OVERLAY.md §24.\n this.actionsBox.classList.add(\"bjs-ovl-no-clip\");\n document.body.appendChild(this.actionsBox);\n this.matchingDomNode(this.actionsBox, function () {\n if (!_this3.actionsBox) return;\n var domRect = _this3.domNode.getBoundingClientRect();\n var iframe = _this3.domNode.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe.getBoundingClientRect();\n var absoluteTop = iframeRect.top + domRect.top;\n var absoluteLeft = iframeRect.left + domRect.left;\n Object.assign(_this3.actionsBox.style, {\n position: \"fixed\",\n top: \"\".concat(absoluteTop - 38, \"px\"),\n left: \"\".concat(absoluteLeft, \"px\"),\n width: \"\".concat(domRect.width, \"px\"),\n height: \"40px\"\n });\n });\n\n // Label\n this.actionsBoxLabel = document.createElement(\"h5\");\n this.actionsBoxLabel.classList.add(\"ms-2\");\n this.actionsBoxLabel.classList.add(\"m-0\");\n this.actionsBoxLabel.classList.add(\"text-light\");\n this.actionsBoxLabel.innerHTML = '<span class=\"d-flex align-items-center\"><span class=\"material-symbols-rounded me-2\">apps</span>' + this.getName() + \"</span>\";\n this.actionsBox.appendChild(this.actionsBoxLabel);\n this.actionsBoxInner = document.createElement(\"div\");\n this.actionsBoxInner.classList.add(\"actions-box-inner\");\n this.actionsBoxInner.classList.add(\"btn-group\");\n this.actionsBoxInner.classList.add(\"ms-auto\");\n this.actionsBox.appendChild(this.actionsBoxInner);\n this.getActions().forEach(function (action) {\n var actionButton = document.createElement(\"button\");\n actionButton.setAttribute(\"class\", \"element-action-item btn btn-light p-1 d-flex align-items-center\");\n actionButton.setAttribute(\"data-tooltip\", action.label);\n actionButton.setAttribute(\"aria-label\", action.label);\n actionButton.innerHTML = \"<span class=\\\"material-symbols-rounded fs-5\\\">\".concat(action.icon, \"</span>\");\n _this3.actionsBoxInner.appendChild(actionButton);\n actionButton.addEventListener(\"click\", function () {\n action.run();\n });\n });\n }\n\n // Add rainbow highlight around all <li> elements\n if (!this.liHighlightBoxes) {\n this.liHighlightBoxes = [];\n\n // Find all <li> elements in the rendered element\n var liElements = this.domNode.querySelectorAll('li');\n liElements.forEach(function (liElement) {\n var highlightBox = document.createElement(\"div\");\n highlightBox.classList.add(\"li-highlight-box\");\n document.body.appendChild(highlightBox);\n _this3.matchingDomNode(highlightBox, function () {\n if (!highlightBox) return;\n var domRect = liElement.getBoundingClientRect();\n var iframe = liElement.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe.getBoundingClientRect();\n var absoluteTop = iframeRect.top + domRect.top;\n var absoluteLeft = iframeRect.left + domRect.left;\n Object.assign(highlightBox.style, {\n position: \"fixed\",\n top: \"\".concat(absoluteTop, \"px\"),\n left: \"\".concat(absoluteLeft, \"px\"),\n width: \"\".concat(domRect.width, \"px\"),\n height: \"\".concat(domRect.height, \"px\"),\n borderRadius: getComputedStyle(liElement).borderRadius || \"6px\"\n });\n });\n\n // Add mouseenter/mouseleave to each li for hover effect\n var enter = function enter() {\n return highlightBox.classList.add(\"hover\");\n };\n var leave = function leave() {\n return highlightBox.classList.remove(\"hover\");\n };\n if (liElement._rainbowHoverHandler) {\n liElement.removeEventListener(\"mouseenter\", liElement._rainbowHoverHandler.enter);\n liElement.removeEventListener(\"mouseleave\", liElement._rainbowHoverHandler.leave);\n }\n liElement.addEventListener(\"mouseenter\", enter);\n liElement.addEventListener(\"mouseleave\", leave);\n liElement._rainbowHoverHandler = {\n enter: enter,\n leave: leave\n };\n _this3.liHighlightBoxes.push({\n box: highlightBox,\n element: liElement\n });\n });\n }\n }\n }, {\n key: \"removeSelectedHighlight\",\n value: function removeSelectedHighlight() {\n if (this.selectedBox) {\n this.selectedBox.remove();\n }\n this.selectedBox = null;\n if (this.actionsBox) {\n this.actionsBox.remove();\n }\n this.actionsBox = null;\n if (this.liHighlightBoxes) {\n this.liHighlightBoxes.forEach(function (_ref) {\n var box = _ref.box,\n element = _ref.element;\n box.remove();\n if (element._rainbowHoverHandler) {\n element.removeEventListener(\"mouseenter\", element._rainbowHoverHandler.enter);\n element.removeEventListener(\"mouseleave\", element._rainbowHoverHandler.leave);\n element._rainbowHoverHandler = null;\n }\n });\n }\n this.liHighlightBoxes = null;\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var e = new ListElement(data.template, data.items);\n if (data.formats && _typeof(data.formats) === 'object') {\n e.formats = _objectSpread(_objectSpread({}, e.formats), data.formats);\n }\n return e;\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ListElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ListElement.js?");
/***/ }),
/***/ "./src/includes/ListWidget.js":
/*!************************************!*\
!*** ./src/includes/ListWidget.js ***!
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ListElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ListElement.js */ \"./src/includes/ListElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar ListWidget = /*#__PURE__*/function (_BaseWidget) {\n function ListWidget() {\n var _this;\n _classCallCheck(this, ListWidget);\n _this = _callSuper(this, ListWidget); // Call the parent class constructor\n _this.elements = [];\n\n // Add a ListElement to the widget\n var list = new _ListElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('List', ['Item 1', 'Item 2', 'Item 3']);\n _this.elements.push(list);\n return _this;\n }\n _inherits(ListWidget, _BaseWidget);\n return _createClass(ListWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.list');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'format_list_bulleted';\n }\n }, {\n key: \"getElements\",\n value: function getElements() {\n // Return the elements\n return this.elements;\n }\n }, {\n key: \"renderElements\",\n value: function renderElements() {\n // Clone all elements and return the cloned ones\n return this.elements.map(function (element) {\n var data = element.getData();\n return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(data);\n });\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ListWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ListWidget.js?");
/***/ }),
/***/ "./src/includes/MenuElement.js":
/*!*************************************!*\
!*** ./src/includes/MenuElement.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _ListControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ListControl.js */ \"./src/includes/ListControl.js\");\n/* harmony import */ var _RangeControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./RangeControl.js */ \"./src/includes/RangeControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _SeparatorControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./SeparatorControl.js */ \"./src/includes/SeparatorControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\nvar MenuElement = /*#__PURE__*/function (_BaseElement) {\n function MenuElement(template, items) {\n var _this;\n _classCallCheck(this, MenuElement);\n _this = _callSuper(this, MenuElement); // Call the parent class constructor\n _this.template = template;\n _this.items = items;\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['items'];\n\n // Formatter. Audit 2026-04-17: dropped `link_color` (dead — a menu\n // is all-links, so the single `text_color` already colors every <a>;\n // previous `link-color:` kebab was invalid CSS, silently no-op).\n // `text_align` now renders meaningfully via the Menu template in\n // both orientations (outer <div> text-align for horizontal, <ul>\n // align-items for vertical).\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]({\n align: 'center',\n // text styles\n font_family: null,\n font_weight: null,\n font_size: null,\n text_color: null,\n text_align: null,\n // separator between items (string like \"|\" or \"•\")\n separator: null,\n // spacing around separator in px\n separator_gap: null,\n // orientation: 'horizontal' | 'vertical'\n orientation: 'horizontal'\n });\n\n // settings (legacy gap control)\n _this.menu_gap = 10;\n return _this;\n }\n _inherits(MenuElement, _BaseElement);\n return _createClass(MenuElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.menu');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c). `formats` is also passed because the\n // Menu template historically reads it as a separate var.\n this.domNode.innerHTML = this.renderTemplate({\n items: this.items,\n formats: this.formats,\n menu_gap: this.menu_gap\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(MenuElement, \"getData\", this, 3)([])), {}, {\n items: this.items,\n menu_gap: this.menu_gap\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this;\n // IMPORTANT behavior rule (2026-04-17 audit pass-4, user-flagged):\n // setters MUST NOT call `builder.renderElementControls(this)`. That\n // rebuilds the whole panel on every value change → text inputs lose\n // focus mid-keystroke, segmented clicks feel twitchy, every control\n // gets destroyed+recreated (ListControl's accordion closes, etc.).\n //\n // For controls whose visibility depends on element state (Separator\n // gap, Item alignment), we stash control refs on `this` and toggle\n // `display: none` via `_syncControlVisibility()`. Cheap, preserves\n // focus, matches the PElement/HeadingElement structure-preserving\n // pattern (`applyFormatStyles` — patch in place, don't rebuild).\n var setFmt = function setFmt(key) {\n return function (value) {\n _this2.formatter.setFormat(key, value);\n _this2.render();\n _this2._syncControlVisibility();\n };\n };\n\n // `orientation` doesn't map to a `format_align_*` Material Symbol\n // (only left/center/right/justify exist). Pass explicit icon names\n // so the glyph renders instead of the ligature-fallback text.\n var ORIENTATION_OPTIONS = [{\n value: 'horizontal',\n icon: 'view_week'\n },\n // column layout icon\n {\n value: 'vertical',\n icon: 'view_agenda'\n } // stacked rows icon\n ];\n\n // Info-banner guidance row (matches Video / Button / Link pattern).\n var bannerNode = document.createElement('div');\n bannerNode.innerHTML = \"\\n <div class=\\\"bjs-info-banner\\\" role=\\\"note\\\">\\n <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">menu</span>\\n <span class=\\\"bjs-info-banner-text\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('menu.banner'), \"</span>\\n </div>\\n \");\n var banner = {\n domNode: bannerNode.firstElementChild\n };\n\n // Microtask runs right after the caller (renderElementControls)\n // appends our controls' domNodes. By then `this._separatorGapControl`\n // and `this._itemAlignmentControl` are set (assigned inline during\n // array construction below) and their .domNodes are in the DOM.\n // Syncing here paints the initial visibility (hidden state if\n // separator is null / orientation is horizontal on open).\n queueMicrotask(function () {\n return _this2._syncControlVisibility();\n });\n return [banner, new _ListControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.list_items'), this.items.map(function (item) {\n return {\n label: item.text,\n url: item.url\n };\n }), {\n setItems: function setItems(items) {\n _this2.items = items.map(function (item) {\n return {\n text: item.label,\n url: item.url\n };\n });\n _this2.render();\n }\n },\n // W3.8c — RULE A compliance: primitives + hooks only, no\n // element ref. `getDomNode` late-binds to the current\n // canvas node so highlighting survives re-render swaps.\n {\n getDomNode: function getDomNode() {\n return _this2.domNode;\n }\n }),\n // Outer-block alignment (the whole menu list in its container)\n new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.block_alignment'), this.formatter.getFormat('align'), {\n setValue: setFmt('align')\n }, ['left', 'center', 'right']),\n // Orientation: row (horizontal) vs column (vertical). Explicit\n // icons because AlignControl's default `format_align_*` glyphs\n // don't exist for these values. setFmt('orientation') triggers\n // _syncControlVisibility → Item alignment row appears/hides\n // without rebuilding the panel.\n new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.orientation'), this.formatter.getFormat('orientation'), {\n setValue: setFmt('orientation')\n }, ORIENTATION_OPTIONS),\n // Items gap — migrated from RangeControl (Bootstrap .form-range)\n // to the already-.bjs-*-compliant NumberControl so the menu\n // panel stops drifting from the showcase.\n new _NumberControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.items_gap'), this.menu_gap, {\n setValue: function setValue(value) {\n _this2.menu_gap = value;\n _this2.render();\n }\n }, {\n defaultValue: 10,\n minValue: 0,\n maxValue: 500,\n suffix: 'px',\n allowZero: true\n }),\n // Separator picker — segmented presets + 50%-width custom input\n // on its own row when Custom is chosen. setText only calls\n // element render() + sync (no panel rebuild) so the custom\n // text input keeps focus across keystrokes.\n new _SeparatorControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.separator'), this.formatter.getFormat('separator'), {\n setText: function setText(value) {\n _this2.formatter.setFormat('separator', value);\n _this2.render();\n _this2._syncControlVisibility();\n }\n }),\n // Separator gap — always mounted; `_syncControlVisibility` hides\n // the row when there is no separator (a user nudging the gap\n // with no separator would be a dead tap — the <li> never\n // renders). Stashed on `this` so the sync method can find it.\n this._separatorGapControl = new _NumberControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.separator_gap'), this.formatter.getFormat('separator_gap') || this.menu_gap, {\n setValue: setFmt('separator_gap')\n }, {\n defaultValue: 10,\n minValue: 0,\n maxValue: 200,\n suffix: 'px',\n allowZero: true\n }), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n setValue: setFmt('font_family')\n }), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n setValue: setFmt('font_weight')\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n setValue: setFmt('font_size')\n }, {\n defaultValue: 16,\n minValue: 8,\n maxValue: 72,\n suffix: 'px',\n allowZero: false\n }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n setValue: setFmt('text_color')\n }),\n // Item alignment — always mounted; `_syncControlVisibility`\n // hides the row for horizontal orientation where <a>s are\n // inline and text-align is a visual no-op.\n this._itemAlignmentControl = new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.item_alignment'), this.formatter.getFormat('text_align'), {\n setValue: setFmt('text_align')\n }, ['left', 'center', 'right'])];\n }\n\n /**\n * Toggle the display of state-dependent controls without rebuilding the\n * panel. Called synchronously after every setter; also called once after\n * initial getControls() (see below — we return the array then trigger\n * the sync via a microtask because the caller hasn't mounted the\n * domNodes yet on first call, but the domNodes themselves exist).\n */\n }, {\n key: \"_syncControlVisibility\",\n value: function _syncControlVisibility() {\n if (this._separatorGapControl && this._separatorGapControl.domNode) {\n var sep = this.formatter.getFormat('separator');\n var hide = sep == null || sep === '';\n this._separatorGapControl.domNode.style.display = hide ? 'none' : '';\n }\n if (this._itemAlignmentControl && this._itemAlignmentControl.domNode) {\n var _hide = this.formatter.getFormat('orientation') !== 'vertical';\n this._itemAlignmentControl.domNode.style.display = _hide ? 'none' : '';\n }\n }\n // 2026-04-17 audit: removed the custom addSelectedHighlight /\n // removeSelectedHighlight overrides. They called\n // `matchingDomNode(box, callback)` using the OLD 2-arg signature,\n // but BaseElement has long since evolved to\n // `matchingDomNode(box, padding=0, setPosSize=null, afterPosSize=null)`.\n // The callback was silently consumed as `padding`, the real position\n // callback never ran, and the canvas action-bar header (with the\n // \"Menu\" label + parent/copy/delete/unselect icons) never positioned\n // itself — users saw only the blue selected-box ring.\n // MenuElement now inherits BaseElement's standard overlay — the same\n // one every other element uses. The rainbow per-<li> hover was\n // decorative and not worth keeping the broken override alive for.\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var e = new MenuElement(data.template, data.items);\n e.menu_gap = data.menu_gap || 10;\n return this.parseFormats(e, data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (MenuElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/MenuElement.js?");
/***/ }),
/***/ "./src/includes/MenuWidget.js":
/*!************************************!*\
!*** ./src/includes/MenuWidget.js ***!
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _MenuElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MenuElement.js */ \"./src/includes/MenuElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar MenuWidget = /*#__PURE__*/function (_BaseWidget) {\n function MenuWidget() {\n var _this;\n _classCallCheck(this, MenuWidget);\n _this = _callSuper(this, MenuWidget); // Call the parent class constructor\n\n // Add elements to the widget\n var menu = new _MenuElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Menu', [{\n url: '#',\n text: 'Home'\n }, {\n url: '#',\n text: 'About'\n }, {\n url: '#',\n text: 'Contact'\n }]);\n\n // Append the new element to the block\n _this.block.appendElements([menu]);\n return _this;\n }\n _inherits(MenuWidget, _BaseWidget);\n return _createClass(MenuWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.menu');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'menu_open';\n }\n }, {\n key: \"getElements\",\n value: function getElements() {\n // Return the elements\n return this.elements;\n }\n }, {\n key: \"renderElements\",\n value: function renderElements() {\n // Clone all elements and return the cloned ones\n return this.elements.map(function (element) {\n var data = element.getData();\n return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(data);\n });\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (MenuWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/MenuWidget.js?");
/***/ }),
/***/ "./src/includes/NumberControl.js":
/*!***************************************!*\
!*** ./src/includes/NumberControl.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * NumberControl — numeric stepper with ± buttons + direct input +\n * arrow-key fine adjust + unit suffix.\n *\n * 2026-04-24 (W3.1) — optional `options.bus` + `options.elementUid` +\n * `options.formatterKey` add dual-mount bus sync. Same pattern as\n * AlignControl (W1.1b) / FontFamilyControl / FontWeightControl:\n * opt-in, zero regression for the 10+ legacy callsites that pass only\n * defaultValue/minValue/maxValue/step/suffix/allowZero/allowNegative.\n */\nvar NumberControl = /*#__PURE__*/function () {\n function NumberControl(label, value, callback) {\n var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n _classCallCheck(this, NumberControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = value === null || value === undefined ? options.defaultValue || 0 : value;\n this.callback = callback;\n this.options = _objectSpread({\n defaultValue: 0,\n minValue: 0,\n maxValue: null,\n step: 1,\n suffix: '',\n allowZero: true,\n allowNegative: false\n }, options);\n\n // W3.1 — bus wiring carried on the same `options` arg (opt-in).\n this._bus = options.bus || null;\n this._elementUid = options.elementUid || null;\n this._formatterKey = options.formatterKey || null;\n this._busOff = null;\n this._busSource = 'number-control:' + this.id;\n this.domNode = document.createElement(\"div\");\n this.render();\n this._attachBusSubscription();\n }\n return _createClass(NumberControl, [{\n key: \"render\",\n value: function render() {\n var suffixHtml = this.options.suffix ? \"<span class=\\\"bjs-number-unit\\\">\".concat(this.options.suffix, \"</span>\") : '';\n var minAttr = this.options.minValue !== null && this.options.minValue !== undefined ? \" min=\\\"\".concat(this.options.minValue, \"\\\"\") : '';\n var maxAttr = this.options.maxValue !== null ? \" max=\\\"\".concat(this.options.maxValue, \"\\\"\") : '';\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\"><span>\".concat(this.label, \"</span></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-number-input\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" aria-label=\\\"Decrease\\\">\\u2212</button>\\n <input type=\\\"number\\\" class=\\\"bjs-number-value\\\" id=\\\"\").concat(this.id, \"\\\"\\n value=\\\"\").concat(this.value, \"\\\"\").concat(minAttr).concat(maxAttr, \"\\n step=\\\"\").concat(this.options.step, \"\\\">\\n \").concat(suffixHtml, \"\\n <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" aria-label=\\\"Increase\\\">+</button>\\n </div>\\n </div>\\n </div>\\n \");\n this._bindEvents();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this = this;\n var decrease = this.domNode.querySelector('[aria-label=\"Decrease\"]');\n var increase = this.domNode.querySelector('[aria-label=\"Increase\"]');\n var input = this.domNode.querySelector('.bjs-number-value');\n if (decrease) {\n decrease.addEventListener('click', function (e) {\n e.preventDefault();\n _this._changeValue(-1);\n });\n }\n if (increase) {\n increase.addEventListener('click', function (e) {\n e.preventDefault();\n _this._changeValue(1);\n });\n }\n if (input) {\n // Direct typing support\n input.addEventListener('input', function (e) {\n var raw = e.target.value;\n if (raw === '' || raw === '-') return; // allow partial typing\n var numeric = parseFloat(raw);\n if (!isNaN(numeric)) {\n _this.value = _this._clamp(numeric);\n _this._fireCallback();\n _this._emitBus();\n }\n });\n\n // Clamp + format on blur\n input.addEventListener('blur', function (e) {\n var raw = e.target.value;\n var numeric = parseFloat(raw);\n if (isNaN(numeric)) {\n _this.value = _this.options.defaultValue;\n } else {\n _this.value = _this._clamp(numeric);\n }\n e.target.value = _this.value;\n _this._fireCallback();\n _this._emitBus();\n });\n\n // Arrow keys in input for fine adjustment\n input.addEventListener('keydown', function (e) {\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n _this._changeValue(1);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n _this._changeValue(-1);\n }\n });\n }\n this._inputNode = input;\n }\n }, {\n key: \"_changeValue\",\n value: function _changeValue(delta) {\n var numeric = parseFloat(this.value) || 0;\n numeric += delta * this.options.step;\n this.value = this._clamp(numeric);\n this._syncInput();\n this._fireCallback();\n this._emitBus();\n }\n }, {\n key: \"_clamp\",\n value: function _clamp(numeric) {\n if (this.options.maxValue !== null) {\n numeric = Math.min(this.options.maxValue, numeric);\n }\n if (!this.options.allowNegative) {\n numeric = Math.max(this.options.allowZero ? 0 : this.options.step, numeric);\n } else {\n numeric = Math.max(this.options.minValue, numeric);\n }\n return numeric;\n }\n }, {\n key: \"_syncInput\",\n value: function _syncInput() {\n var input = this.domNode.querySelector('.bjs-number-value');\n if (input) input.value = this.value;\n }\n }, {\n key: \"_fireCallback\",\n value: function _fireCallback() {\n if (typeof this.callback === 'function') {\n this.callback(this.value);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(this.value);\n }\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$silent = _ref.silent,\n silent = _ref$silent === void 0 ? false : _ref$silent;\n this.value = newValue === null || newValue === undefined ? this.options.defaultValue : newValue;\n this._syncInput();\n if (silent) return;\n this._fireCallback();\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n\n /** Control teardown — drops bus subscription. Called by\n * `Builder.renderElementControls` (SA I14) on sidebar rebuild. */\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this._busOff) {\n this._busOff();\n this._busOff = null;\n }\n }\n }, {\n key: \"_attachBusSubscription\",\n value: function _attachBusSubscription() {\n var _this2 = this;\n if (!this._bus || !this._elementUid || !this._formatterKey) return;\n if (typeof this._bus.on !== 'function') return;\n this._busOff = this._bus.on('formatter:change', function (payload) {\n if (!payload) return;\n if (payload.elementUid !== _this2._elementUid) return;\n if (payload.key !== _this2._formatterKey) return;\n if (payload.source === _this2._busSource) return;\n _this2.setValue(payload.value, {\n silent: true\n });\n });\n }\n }, {\n key: \"_emitBus\",\n value: function _emitBus() {\n if (!this._bus || !this._elementUid || !this._formatterKey) return;\n if (typeof this._bus.emit !== 'function') return;\n this._bus.emit('formatter:change', {\n elementUid: this._elementUid,\n key: this._formatterKey,\n value: this.value,\n source: this._busSource\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (NumberControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/NumberControl.js?");
/***/ }),
/***/ "./src/includes/PElement.js":
/*!**********************************!*\
!*** ./src/includes/PElement.js ***!
\**********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\nvar PElement = /*#__PURE__*/function (_BaseElement) {\n function PElement(template, text) {\n var _this;\n _classCallCheck(this, PElement);\n _this = _callSuper(this, PElement);\n _this.template = template;\n _this.text = text;\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['text'];\n\n // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n _this.registerInlineEdit('text');\n\n // Formatter. `text_decoration` and `font_style` exist as entries\n // because the template emits all formats via `toStyleStringAll()`,\n // but they are managed by RichTextControl's inline `<b>/<i>/<u>`\n // tags (character-level), not by paragraph-level formats — so no\n // panel control is needed. Paragraph-level `border_*` + `border_radius`\n // are declared but unreachable (no BorderControl in a text panel\n // would add ~270 lines of noise to every paragraph's settings).\n // Audited 2026-04-17, Phase 2.7 — keeping the keys so future\n // sessions can opt in without a data migration.\n _this.formatter = new Formatter({\n font_family: null,\n font_weight: null,\n font_size: null,\n text_color: null,\n link_color: null,\n paragraph_spacing: null,\n text_align: null,\n line_height: null,\n letter_spacing: null,\n text_direction: null,\n text_decoration: null,\n font_style: null,\n padding_top: null,\n padding_right: null,\n padding_bottom: null,\n padding_left: null,\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_style: null,\n border_left_width: null,\n border_left_color: null,\n border_radius: null\n });\n return _this;\n }\n _inherits(PElement, _BaseElement);\n return _createClass(PElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.paragraph');\n }\n\n /**\n * Full render — emits the template's innerHTML. Inline-edit wiring is\n * auto-fired by BaseElement.afterRender() (W0.2b). Used only when\n * structure/text changes; prefer `applyFormatStyles()` for format-only\n * tweaks so the canvas <p> stays alive (contenteditable cursor + text\n * selection + RichText editor state preserved). PHASE_2_PLAN §2.8 E.\n */\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter + text auto-merged by BaseElement.renderTemplate (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({});\n }\n\n /**\n * Structure-preserving format update. Patches the existing <p> element's\n * style attribute in place (no innerHTML swap), so contenteditable\n * cursor + any in-flight text selection survive every font/colour/\n * alignment tweak. PHASE_2_PLAN §2.8 rule E.\n */\n }, {\n key: \"applyFormatStyles\",\n value: function applyFormatStyles() {\n if (!this.domNode) {\n this.render();\n return;\n }\n var target = this.domNode.querySelector('[inline-edit=\"text\"]');\n if (!target) {\n this.render();\n return;\n }\n target.setAttribute('style', this.formatter.toStyleStringAll());\n }\n }, {\n key: \"getData\",\n value: function getData() {\n // name + template + formats baseline merged from super (W0.2c)\n return _objectSpread(_objectSpread({}, _superPropGet(PElement, \"getData\", this, 3)([])), {}, {\n text: this.text\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this,\n _this$host;\n var setFmt = function setFmt(key) {\n return function (value) {\n _this2.formatter.setFormat(key, value);\n _this2.applyFormatStyles();\n };\n };\n // W3.1 — bus wiring for dual-view sync between sidebar and the\n // canvas FontPopoverOverlay. Each sidebar font control mirrors\n // popover writes via `formatter:change` + silent setValue.\n var busOpts = function busOpts(key) {\n var _this2$host;\n return {\n bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n elementUid: _this2.id,\n formatterKey: key\n };\n };\n return [\n // TEXT_INLINE_PLAN W8 (2026-04-24) — RichTextControl retired.\n // Canvas inline-edit host is the text-edit surface (W0.2b marker\n // + W1.1 floating toolbar + W1.2/W1.3 popovers). Sidebar is now\n // the element-level config panel only — no text-content editor.\n new FontFamilyControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n setValue: setFmt('font_family')\n }, busOpts('font_family')), new FontWeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n setValue: setFmt('font_weight')\n }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n setValue: setFmt('font_size')\n }, _objectSpread({\n defaultValue: 16,\n minValue: 8,\n maxValue: 72,\n suffix: 'px',\n allowZero: false\n }, busOpts('font_size'))), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n setValue: setFmt('text_color')\n }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n setValue: setFmt('link_color')\n }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('text_align'), {\n setValue: setFmt('text_align')\n }, ['left', 'justify', 'center', 'right'], {\n bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n elementUid: this.id,\n formatterKey: 'text_align'\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n setValue: setFmt('paragraph_spacing')\n }, {\n defaultValue: 0,\n minValue: 0,\n maxValue: 50,\n suffix: 'px',\n allowZero: true\n }), new LineHeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n setValue: setFmt('line_height')\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n setValue: setFmt('letter_spacing')\n }, {\n defaultValue: 0,\n minValue: -5,\n maxValue: 10,\n step: 0.1,\n suffix: 'px',\n allowZero: true,\n allowNegative: true\n }), new TextDirectionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n setValue: setFmt('text_direction')\n })\n // W3.8b — PaddingMarginControl removed. Padding is a\n // container-only concern (Block/Cell/Page). Formatter keys\n // remain so legacy JSON renders identically.\n ];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.text || ''), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PElement.js?");
/***/ }),
/***/ "./src/includes/PaddingMarginControl.js":
/*!**********************************************!*\
!*** ./src/includes/PaddingMarginControl.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * PaddingMarginControl — 4-side numeric editor (Top/Right/Bottom/Left)\n * used by BlockElement/CellElement/PageElement for padding. Each side\n * has stepper −/+ buttons and a direct-entry input with an explicit\n * \"Clear\" (✕) to return to the null/default state. A small live\n * preview at the top visualises how the 4 values inset an inner box\n * from the outer container.\n *\n * 2026-04-17 audit (§2.12 + UX-bugs pass): migrated from Bootstrap\n * `.input-group` + `.form-control` + `.btn btn-outline-secondary` +\n * hardcoded-color preview to the panel's `.bjs-*` primitives with\n * tokenised preview. Rows sit flush to the panel edges (parent\n * `.bjs-control-stack` provides inset — no double-padding), icon\n * buttons and the numeric input are all `var(--bjs-control-h)` tall\n * so the stepper rows look square and uniform.\n *\n * Structure stable across interactions (no innerHTML rebuild on value\n * change) — each keystroke/click mutates `input.value` + the `is-null`\n * class + preview inner-box offsets only. Per the no-flicker rule\n * (BUILDER.md Lesson 19).\n */\nvar PaddingMarginControl = /*#__PURE__*/function () {\n /**\n * @param {string} label\n * @param {object} values initial { top, right, bottom, left }\n * @param {object} callback { setValues(values) }\n * @param {object} [opts] W3.8a decoupled API. Control takes ONLY\n * primitives + pre-constructed shared singletons — NEVER an element\n * reference. See BUILDER.md \"Controls take primitives + hooks\" RULE.\n * @param {string} [opts.elementUid] primitive id used\n * to scope bus payloads + pin-set keys. Absent → pin button hidden,\n * bus inert, control behaves as the pre-W3.2 3-arg caller.\n * @param {string} [opts.namespace] defaults 'padding'.\n * A non-default value (e.g. 'block_padding') isolates pin-set +\n * bus payloads so one element can carry two controls without\n * cross-talk (Page: page_padding + block_padding).\n * @param {CanvasHighlightBus} [opts.bus] injected singleton.\n * `null` → bus emissions skipped.\n * @param {Set<string>} [opts.pinSet] injected singleton.\n * `null` → pin state lives only in-control (button still toggles\n * aria-pressed but nothing else sees it).\n */\n function PaddingMarginControl(label, values, callback) {\n var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n _classCallCheck(this, PaddingMarginControl);\n this.label = label;\n this.top = values.top !== undefined ? values.top : null;\n this.bottom = values.bottom !== undefined ? values.bottom : null;\n this.left = values.left !== undefined ? values.left : null;\n this.right = values.right !== undefined ? values.right : null;\n this.callback = callback;\n // Host-injection — supersedes the W3.8a prop-drilled bus / pinSet\n // options. Caller still passes elementUid + namespace (plain\n // primitives — host-agnostic). bus / pinSet are derived from\n // `this.host` at lookup time inside _getBus() / _getPinSet().\n this.elementUid = opts.elementUid || null;\n this.namespace = opts.namespace || 'padding';\n // Host is set later by Builder.renderElementControls (host injection).\n this.host = null;\n this._panelBlurTimer = null;\n this._panelFocusedNow = false;\n this.domNode = document.createElement('div');\n this._buildDom();\n this._bindEvents();\n this._syncPreview();\n }\n return _createClass(PaddingMarginControl, [{\n key: \"_buildDom\",\n value: function _buildDom() {\n var _this = this;\n var side = function side(name, labelKey) {\n var value = _this[name];\n var display = value === null ? '' : value;\n var nullClass = value === null ? 'is-null' : '';\n return \"\\n <div class=\\\"bjs-pm-side\\\" data-side=\\\"\".concat(name, \"\\\">\\n <label class=\\\"bjs-pm-side-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey), \"</label>\\n <div class=\\\"bjs-pm-side-stepper\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"\").concat(name, \"-clear\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('padding.clear'), \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('padding.clear'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">close</span>\\n </button>\\n <input type=\\\"number\\\" class=\\\"bjs-text-input bjs-pm-input \").concat(nullClass, \"\\\" name=\\\"\").concat(name, \"\\\" value=\\\"\").concat(display, \"\\\" placeholder=\\\"--\\\" min=\\\"0\\\" step=\\\"1\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey), \"\\\">\\n <div class=\\\"bjs-vstepper\\\" role=\\\"group\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-vstepper-btn\\\" data-control=\\\"\").concat(name, \"-increase\\\" aria-label=\\\"+\\\">\\n <span class=\\\"material-symbols-rounded\\\">arrow_drop_up</span>\\n </button>\\n <button type=\\\"button\\\" class=\\\"bjs-vstepper-btn\\\" data-control=\\\"\").concat(name, \"-decrease\\\" aria-label=\\\"\\u2212\\\">\\n <span class=\\\"material-symbols-rounded\\\">arrow_drop_down</span>\\n </button>\\n </div>\\n </div>\\n </div>\\n \");\n };\n\n // Pin toggle. Rendered only when caller provides an elementUid\n // (container elements — Block/Cell/Page). 3-arg legacy callers\n // stay pin-less. W3.3: icon + text label (\"Pin preview\" /\n // \"Pinned\") — icon alone isn't self-explanatory.\n var pinned = this._isPinned();\n var pinToggleHtml = this.elementUid ? \"\\n <button type=\\\"button\\\"\\n class=\\\"bjs-pm-pin-toggle\\\"\\n data-control=\\\"pin-toggle\\\"\\n aria-pressed=\\\"\".concat(pinned ? 'true' : 'false', \"\\\"\\n data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(pinned ? 'padding.pin_off' : 'padding.pin_on'), \"\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(pinned ? 'padding.pin_off' : 'padding.pin_on'), \"\\\">\\n <span class=\\\"material-symbols-rounded bjs-pm-pin-icon\\\" aria-hidden=\\\"true\\\">push_pin</span>\\n <span class=\\\"bjs-pm-pin-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(pinned ? 'padding.pin_label_on' : 'padding.pin_label_off'), \"</span>\\n </button>\") : '';\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-stack bjs-pm-control\\\">\\n <div class=\\\"bjs-pm-label-row\\\" style=\\\"display:flex;align-items:center;gap:8px;\\\">\\n <label class=\\\"bjs-control-label\\\" style=\\\"margin:0;\\\">\".concat(this.label, \"</label>\\n \").concat(pinToggleHtml, \"\\n </div>\\n <div class=\\\"bjs-info-banner bjs-info-banner--flush\\\" role=\\\"note\\\">\\n <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">info</span>\\n <span class=\\\"bjs-info-banner-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('padding.help'), \"</span>\\n </div>\\n <div class=\\\"bjs-pm-body\\\">\\n <div class=\\\"bjs-pm-grid\\\">\\n \").concat(side('top', 'padding.top'), \"\\n \").concat(side('left', 'padding.left'), \"\\n \").concat(side('right', 'padding.right'), \"\\n \").concat(side('bottom', 'padding.bottom'), \"\\n </div>\\n <div class=\\\"bjs-pm-preview\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"bjs-pm-preview-outer\\\" data-control=\\\"preview-outer\\\">\\n <div class=\\\"bjs-pm-preview-inner\\\" data-control=\\\"preview-inner\\\"></div>\\n </div>\\n </div>\\n </div>\\n </div>\\n \");\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this2 = this;\n ['top', 'right', 'bottom', 'left'].forEach(function (position) {\n var clearBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-clear\\\"]\"));\n var decreaseBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-decrease\\\"]\"));\n var increaseBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-increase\\\"]\"));\n var input = _this2.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n clearBtn.addEventListener('click', function () {\n return _this2.clearValue(position);\n });\n decreaseBtn.addEventListener('click', function () {\n _this2._activeSide = position;\n _this2.updateValue(position, -5);\n });\n increaseBtn.addEventListener('click', function () {\n _this2._activeSide = position;\n _this2.updateValue(position, 5);\n });\n input.addEventListener('input', function (e) {\n return _this2.setValue(position, e.target.value);\n });\n\n // PLAN_EFFECT W3.2 — emit bus events on focus/blur so the\n // PaddingVisualizerOverlay can highlight the corresponding\n // side on the canvas. No-ops for legacy callers without an\n // element (this.elementUid null → early return).\n input.addEventListener('focus', function () {\n _this2._activeSide = position;\n _this2._syncPreview();\n _this2._emitRegionFocus(position);\n _this2._notifyPanelFocus();\n });\n input.addEventListener('blur', function () {\n _this2._emitRegionBlur(position);\n // Panel-blur is deferred — if the user is tabbing to\n // another input inside the panel, a new focus fires\n // within the same microtask and cancels this timer.\n _this2._schedulePanelBlur();\n });\n });\n\n // Pin toggle click handler — scoped by elementUid presence.\n var pinBtn = this.domNode.querySelector('[data-control=\"pin-toggle\"]');\n if (pinBtn && this.elementUid) {\n pinBtn.addEventListener('click', function () {\n return _this2._togglePin();\n });\n }\n }\n\n // ─── Host injection — supersedes W3.8a prop-drilling ─────────────────\n // The control reads its bus + pin-set off `this.host` (set by\n // Builder.renderElementControls when emitted by an element's\n // getControls()). Each Builder owns its own EventEmitter +\n // _pinnedPaddingElements Set — multi-instance isolation is automatic.\n // See Lesson \"Host Injection\" in BUILDER.md.\n }, {\n key: \"_getBus\",\n value: function _getBus() {\n var _this$host;\n return ((_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events) || null;\n }\n }, {\n key: \"_getPinSet\",\n value: function _getPinSet() {\n var _this$host2;\n return ((_this$host2 = this.host) === null || _this$host2 === void 0 ? void 0 : _this$host2._pinnedPaddingElements) || null;\n }\n }, {\n key: \"_pinKey\",\n value: function _pinKey() {\n // W3.6 — default namespace keeps the bare UID for back-compat\n // with existing Set members + existing tests. Other namespaces\n // compose a distinct key so Page's Page Padding + Block Padding\n // pin independently.\n return this.namespace === 'padding' ? this.elementUid : \"\".concat(this.elementUid, \"::\").concat(this.namespace);\n }\n }, {\n key: \"_isPinned\",\n value: function _isPinned() {\n if (!this.elementUid) return false;\n var set = this._getPinSet();\n return set ? set.has(this._pinKey()) : false;\n }\n }, {\n key: \"_payload\",\n value: function _payload(extra) {\n return Object.assign({\n elementUid: this.elementUid,\n namespace: this.namespace\n }, extra || {});\n }\n }, {\n key: \"_emitRegionFocus\",\n value: function _emitRegionFocus(position) {\n if (!this.elementUid) return;\n var bus = this._getBus();\n if (bus) bus.emit('region:focus', this._payload({\n regionKey: \"padding-\".concat(position)\n }));\n }\n }, {\n key: \"_emitRegionBlur\",\n value: function _emitRegionBlur(position) {\n if (!this.elementUid) return;\n var bus = this._getBus();\n if (bus) bus.emit('region:blur', this._payload({\n regionKey: \"padding-\".concat(position)\n }));\n }\n }, {\n key: \"_notifyPanelFocus\",\n value: function _notifyPanelFocus() {\n // Cancel any pending panel-blur — a new focus inside the panel\n // means the panel is still active. Same 120ms debounce window\n // as UIManager's 50ms hover debounce (SA I1) — prevents flap\n // when Tab-ing between sides.\n if (this._panelBlurTimer) {\n clearTimeout(this._panelBlurTimer);\n this._panelBlurTimer = null;\n }\n if (this._panelFocusedNow) return;\n if (!this.elementUid) return;\n this._panelFocusedNow = true;\n var bus = this._getBus();\n if (bus) bus.emit('region:panel-focus', this._payload());\n }\n }, {\n key: \"_schedulePanelBlur\",\n value: function _schedulePanelBlur() {\n var _this3 = this;\n if (!this.elementUid) return;\n if (this._panelBlurTimer) clearTimeout(this._panelBlurTimer);\n this._panelBlurTimer = setTimeout(function () {\n _this3._panelBlurTimer = null;\n if (!_this3._panelFocusedNow) return;\n var active = document.activeElement;\n if (active && _this3.domNode.contains(active)) return;\n _this3._panelFocusedNow = false;\n var bus = _this3._getBus();\n if (bus) bus.emit('region:panel-blur', _this3._payload());\n }, 120);\n }\n\n /**\n * Hook fires after Builder.renderElementControls has appended this\n * control AND assigned `this.host`. Re-syncs the pin-toggle UI from\n * the host's pin Set — `_buildDom` ran in the constructor when\n * `this.host` was still null and rendered the button as not-pinned.\n */\n }, {\n key: \"afterRender\",\n value: function afterRender() {\n if (!this.elementUid) return;\n var pinBtn = this.domNode.querySelector('[data-control=\"pin-toggle\"]');\n if (!pinBtn) return;\n var on = this._isPinned();\n pinBtn.setAttribute('aria-pressed', on ? 'true' : 'false');\n var tipKey = on ? 'padding.pin_off' : 'padding.pin_on';\n var lblKey = on ? 'padding.pin_label_on' : 'padding.pin_label_off';\n pinBtn.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(tipKey));\n pinBtn.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(tipKey));\n var label = pinBtn.querySelector('.bjs-pm-pin-label');\n if (label) label.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(lblKey);\n }\n }, {\n key: \"_togglePin\",\n value: function _togglePin() {\n if (!this.elementUid) return;\n var set = this._getPinSet();\n var bus = this._getBus();\n if (!set) return;\n var key = this._pinKey();\n var pinBtn = this.domNode.querySelector('[data-control=\"pin-toggle\"]');\n\n // Shared DOM patch — structure preserving, no innerHTML rebuild.\n var updateBtn = function updateBtn(on) {\n if (!pinBtn) return;\n pinBtn.setAttribute('aria-pressed', on ? 'true' : 'false');\n var tipKey = on ? 'padding.pin_off' : 'padding.pin_on';\n var lblKey = on ? 'padding.pin_label_on' : 'padding.pin_label_off';\n pinBtn.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(tipKey));\n pinBtn.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(tipKey));\n var label = pinBtn.querySelector('.bjs-pm-pin-label');\n if (label) label.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(lblKey);\n };\n if (set.has(key)) {\n set[\"delete\"](key);\n if (bus) bus.emit('padding:unpin', this._payload());\n updateBtn(false);\n } else {\n set.add(key);\n if (bus) bus.emit('padding:pin', this._payload());\n updateBtn(true);\n }\n }\n }, {\n key: \"clearValue\",\n value: function clearValue(position) {\n this[position] = null;\n var input = this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n input.value = '';\n input.classList.add('is-null');\n this.callback.setValues(this.getValues());\n this._syncPreview();\n }\n }, {\n key: \"updateValue\",\n value: function updateValue(position, delta) {\n var currentValue = this[position] === null ? 0 : this[position];\n this[position] = Math.max(0, currentValue + delta);\n var input = this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n input.value = this[position];\n input.classList.remove('is-null');\n this.callback.setValues(this.getValues());\n this._syncPreview();\n }\n }, {\n key: \"setValue\",\n value: function setValue(position, value) {\n if (value === '' || value === null || value === undefined) {\n this[position] = null;\n this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\")).classList.add('is-null');\n } else {\n this[position] = Math.max(0, parseInt(value) || 0);\n this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\")).classList.remove('is-null');\n }\n this.callback.setValues(this.getValues());\n this._syncPreview();\n }\n }, {\n key: \"getValues\",\n value: function getValues() {\n return {\n top: this.top,\n bottom: this.bottom,\n left: this.left,\n right: this.right\n };\n }\n\n // Scales the 4 values into inset-from-each-edge pixels so the inner\n // box visibly shrinks in proportion to the padding. The preview is\n // 72×72; each inset is capped so the inner box never collapses\n // completely when users push large values on opposing sides.\n }, {\n key: \"_syncPreview\",\n value: function _syncPreview() {\n var inner = this.domNode.querySelector('[data-control=\"preview-inner\"]');\n if (!inner) return;\n var clamp = function clamp(v) {\n var n = v == null ? 0 : parseInt(v, 10) || 0;\n // 50px padding ≈ 10px inset; max 22px so top+bottom (or left+right)\n // combined can be ≤44px, leaving ≥28px inner content.\n return Math.max(0, Math.min(22, Math.round(n / 5)));\n };\n inner.style.top = clamp(this.top) + 'px';\n inner.style.right = clamp(this.right) + 'px';\n inner.style.bottom = clamp(this.bottom) + 'px';\n inner.style.left = clamp(this.left) + 'px';\n }\n\n /**\n * PLAN_EFFECT W3.2 — the legacy `renderRuler` / `renderEdgeRuler` /\n * `createRulerEl` / `hideRuler` methods lived here pre-2026-04-19.\n * They rendered a translucent band + \"Npx\" label directly in the\n * host document on every input focus. The approach suffered three\n * bugs (wrong-side label for top, stale `0px` when value was the\n * active one, forced disappear via setTimeout clashing with the\n * user's focus cadence).\n *\n * Replaced by the Canvas Highlight Bus + PaddingVisualizerOverlay\n * (W0.1 + W0.2). This control now only emits events; the overlay\n * owns all on-canvas visualisation. All 4 sides react simultaneously\n * to panel focus; a single side gets emphasis when its input is\n * focused specifically. See docs/core/OVERLAY.md §18 + §5.7.\n */\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PaddingMarginControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PaddingMarginControl.js?");
/***/ }),
/***/ "./src/includes/PageElement.js":
/*!*************************************!*\
!*** ./src/includes/PageElement.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _RangeControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./RangeControl.js */ \"./src/includes/RangeControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _DropdownControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./DropdownControl.js */ \"./src/includes/DropdownControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./overlays/PaddingVisualizerOverlay.js */ \"./src/includes/overlays/PaddingVisualizerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\nvar PageElement = /*#__PURE__*/function (_BaseElement) {\n function PageElement(builder) {\n var _this;\n _classCallCheck(this, PageElement);\n _this = _callSuper(this, PageElement); // Call the parent class constructor\n _this.builder = builder;\n _this.blocks = [];\n _this.iframe = null; // Reference to the iframe\n\n //\n _this.template = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['page'];\n\n // \n _this.page_title = null;\n\n // Formatter\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]({\n // background\n background_color: null,\n background_image: null,\n background_position: null,\n background_size: null,\n background_repeat: null,\n background_blend_mode: null,\n opacity: null,\n filter: null,\n // padding\n padding_top: 0,\n padding_right: 0,\n padding_bottom: 0,\n padding_left: 0,\n // typography\n font_family: null\n });\n\n // more attributes\n _this.block_gap = 0;\n\n // container width\n _this.container_width = 'auto';\n\n // block padding\n _this.block_padding_bottom = 0;\n _this.block_padding_top = 0;\n _this.block_padding_right = 0;\n _this.block_padding_left = 0;\n\n // default block background color\n _this.default_block_background_color = null;\n return _this;\n }\n _inherits(PageElement, _BaseElement);\n return _createClass(PageElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.page');\n }\n }, {\n key: \"isDroppable\",\n value: function isDroppable() {\n return true;\n }\n\n /**\n * PLAN_EFFECT W3.6 — Page Padding visualiser.\n *\n * Mounts a single overlay under the default 'padding' namespace that\n * tracks the page's own padding_top/right/bottom/left (formatter-\n * backed). The Block Padding control on PageElement uses a separate\n * namespace ('block_padding') — its overlay belongs on each child\n * Block that cascades from page.block_padding_* (lands in W3.7);\n * drawing one giant overlay at the Page level for \"block default\n * padding\" would be visually confusing, so we don't.\n */\n }, {\n key: \"getOverlays\",\n value: function getOverlays() {\n // Always emit; overlay self-disposes in afterMount() when host's\n // usePaddingVisualizer flag is off. (See CellElement /\n // BlockElement for the same pattern + rationale.)\n return [new _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](this)];\n }\n\n /** Host-injection recursion hook — returns this page's blocks so\n * Builder._adopt() can walk down the tree. See BUILDER.md \"Host\n * Injection\" lesson. */\n }, {\n key: \"getChildren\",\n value: function getChildren() {\n return this.blocks || [];\n }\n }, {\n key: \"canDropInside\",\n value: function canDropInside() {\n // ─────────────────────────────────────────────────────────────────\n // RULE: drop-inside is allowed on a PageElement ONLY when it's empty.\n // ─────────────────────────────────────────────────────────────────\n //\n // Why this rule exists:\n // Previously canDropInside() always returned true. When the user\n // dragged a widget over a page that already contained blocks, the\n // *entire page* lit up with the drop-inside highlight. The user\n // could not tell where the new block would land — and on drop, it\n // silently appended to the bottom of the page (appendBlock). That\n // is bad UX: the highlight does not match the actual landing spot.\n //\n // The new rule:\n // • Empty page → drop-inside is allowed. The whole page lights up,\n // the user drops anywhere, the block becomes the first child.\n // This is the only situation where \"drop anywhere inside\" makes\n // sense, because there is no other reference point.\n // • Page with ≥1 block → drop-inside is DISABLED. The user must\n // hover an existing block and drop above/below it (handled by\n // BlockElement.canDropBefore / canDropAfter). The landing\n // position is then unambiguous and matches the highlight.\n //\n // Where this is enforced:\n // UIManager.dragOver() consults canDropInside() AFTER checking\n // canDropBefore/canDropAfter, so blocks always win over the page.\n // When this method returns false and the user is hovering directly\n // on the page background (not on any block), no highlight appears\n // and UIManager.drop() is a no-op for that target. The user gets\n // immediate visual feedback that \"you must drop on a block\".\n //\n // Mirrored in CellElement.canDropInside() — same rule, same reason.\n //\n // Regression tests: e2e/drop-inside-empty-only.spec.js\n return this.blocks.length === 0;\n }\n }, {\n key: \"render\",\n value: function () {\n var _render = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var _this2 = this;\n var htmlContent, parser, doc, iframe, docx, scrollTop;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n //\n htmlContent = this.renderTemplate({\n page: '<div builder-element=\"PageElement\"></div>',\n // page title\n page_title: this.page_title || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('page.untitled'),\n // Formatter (also pass formats string for templates that consume it)\n formats: this.formatter.getFormats(),\n // more attributes\n block_gap: this.block_gap,\n // container width\n container_width: this.container_width,\n // block padding\n block_padding_bottom: this.block_padding_bottom,\n block_padding_top: this.block_padding_top,\n block_padding_right: this.block_padding_right,\n block_padding_left: this.block_padding_left,\n // default block background color\n default_block_background_color: this.default_block_background_color\n }); // parse data first time then re-render if second time\n if (!this.domNode) {\n // write to iframe\n this.builder.iframeDoc.open();\n this.builder.iframeDoc.write(htmlContent);\n this.builder.iframeDoc.close();\n\n // set page dom\n this.domNode = this.builder.iframeDoc.body.querySelector('[builder-element=\"PageElement\"]');\n\n // initialize UI manager: for drag and drop, hovering, etc. @todo: clean it up later\n this.builder.uiManager.init();\n this.builder.uiManager.addElement(this);\n } else {\n // inside htmlContent get <head> only and re-render current iframe head\n parser = new DOMParser();\n doc = parser.parseFromString(htmlContent, 'text/html'); // replace head\n this.builder.iframeDoc.head.innerHTML = doc.head.innerHTML;\n\n // Reset the page body container before appending the new\n // block list. `parse()` already wipes it via `removeAllBlocks`,\n // but the host can also call `builder.render()` after a direct\n // `builder.data = ...` assignment without going through parse\n // (the legacy demo/element.php's AI applyPageData was the\n // original driver — its `applyPageData` callback assigned to\n // `builder.data` then called `builder.render()` directly) —\n // without this,\n // re-renders would stack child block DOM on top of stale DOM\n // from the previous render, producing the duplicate-DOM jitter\n // we observed on undo/redo + AI replace flows.\n if (this.domNode) this.domNode.innerHTML = '';\n }\n\n // The head replacement above (and the initial iframeDoc.write on first\n // render) wipes any builder-helper <style> we injected previously —\n // most critically the autosize override that pins PageElement\n // min-height to 0 instead of 100vh. Re-inject so the next syncHeight()\n // pass measures the page without the viewport-unit feedback loop.\n // Idempotent — bails fast when helpers are already present.\n if (typeof this.builder._injectIframeHelpers === 'function') {\n this.builder._injectIframeHelpers();\n }\n\n // save current scroll position\n iframe = this.host.iframe;\n docx = iframe.contentDocument || iframe.contentWindow.document;\n scrollTop = docx.documentElement.scrollTop || docx.body.scrollTop; //\n this.blocks.forEach(function (block) {\n // render block\n var domNode = block.render();\n\n // Dome append child\n _this2.domNode.appendChild(domNode);\n\n //\n _this2.host.uiManager.addElement(block);\n _this2.host.uiManager.addDraggableItem(block);\n });\n\n // Empty page placeholder — share helpers with the surgical\n // removeElement / addBlock* paths so the placeholder transition\n // logic has a single source of truth.\n if (this.blocks.length === 0) {\n this._showEmptyPlaceholder();\n } else {\n this._hideEmptyPlaceholder();\n }\n\n // formats\n this.domNode.style.cssText = this.formatter.toStyleStringAll();\n\n // restore scroll position\n docx.documentElement.scrollTop = scrollTop;\n docx.body.scrollTop = scrollTop;\n return _context.abrupt(\"return\", this.domNode);\n case 12:\n case \"end\":\n return _context.stop();\n }\n }, _callee, this);\n }));\n function render() {\n return _render.apply(this, arguments);\n }\n return render;\n }()\n }, {\n key: \"addBlockAfter\",\n value: function addBlockAfter(newBlock, referenceBlock) {\n newBlock.container = this; // set container\n\n var index = this.blocks.indexOf(referenceBlock);\n if (index === -1) {\n throw new Error('Reference block not found');\n }\n this.blocks.splice(index + 1, 0, newBlock);\n this._mountBlockDom(newBlock, {\n afterDomNode: referenceBlock.domNode\n });\n }\n }, {\n key: \"addBlockBefore\",\n value: function addBlockBefore(newBlock, referenceBlock) {\n newBlock.container = this; // set container\n\n var index = this.blocks.indexOf(referenceBlock);\n if (index === -1) {\n throw new Error('Reference block not found');\n }\n this.blocks.splice(index, 0, newBlock);\n this._mountBlockDom(newBlock, {\n beforeDomNode: referenceBlock.domNode\n });\n }\n\n /**\n * Empty-page placeholder helpers — extracted so the surgical\n * removeElement / addBlock* paths use the same logic as the full\n * `render()` path. Idempotent.\n */\n }, {\n key: \"_emptyPlaceholderHtml\",\n value: function _emptyPlaceholderHtml() {\n return \"<div data-control=\\\"page-empty-placeholder\\\" style=\\\"display: flex;\\n align-items: center;\\n justify-content: center;\\n min-height: 480px;\\n background-color: rgba(34,83,159,0.05);\\n border: dashed 1px rgba(120, 130, 150, 0.5);\\n \\\">\\n <svg style=\\\"width: 100px;\\n display: inline-block;\\n margin: auto;\\n opacity: 1;\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"48px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"48px\\\" fill=\\\"#808080\\\"><path d=\\\"M345-285q-24 0-42-18t-18-42v-435q0-24 18-42t42-18h435q24 0 42 18t18 42v435q0 24-18 42t-42 18H345Zm0-60h435v-435H345v435ZM149.82-615q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Z\\\"/></svg>\\n\\n </div>\";\n }\n }, {\n key: \"_showEmptyPlaceholder\",\n value: function _showEmptyPlaceholder() {\n if (!this.domNode) return;\n if (this.domNode.querySelector('[data-control=\"page-empty-placeholder\"]')) return;\n this.domNode.insertAdjacentHTML('beforeend', this._emptyPlaceholderHtml());\n }\n }, {\n key: \"_hideEmptyPlaceholder\",\n value: function _hideEmptyPlaceholder() {\n if (!this.domNode) return;\n var ph = this.domNode.querySelector('[data-control=\"page-empty-placeholder\"]');\n if (ph) ph.remove();\n }\n\n /**\n * Mount a freshly-added block into the live DOM at the right\n * position. Called from the surgical add paths (`addBlockBefore`,\n * `addBlockAfter`, `appendBlock`). Hides the empty-page placeholder.\n *\n * `position` is one of:\n * - { afterDomNode: ref } — insert after `ref`\n * - { beforeDomNode: ref } — insert before `ref`\n * - { append: true } — append at end\n *\n * No-op if `this.domNode` isn't mounted yet (block was added before\n * first PageElement.render); the full render path will pick it up.\n */\n }, {\n key: \"_mountBlockDom\",\n value: function _mountBlockDom(block, position) {\n if (!this.domNode) return;\n this._hideEmptyPlaceholder();\n var rendered = block.render();\n if (position && position.afterDomNode && position.afterDomNode.parentNode === this.domNode) {\n this.domNode.insertBefore(rendered, position.afterDomNode.nextSibling);\n } else if (position && position.beforeDomNode && position.beforeDomNode.parentNode === this.domNode) {\n this.domNode.insertBefore(rendered, position.beforeDomNode);\n } else {\n this.domNode.appendChild(rendered);\n }\n if (this.builder && this.builder.uiManager) {\n this.builder.uiManager.addElement(block);\n this.builder.uiManager.addDraggableItem(block);\n }\n }\n\n /**\n * Programmatic mass-teardown — used by `parse()` and `clear()`.\n *\n * Why NOT route through `block.remove()` (the user-delete API)?\n * 1. `BaseElement.remove()` fires `commit('history.structure_remove')`\n * in its fadeOut callback — outside `_apply`, this leaks N entries\n * per cleared page (one per block), spamming the history dropdown\n * with \"Delete Block\" rows on every clear/template-swap/AI-replace.\n * 2. Its callback calls `container.removeElement(this)` which itself\n * triggers a full `PageElement.render()` mid-iteration — N nested\n * re-renders + N head replacements during a single clear, causing\n * visible reflow storm.\n * 3. During HistoryManager `_apply`, `fadeOut` early-returns\n * synchronously WITHOUT setting `display: none` (that's only set in\n * the `transitionend` handler) — so old block DOM stays visible\n * while the next render appends new ones, causing the duplicate-DOM\n * jitter on undo/redo.\n *\n * This path does the minimal correct teardown: detach overlays, drop\n * UIManager registrations, wipe the body container in one shot.\n */\n }, {\n key: \"removeAllBlocks\",\n value: function removeAllBlocks() {\n var _this3 = this;\n this.blocks.forEach(function (block) {\n block.unmountOverlays('*');\n _this3.builder.uiManager.removeElement(block);\n _this3.builder.uiManager.removeDraggableItem(block);\n });\n // Reset hover/drag-over lists wholesale — references to torn-down\n // blocks would otherwise linger and break highlight cleanup.\n this.builder.uiManager.dragOveringElements = [];\n this.builder.uiManager.hoveringElements = [];\n\n // Unselect — every block instance (and every descendant element\n // instance held by them) is about to be discarded; any selection\n // pointer would dangle into a torn-down element.\n if (typeof this.builder.getSelectedElement === 'function' && this.builder.getSelectedElement() && typeof this.builder.unselect === 'function') {\n this.builder.unselect();\n }\n this.blocks = [];\n\n // Wholesale DOM clear — kills orphan child DOM, drag anchors, any\n // overlay residue. Cheaper + less buggy than per-block DOM surgery.\n if (this.domNode) this.domNode.innerHTML = '';\n }\n }, {\n key: \"clear\",\n value: function clear() {\n this.removeAllBlocks();\n this.render();\n }\n }, {\n key: \"appendBlock\",\n value: function appendBlock(block) {\n // private\n block.container = this; // set container\n\n // Host injection — adopt the new block before it joins the page\n // tree so its overlays + control emissions can reach the bus\n // from first render. UIManager.addBlockInside also pre-adopts at\n // its boundary; double-adopt is a no-op (idempotent).\n if (this.host && typeof this.host._adopt === 'function') {\n this.host._adopt(block);\n }\n\n // Add block to blocks array.\n this.blocks.push(block);\n\n // Surgical DOM mount when the page is already live. During\n // `parse()` the page hasn't rendered yet (domNode null), so\n // `_mountBlockDom` is a no-op and the full `render()` that\n // follows picks up the block.\n this._mountBlockDom(block, {\n append: true\n });\n }\n\n /**\n * Surgical remove — BUILDER.md Lesson 21 + customer fix 2026-05-20.\n *\n * Pre-fix this called `this.render()`, which wipes iframe head + body\n * and re-renders EVERY remaining block. Each block's `_doRender()`\n * then assigned `domNode.innerHTML = …`, round-tripping its children's\n * `this.text` through the HTML5 fragment parser. With customer content\n * that contained `<div>` block children inside a `<p inline-edit>`\n * (Chrome's default-paragraph-separator behaviour), the parser auto-\n * closed the `<p>` and kicked the `<div>` content out — stripping\n * inline `font-weight` / `text-align` / `font-family`. Even after\n * defence-in-depth (defaultParagraphSeparator + InlineSanitizer\n * unwrap) the cascade re-render is wasteful and triggers a\n * MutationObserver firehose in host integrations (acelle's blade\n * pushes one history snapshot per mutation).\n *\n * Surgical path: drop from blocks array, detach domNode, transition\n * the empty placeholder. Sibling DOM untouched — every contenteditable\n * cursor, sidebar control closure, overlay anchor, UIManager\n * registration survives byte-perfect.\n */\n }, {\n key: \"removeElement\",\n value: function removeElement(element) {\n var idx = this.blocks.indexOf(element);\n if (idx === -1) return;\n this.blocks.splice(idx, 1);\n if (element.domNode && element.domNode.parentNode) {\n element.domNode.remove();\n }\n if (this.blocks.length === 0) {\n this._showEmptyPlaceholder();\n }\n }\n }, {\n key: \"insertElementAfter\",\n value: function insertElementAfter(element, newElement) {\n newElement.container = this; // set container\n\n var idx = this.blocks.indexOf(element);\n if (idx === -1) return;\n this.blocks.splice(idx + 1, 0, newElement);\n this._mountBlockDom(newElement, {\n afterDomNode: element.domNode\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n // Return JSON encoded representation of the PageElement\n return _objectSpread(_objectSpread({}, _superPropGet(PageElement, \"getData\", this, 3)([])), {}, {\n page_title: this.page_title,\n blocks: this.blocks.map(function (block) {\n return block.getData();\n }),\n block_gap: this.block_gap,\n container_width: this.container_width,\n block_padding_bottom: this.block_padding_bottom,\n block_padding_top: this.block_padding_top,\n block_padding_right: this.block_padding_right,\n block_padding_left: this.block_padding_left,\n default_block_background_color: this.default_block_background_color\n });\n }\n }, {\n key: \"parse\",\n value: function parse(data) {\n var _this4 = this;\n // Clear existing blocks\n this.removeAllBlocks();\n\n // Guard: if data is null/undefined or missing required fields,\n // initialize with safe defaults so the builder opens an empty canvas\n // instead of crashing with a TypeError.\n if (!data || _typeof(data) !== 'object') {\n data = {\n template: 'Page',\n blocks: []\n };\n }\n\n // Set template\n this.template = data.template || 'Page';\n\n // Parse blocks\n (data.blocks || []).forEach(function (blockData) {\n var block = _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(blockData);\n block.container = _this4;\n _this4.appendBlock(block);\n });\n\n // page title\n this.page_title = data.page_title || null;\n\n // Formatter\n this.formatter.parseFormats(data.formats || {});\n\n // more attributes\n this.block_gap = data.block_gap || 0;\n\n // container width\n this.container_width = data.container_width || 'auto';\n\n // block padding\n this.block_padding_bottom = data.block_padding_bottom || 0;\n this.block_padding_top = data.block_padding_top || 0;\n this.block_padding_right = data.block_padding_right || 0;\n this.block_padding_left = data.block_padding_left || 0;\n\n // default block background color\n this.default_block_background_color = data.default_block_background_color || null;\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this5 = this;\n return [new _RangeControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](\n //label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.block_gap'),\n // current value\n this.block_gap,\n // min\n 0,\n // max\n 500,\n // unit\n 'px',\n // step\n 1,\n // callback\n function (value) {\n _this5.block_gap = value;\n _this5.render();\n }), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n setValue: function setValue(value) {\n _this5.formatter.setFormat('font_family', value);\n _this5.render();\n }\n }), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.container_width'), this.container_width || 'auto', [{\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.auto_full'),\n value: 'auto'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.narrow'),\n value: 'narrow'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.medium'),\n value: 'medium'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.wide'),\n value: 'wide'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.xl'),\n value: 'xl'\n }, {\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.full_bleed'),\n value: 'full'\n }], function (value) {\n _this5.container_width = value || 'auto';\n _this5.render();\n }), new _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.page_padding'),\n // value\n {\n top: this.formatter.getFormat('padding_top'),\n right: this.formatter.getFormat('padding_right'),\n bottom: this.formatter.getFormat('padding_bottom'),\n left: this.formatter.getFormat('padding_left')\n },\n // callback\n {\n setValues: function setValues(values) {\n _this5.formatter.setFormat('padding_top', values.top);\n _this5.formatter.setFormat('padding_right', values.right);\n _this5.formatter.setFormat('padding_bottom', values.bottom);\n _this5.formatter.setFormat('padding_left', values.left);\n _this5.render();\n }\n },\n // Host-injection — control reads bus + pinSet off\n // `this.host` directly. No prop-drilling needed.\n {\n elementUid: this.id\n }), new _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.block_padding'),\n // value\n {\n top: this.block_padding_top,\n right: this.block_padding_right,\n bottom: this.block_padding_bottom,\n left: this.block_padding_left\n },\n // callback\n {\n setValues: function setValues(values) {\n _this5.block_padding_top = values.top;\n _this5.block_padding_right = values.right;\n _this5.block_padding_bottom = values.bottom;\n _this5.block_padding_left = values.left;\n _this5.render();\n }\n },\n // Host-injection — namespace isolates this Block-Padding\n // control from the Page-Padding one above so their\n // bus events don't cross-talk on the same element.\n {\n elementUid: this.id,\n namespace: 'block_padding'\n }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.default_block_background'), this.default_block_background_color, {\n setValue: function setValue(value) {\n _this5.default_block_background_color = value;\n _this5.render();\n }\n }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n color: this.formatter.getFormat('background_color'),\n image: this.formatter.getFormat('background_image'),\n position: this.formatter.getFormat('background_position'),\n size: this.formatter.getFormat('background_size'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat'),\n blendMode: this.formatter.getFormat('background_blend_mode', 'normal'),\n opacity: Math.round((parseFloat(this.formatter.getFormat('opacity', 1)) || 1) * 100),\n filter: this.formatter.getFormat('filter', '')\n }, {\n setBackground: function setBackground(values) {\n _this5.formatter.setFormat('background_color', values.color);\n _this5.formatter.setFormat('background_image', values.image);\n _this5.formatter.setFormat('background_position', values.position);\n _this5.formatter.setFormat('background_size', values.size);\n _this5.formatter.setFormat('background_repeat', values.repeat);\n _this5.formatter.setFormat('background_blend_mode', values.blendMode === 'normal' ? null : values.blendMode);\n _this5.formatter.setFormat('opacity', values.opacity === 1 ? null : values.opacity);\n _this5.formatter.setFormat('filter', values.filter || null);\n _this5.render();\n }\n })];\n }\n }, {\n key: \"getActions\",\n value: function getActions() {\n var _this6 = this;\n var actions = [];\n actions.push({\n icon: 'remove_selection',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('actions.unselect'),\n run: function run() {\n _this6.host.unselect();\n }\n });\n return actions;\n }\n }, {\n key: \"addContainerHightlight\",\n value: function addContainerHightlight() {\n // do nothing\n }\n }, {\n key: \"removeContainerHightlight\",\n value: function removeContainerHightlight() {\n // do nothing\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PageElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PageElement.js?");
/***/ }),
/***/ "./src/includes/ParagraphSpacingControl.js":
/*!*************************************************!*\
!*** ./src/includes/ParagraphSpacingControl.js ***!
\*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar ParagraphSpacingControl = /*#__PURE__*/function () {\n function ParagraphSpacingControl(label, value, callback) {\n _classCallCheck(this, ParagraphSpacingControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n // Initialize properties\n this.label = label; // Label for the text control\n this.value = value; // Initial /* left | center | right */\n this.callback = callback; // Callback function to handle input changes\n\n // Create the main container element\n this.domNode = document.createElement(\"div\");\n\n //\n this.render(); // Call the render method to create the UI\n }\n return _createClass(ParagraphSpacingControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n this.domNode.innerHTML = \"<div class=\\\"py-2 ps-3 pe-3 w-100 d-flex align-items-center justify-content-between\\\">\\n <label for=\\\"\".concat(this.id, \"\\\" class=\\\"form-label fw-semibold mb-0 me-3\\\">\").concat(this.label, \"</label>\\n\\n\\n <div class=\\\"input-group flex-nowrap w-25 \\\" role=\\\"group\\\" aria-label=\\\"\").concat(this.label, \"\\\" style=\\\"min-width:140px; height: 32px;\\\">\\n <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"reduction\\\" type=\\\"button\\\">-</button>\\n <input id=\\\"\").concat(this.id, \"\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-control text-center\\\" style=\\\"font-size: 0.875em;\\\" readonly>\\n <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"increment\\\" type=\\\"button\\\">+</button>\\n </div>\\n </div>\");\n var decrease = this.domNode.querySelector('[role=\"reduction\"]');\n var increase = this.domNode.querySelector('[role=\"increment\"]');\n var input = this.domNode.querySelector(\"#\".concat(this.id));\n var step = 1;\n var changeValue = function changeValue(delta) {\n var numeric = parseFloat(_this.value);\n if (isNaN(numeric)) numeric = 0;\n numeric = numeric + delta;\n numeric = Math.max(0, numeric); // allow 0 and fractional values\n // round to one decimal to avoid float noise\n numeric = Math.round(numeric * 10) / 10;\n _this.setValue(numeric);\n };\n if (decrease) {\n decrease.addEventListener('click', function (e) {\n e.preventDefault();\n changeValue(-step);\n });\n }\n if (increase) {\n increase.addEventListener('click', function (e) {\n e.preventDefault();\n changeValue(step);\n });\n }\n\n // allow direct programmatic update keeping UI in sync\n this._inputNode = input;\n\n // normalize initial display\n // this.setValue(this.value === undefined ? 0 : this.value);\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n // Method to set value programmatically\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.value = newValue;\n var input = this.domNode.querySelector('input');\n if (input) {\n input.value = this.value;\n }\n\n // Support both function and object with setValue\n if (typeof this.callback === 'function') {\n this.callback(this.value);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(this.value);\n }\n }\n\n // Method to get current value\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ParagraphSpacingControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ParagraphSpacingControl.js?");
/***/ }),
/***/ "./src/includes/ParagraphWidget.js":
/*!*****************************************!*\
!*** ./src/includes/ParagraphWidget.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ParagraphWidget = /*#__PURE__*/function (_BaseWidget) {\n function ParagraphWidget() {\n var _this;\n _classCallCheck(this, ParagraphWidget);\n _this = _callSuper(this, ParagraphWidget); // Call the parent class constructor\n\n // New element for Paragraph\n var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'This is a sample paragraph.');\n\n // Append the new element to the block\n _this.block.appendElements([p]);\n return _this;\n }\n _inherits(ParagraphWidget, _BaseWidget);\n return _createClass(ParagraphWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.paragraph');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'subject';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ParagraphWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ParagraphWidget.js?");
/***/ }),
/***/ "./src/includes/PointerCaptureRegistry.js":
/*!************************************************!*\
!*** ./src/includes/PointerCaptureRegistry.js ***!
\************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/*\n * PointerCaptureRegistry — single source of truth for \"is a drag in flight?\"\n *\n * See docs/core/OVERLAY.md §10 for full spec.\n * See docs/archived/OVERLAY_PLAN.md §4.I5 for the lostpointercapture invariant.\n *\n * What this registry DOES:\n * - Acquire pointer capture on a DOM node (wraps setPointerCapture + try/catch).\n * - Track all currently-captured nodes in a Set.\n * - Auto-cleanup via `lostpointercapture` listener when a node is detached\n * mid-drag (W3C spec: browser silently releases capture; pointerup may\n * NOT fire reliably on Safari).\n * - Expose hasActive() for UIManager to suspend hover recompute during\n * active drags (pointerdown → pointerup).\n *\n * What this registry DOES NOT do:\n * - Replace the 50ms _hideTimeout debounce in UIManager.mouseout. That\n * debounce fixes idle-hover ping-pong (user hovering with NO button\n * pressed) — pointer capture only activates on pointerdown. Different\n * bug class. The debounce stays. (§4.I1)\n *\n * Used by:\n * - DraggableHandleOverlay (pointer-driven gestures: grid separator, crop,\n * resize corner)\n *\n * NOT used by:\n * - NativeDragHandleOverlay (HTML5 DnD participants: Block drag anchor).\n * Those wire dragstart only; pointer capture is incompatible with HTML5\n * DnD on the same node (§4.I2).\n */\nvar active = new Set();\nvar PointerCaptureRegistry = {\n /**\n * Acquire pointer capture on `node` for `pointerId`. MUST be called\n * from a pointerdown handler. Registers automatic cleanup on\n * `lostpointercapture` so detaching `node` mid-drag doesn't leak\n * the registry (§4.I5).\n */\n acquire: function acquire(node, pointerId) {\n try {\n node.setPointerCapture(pointerId);\n } catch (_) {\n // Some browsers throw if node is detached or pointer already released.\n // Non-fatal — don't poison the registry.\n return;\n }\n active.add(node);\n\n // W3C: if the captured node is removed from the DOM, the browser\n // releases capture silently. pointerup may NOT fire on all browsers\n // (Safari is unreliable). `lostpointercapture` DOES fire in that\n // case. Without this listener, the Set would leak → hasActive()\n // returns true forever → UIManager hover frozen forever.\n var _onLost = function onLost() {\n active[\"delete\"](node);\n node.removeEventListener('lostpointercapture', _onLost);\n };\n node.addEventListener('lostpointercapture', _onLost);\n },\n /**\n * Release pointer capture. MUST be called from pointerup / pointercancel.\n * Internally try/catch-guarded — browser may have already released.\n */\n release: function release(node, pointerId) {\n try {\n node.releasePointerCapture(pointerId);\n } catch (_) {}\n active[\"delete\"](node);\n },\n /**\n * Returns true iff at least one pointer is currently captured on any node.\n * Read by UIManager.mouseover/out at line 1 to suspend hover recompute\n * during active drags. Inexpensive (Set.size > 0).\n */\n hasActive: function hasActive() {\n return active.size > 0;\n },\n /**\n * Dev-mode peek — testing only. Do NOT branch production logic on this.\n */\n _activeCount: function _activeCount() {\n return active.size;\n }\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PointerCaptureRegistry);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PointerCaptureRegistry.js?");
/***/ }),
/***/ "./src/includes/PricingCardElement.js":
/*!********************************************!*\
!*** ./src/includes/PricingCardElement.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _CellElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CellElement.js */ \"./src/includes/CellElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./IconPickerControl.js */ \"./src/includes/IconPickerControl.js\");\n/* harmony import */ var _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./InfoBannerControl.js */ \"./src/includes/InfoBannerControl.js\");\n/* harmony import */ var _ActionButtonControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ActionButtonControl.js */ \"./src/includes/ActionButtonControl.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\n/* harmony import */ var _ButtonElement_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./ButtonElement.js */ \"./src/includes/ButtonElement.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * PricingCardElement — a Cell that visually presents itself as a pricing card.\n *\n * Different from a plain CellElement in four ways:\n * 1. Uses template \"PricingCard\" — the cell DOM is wrapped in a styled\n * <section class=\"pricing-card\"> whose visual treatment (radius / pad /\n * shadow / border / bg) is driven by the parent PricingCardsElement's\n * `style` prop, combined with this cell's own meta (highlighted, badge,\n * icon, accent_color). One template, ten style branches, fully inline.\n * 2. Card-level metadata lives on the cell (highlighted, badge, icon,\n * accent_color). The children (Heading, PElements, Button…) stay native\n * and editable through their own controls — we never wrap them in the\n * RichText blob pattern the retired PricingTableElement used.\n * 3. Overrides `renderEmptyPlaceholder()` with a pricing-specific dashed\n * card that invites the user to drop plan content (heading, price, CTA).\n * 4. Overrides `canDropOn()` to reject drops *of* this cell INTO another\n * cell (mirrors the CellElement rule — cells never nest inside cells).\n *\n * Retired legacy: PricingTableElement (HTML blob) + PricingGridElement\n * (orphan prototype). See docs/plans/DESIGN_PRICING_ELEMENT.md.\n */\nvar PricingCardElement = /*#__PURE__*/function (_CellElement) {\n function PricingCardElement(template) {\n var _this;\n var meta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, PricingCardElement);\n _this = _callSuper(this, PricingCardElement, [template]);\n _this.highlighted = !!meta.highlighted;\n _this.badge = typeof meta.badge === 'string' ? meta.badge : '';\n _this.icon = typeof meta.icon === 'string' ? meta.icon : '';\n _this.accent_color = typeof meta.accent_color === 'string' ? meta.accent_color : '';\n return _this;\n }\n\n // Hard-code class name so webpack can't mangle it — getData() must always\n // write `name: \"PricingCardElement\"` so the registry lookup succeeds.\n _inherits(PricingCardElement, _CellElement);\n return _createClass(PricingCardElement, [{\n key: \"getClassName\",\n value: function getClassName() {\n return 'PricingCardElement';\n }\n }, {\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.pricing_card');\n }\n }, {\n key: \"getStyle\",\n value: function getStyle() {\n return this.container && this.container.style || 'minimal';\n }\n\n // Override CellElement.isHoverable() (false by default). Pricing cards\n // are self-contained visual units — users should hover/click the whole\n // card to select it (then the panel reveals card-meta controls). Without\n // this, hover feedback only appears on inner native elements, making\n // \"select the card\" feel invisible.\n }, {\n key: \"isHoverable\",\n value: function isHoverable() {\n return true;\n }\n }, {\n key: \"getResolvedAccent\",\n value: function getResolvedAccent() {\n if (this.accent_color && String(this.accent_color).trim()) return this.accent_color;\n var fallback = PricingCardElement.STYLE_ACCENTS[this.getStyle()];\n return fallback || '#ffcc2a';\n }\n\n // Walk the cell's blocks and collect every element. Used by the\n // style-preset applier to tour buttons + text elements and push\n // style-consistent formats onto their Formatters. `instanceof` (not\n // getClassName()) because webpack can mangle constructor.name in\n // production and break a string comparison.\n }, {\n key: \"_collectElements\",\n value: function _collectElements() {\n var out = [];\n (this.blocks || []).forEach(function (block) {\n (block.elements || []).forEach(function (el) {\n if (el) out.push(el);\n });\n });\n return out;\n }\n\n // Semantic role for an element in the pricing-card context. We tag\n // elements at newCell() time (`el._pricing_role = 'heading'|…`) and\n // read that tag here. If the tag is missing (card was loaded from\n // older JSON, or user added a custom element), fall back to a\n // positional heuristic: HeadingElement → heading; first big-font\n // PElement → price; small PElement directly after heading → desc;\n // etc. The heuristic is only used when no explicit role tag exists,\n // so custom user elements won't be mis-themed once they've been\n // re-authored.\n }, {\n key: \"_roleOf\",\n value: function _roleOf(el, index, all) {\n if (el && typeof el._pricing_role === 'string' && el._pricing_role) {\n return el._pricing_role;\n }\n if (el instanceof _ButtonElement_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"]) return 'cta';\n if (el instanceof _HeadingElement_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"]) return 'heading';\n if (el instanceof _PElement_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"]) {\n var size = parseInt(el.formatter.getFormat('font_size'), 10) || 16;\n if (size >= 28) return 'price';\n return 'muted';\n }\n return '';\n }\n\n // Apply the parent-style-aware preset to every eligible element in\n // this card. Covers:\n // - CTA button (bg / text color / border / radius / padding / weight)\n // - Text colors for heading, price (primary), muted (desc / period),\n // feature (list lines)\n // Intent: each card style ships with a visually coherent default —\n // editorial → outline amber button + serif dark text; neon → cyan\n // filled button + light text on dark card; mailchimp/banded → yellow\n // pill + serif. Without this, dark-background styles render text\n // invisibly (hardcoded dark text-color from newCell bleeds through\n // inheritance).\n //\n // Users can override any element manually after; this is just the\n // default that matches the chosen style. Called at newCell() time,\n // whenever setStyle() runs, and when the cell's highlighted or\n // accent flags change.\n }, {\n key: \"applyStylePreset\",\n value: function applyStylePreset() {\n var _this2 = this;\n var style = this.getStyle();\n var accent = this.getResolvedAccent();\n var highlighted = !!this.highlighted;\n var buttonFormats = PricingCardElement.resolveButtonFormats(style, accent, highlighted);\n var textFormats = PricingCardElement.resolveTextFormats(style, accent, highlighted);\n var all = this._collectElements();\n all.forEach(function (el, i) {\n var role = _this2._roleOf(el, i, all);\n var formats = role === 'cta' ? buttonFormats : textFormats[role];\n if (!formats) return;\n Object.entries(formats).forEach(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n key = _ref2[0],\n value = _ref2[1];\n if (el.formatter.isKeyValid(key)) {\n el.formatter.setFormat(key, value);\n }\n });\n });\n }\n\n // Back-compat alias — some callsites were written against the\n // original \"button-only\" helper. Keep until all callsites migrate.\n }, {\n key: \"applyButtonPreset\",\n value: function applyButtonPreset() {\n return this.applyStylePreset();\n }\n\n // Inject card-meta + parent style into every PricingCard render pass.\n // CellElement._doRender() calls this.renderTemplate(vars); we augment\n // vars with the card's visual state. W0.2c: dropped the redundant\n // `if (template === 'PricingCard')` dispatch — element identity ↔\n // template = 1:1 invariant after A2 pure refactor (see BUILDER.md\n // Lesson 50), so this override only fires when `this` is a\n // PricingCardElement instance which always renders 'PricingCard'.\n }, {\n key: \"renderTemplate\",\n value: function renderTemplate() {\n var vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var parent = this.container || {};\n var showIcons = parent.show_icons !== false;\n var showBadges = parent.show_badges !== false;\n // Cell index/count — needed by the `banded` style (first/last\n // cell get outer radius, middle cells get inner dividers)\n // and by `tier` (staircase offset keyed on index). Falls\n // back to (0, 1) for orphan cells outside a container.\n var siblings = Array.isArray(parent.cells) ? parent.cells : [];\n var cellIndex = siblings.indexOf(this);\n var cellCount = siblings.length;\n return _superPropGet(PricingCardElement, \"renderTemplate\", this, 3)([_objectSpread({\n style: this.getStyle(),\n highlighted: !!this.highlighted,\n badge: showBadges ? this.badge || '' : '',\n icon: showIcons ? this.icon || '' : '',\n accent: this.getResolvedAccent(),\n cell_index: cellIndex >= 0 ? cellIndex : 0,\n cell_count: cellCount > 0 ? cellCount : 1,\n renderIcon: function renderIcon(name, size, color) {\n return _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].render(name, {\n size: size,\n color: color\n });\n }\n }, vars)]);\n }\n\n // Override CellElement.render() to strip stale attributes (data-style,\n // data-highlighted, inline style) before the parent's attribute-copy\n // pass. Without this, switching parent style (e.g. highlighted →\n // featured) left the previous `style=\"\"` value partially intact because\n // CellElement only calls setAttribute on keys the NEW template emits —\n // any attribute the old template had but the new one omits stays.\n // Result: badge/border from old style bleeds into the new render.\n // PricingCardElement is one of the few elements that legitimately overrides\n // `render()` directly — it needs a PRE-render attribute strip before the\n // BaseElement render lifecycle runs. After W0.2a, super.render() hits the\n // BaseElement Template Method (which calls CellElement._doRender + afterRender +\n // notifySyncListeners) so the lifecycle is preserved end-to-end.\n }, {\n key: \"render\",\n value: function render() {\n var _this3 = this;\n if (this.domNode) {\n // Strip every non-essential attribute before super.render() repaints.\n // Keep only the framework-owned `builder-element` tag.\n var keep = new Set(['builder-element']);\n var toRemove = [];\n var _iterator = _createForOfIteratorHelper(this.domNode.attributes),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var attr = _step.value;\n if (!keep.has(attr.name)) toRemove.push(attr.name);\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n toRemove.forEach(function (name) {\n return _this3.domNode.removeAttribute(name);\n });\n }\n return _superPropGet(PricingCardElement, \"render\", this, 3)([]);\n }\n\n // One-shot inspector rebuild — safe for discrete clicks (reset\n // button). No-op unless this cell is the selected element; the\n // panel will rebuild naturally next time it's selected otherwise.\n }, {\n key: \"_refreshInspector\",\n value: function _refreshInspector() {\n if (!this.host) return;\n var host = this.host;\n if (typeof host.renderElementControls !== 'function') return;\n if (typeof host.getSelectedElement === 'function' && host.getSelectedElement() !== this) {\n return;\n }\n host.renderElementControls(this);\n }\n }, {\n key: \"renderEmptyPlaceholder\",\n value: function renderEmptyPlaceholder() {\n var title = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.card_empty_title');\n var hint = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.card_empty_hint');\n return \"\\n <div builder-no-select style=\\\"\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center;\\n gap: 8px;\\n min-height: 160px;\\n padding: 24px 16px;\\n margin: 0;\\n border-radius: 10px;\\n background: rgba(148, 163, 184, 0.08);\\n border: 1px dashed rgba(148, 163, 184, 0.45);\\n color: #6b7280;\\n font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\\n text-align: center;\\n user-select: none;\\n pointer-events: none;\\n \\\">\\n <span class=\\\"material-symbols-rounded\\\" style=\\\"font-size: 28px; color: #9ca3af;\\\">view_column</span>\\n <div style=\\\"font-size: 13px; font-weight: 600; color: #374151;\\\">\".concat(title, \"</div>\\n <div style=\\\"font-size: 11px; color: #6b7280; max-width: 220px; line-height: 1.5;\\\">\").concat(hint, \"</div>\\n </div>\\n \");\n }\n }, {\n key: \"getData\",\n value: function getData() {\n var base = _superPropGet(PricingCardElement, \"getData\", this, 3)([]);\n base.highlighted = this.highlighted;\n base.badge = this.badge;\n base.icon = this.icon;\n base.accent_color = this.accent_color;\n return base;\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this4 = this;\n var onMetaChange = function onMetaChange() {\n return _this4.render();\n };\n // highlighted + accent mutations flip button treatment in 3 styles\n // (highlighted / featured / brutalist) and recolor the button in\n // a further 4 (compact / pill / neon / editorial). Re-apply the\n // preset BEFORE render so the button's Formatter holds the new\n // values by the time the cell repaints.\n var onVisualMetaChange = function onVisualMetaChange() {\n _this4.applyStylePreset();\n _this4.render();\n };\n var currentStyle = this.getStyle();\n var currentStyleLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing_style.' + currentStyle + '_label');\n return [new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.section_card_meta'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.section_card_meta_desc')),\n // Tell the user exactly which style's defaults this card is\n // inheriting — and that the accent color they pick here\n // overrides the style default. Kills the \"why is my button\n // still orange after I picked blue\" confusion.\n new _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.card_style_hint').replace('{style}', currentStyleLabel)), new _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.highlighted_label'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.highlighted_desc'), this.highlighted, function (v) {\n _this4.highlighted = !!v;\n onVisualMetaChange();\n }), new _TextControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.badge_label'), this.badge, {\n setText: function setText(v) {\n _this4.badge = v || '';\n onMetaChange();\n }\n }), new _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.icon_label'), this.icon, {\n setValue: function setValue(v) {\n _this4.icon = v || '';\n onMetaChange();\n }\n }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.accent_label'), this.accent_color, {\n setColor: function setColor(v) {\n _this4.accent_color = v || '';\n onVisualMetaChange();\n }\n }),\n // Per-card escape hatch — strips accent_color override,\n // clears icon/badge/highlight, and re-applies the style's\n // default button + text colors. Useful when the user\n // wants one card to \"go back to defaults\" without wiping\n // every other card too.\n new _ActionButtonControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"]({\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_card_label'),\n hint: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_card_hint').replace('{style}', currentStyleLabel),\n buttonText: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_card_button'),\n variant: 'default',\n onClick: function onClick() {\n _this4.accent_color = '';\n _this4.icon = '';\n _this4.badge = '';\n _this4.highlighted = false;\n _this4.applyStylePreset();\n _this4.render();\n // Rebuild inspector so the accent ColorPicker,\n // badge TextControl, icon IconPicker, and\n // highlighted Checkbox all snap back to their\n // cleared state. Without this, the canvas\n // repaints but the panel keeps the pre-reset\n // values — user sees \"Reset\" do nothing.\n _this4._refreshInspector();\n }\n })].concat(_toConsumableArray(_superPropGet(PricingCardElement, \"getControls\", this, 3)([])));\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var meta = {\n highlighted: !!data.highlighted,\n badge: typeof data.badge === 'string' ? data.badge : '',\n icon: typeof data.icon === 'string' ? data.icon : '',\n accent_color: typeof data.accent_color === 'string' ? data.accent_color : ''\n };\n var cell = new this(data.template || 'PricingCard', meta);\n var blocks = Array.isArray(data.blocks) ? data.blocks : [];\n blocks.forEach(function (blockData) {\n var block = _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(blockData);\n block.container = cell;\n cell.appendBlock(block);\n });\n cell.vertical_align = data.vertical_align || 'top';\n return this.parseFormats(cell, data);\n }\n }]);\n}(_CellElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/**\n * Default accent color per parent style. Cell-level `accent_color` overrides.\n * Keep in sync with PricingCard.template.html STYLE_TOKENS.\n */\nPricingCardElement.STYLE_ACCENTS = {\n minimal: '#ffcc2a',\n highlighted: '#ffcc2a',\n featured: '#ff4c6a',\n compact: '#1b8a5a',\n glass: '#6366f1',\n pill: '#f59e0b',\n neon: '#00e5ff',\n brutalist: '#ff4c6a',\n editorial: '#b45309',\n gradient: '#7c3aed',\n // Mailchimp yellow — same warm-mustard hue Mailchimp ships on its\n // public pricing page (visual reference: image in task).\n banded: '#ffe01b',\n // Indigo — conveys elevation/tier/upgrade in SaaS pricing pages.\n tier: '#4f46e5',\n // Soft periwinkle — works with neumorphism's pale gray-blue\n // surface without overwhelming the soft shadow play.\n neo: '#818cf8'\n};\n\n// Tiny helper that emits a full 4-side border spec from a single shorthand.\n// ButtonElement's Formatter stores borders per-side (border_top_*, …);\n// the preset resolvers below only care about \"all sides the same\" so we\n// expand once here.\nfunction _border(style, width, color) {\n return {\n border_top_style: style,\n border_top_width: width,\n border_top_color: color,\n border_right_style: style,\n border_right_width: width,\n border_right_color: color,\n border_bottom_style: style,\n border_bottom_width: width,\n border_bottom_color: color,\n border_left_style: style,\n border_left_width: width,\n border_left_color: color\n };\n}\n\n/**\n * Per-style button preset resolvers. Each returns a flat formats object\n * that gets merged into the CTA ButtonElement's Formatter — only keys\n * that already exist in the Formatter are applied (see applyButtonPreset).\n *\n * The design intent is that each card style ships with a button that\n * looks \"native\" to that visual language — the old hardcoded dark pill\n * looked foreign on Glass (dark navy card-text, glass bg → navy button),\n * Editorial (thin amber outlines → outline button), Brutalist (hard\n * shadow + thick border → match), Gradient (white-on-gradient → white\n * button). Second argument `accent` is the cell's resolved accent (per-\n * cell override → style default). Third argument `highlighted` is the\n * per-cell flag; three styles (highlighted, featured, brutalist) use it\n * to swap the button fill to the accent on the stand-out card.\n */\nvar STYLE_BUTTON_RESOLVERS = {\n minimal: function minimal(accent, highlighted) {\n return Object.assign({\n background_color: '#111827',\n text_color: '#ffffff',\n link_color: '#ffffff',\n font_weight: '700',\n border_radius: '8px',\n padding_top: 12,\n padding_bottom: 12,\n padding_left: 14,\n padding_right: 14\n }, _border('solid', 0, '#111827'));\n },\n highlighted: function highlighted(accent, _highlighted) {\n return _highlighted ? Object.assign({\n background_color: accent,\n text_color: '#1a1a1a',\n link_color: '#1a1a1a',\n font_weight: '800',\n border_radius: '8px',\n padding_top: 12,\n padding_bottom: 12,\n padding_left: 14,\n padding_right: 14\n }, _border('solid', 0, accent)) : Object.assign({\n background_color: '#111827',\n text_color: '#ffffff',\n link_color: '#ffffff',\n font_weight: '700',\n border_radius: '8px',\n padding_top: 12,\n padding_bottom: 12,\n padding_left: 14,\n padding_right: 14\n }, _border('solid', 0, '#111827'));\n },\n featured: function featured(accent, highlighted) {\n return highlighted ? Object.assign({\n background_color: accent,\n text_color: '#ffffff',\n link_color: '#ffffff',\n font_weight: '800',\n border_radius: '999px',\n padding_top: 13,\n padding_bottom: 13,\n padding_left: 14,\n padding_right: 14\n }, _border('solid', 0, accent)) : Object.assign({\n background_color: '#111827',\n text_color: '#ffffff',\n link_color: '#ffffff',\n font_weight: '700',\n border_radius: '999px',\n padding_top: 13,\n padding_bottom: 13,\n padding_left: 14,\n padding_right: 14\n }, _border('solid', 0, '#111827'));\n },\n compact: function compact(accent, highlighted) {\n return Object.assign({\n background_color: accent,\n text_color: '#ffffff',\n link_color: '#ffffff',\n font_weight: '700',\n border_radius: '4px',\n padding_top: 10,\n padding_bottom: 10,\n padding_left: 14,\n padding_right: 14\n }, _border('solid', 0, accent));\n },\n glass: function glass(accent, highlighted) {\n return Object.assign({\n background_color: '#312e81',\n text_color: '#ffffff',\n link_color: '#ffffff',\n font_weight: '700',\n border_radius: '999px',\n padding_top: 12,\n padding_bottom: 12,\n padding_left: 16,\n padding_right: 16\n }, _border('solid', 0, '#312e81'));\n },\n pill: function pill(accent, highlighted) {\n return Object.assign({\n background_color: accent,\n text_color: '#ffffff',\n link_color: '#ffffff',\n font_weight: '700',\n border_radius: '999px',\n padding_top: 12,\n padding_bottom: 12,\n padding_left: 16,\n padding_right: 16\n }, _border('solid', 0, accent));\n },\n neon: function neon(accent, highlighted) {\n return Object.assign({\n background_color: accent,\n text_color: '#0a0a0f',\n link_color: '#0a0a0f',\n font_weight: '800',\n border_radius: '6px',\n padding_top: 12,\n padding_bottom: 12,\n padding_left: 14,\n padding_right: 14\n }, _border('solid', 0, accent));\n },\n brutalist: function brutalist(accent, highlighted) {\n // Highlighted brutalist card is flooded with accent + white text,\n // so flip the button to white-on-black hard border to keep the\n // \"stamped block\" look from disappearing. Non-highlighted cards\n // get the classic solid-black rectangle.\n return highlighted ? Object.assign({\n background_color: '#ffffff',\n text_color: '#000000',\n link_color: '#000000',\n font_weight: '900',\n border_radius: 0,\n padding_top: 12,\n padding_bottom: 12,\n padding_left: 16,\n padding_right: 16\n }, _border('solid', '2px', '#000000')) : Object.assign({\n background_color: '#000000',\n text_color: '#ffffff',\n link_color: '#ffffff',\n font_weight: '900',\n border_radius: 0,\n padding_top: 12,\n padding_bottom: 12,\n padding_left: 16,\n padding_right: 16\n }, _border('solid', '2px', '#000000'));\n },\n editorial: function editorial(accent, highlighted) {\n // Outline-only amber button — matches the editorial card's thin\n // serif/underline treatment. Transparent bg → the card's cream\n // paper shows through.\n return Object.assign({\n background_color: 'transparent',\n text_color: accent,\n link_color: accent,\n font_weight: '700',\n border_radius: 0,\n padding_top: 11,\n padding_bottom: 11,\n padding_left: 18,\n padding_right: 18\n }, _border('solid', '1px', accent));\n },\n gradient: function gradient(accent, highlighted) {\n // White filled button on the gradient card bg — maximum contrast\n // against any accent. Text reads the card's background gradient\n // through dark-slate ink.\n return Object.assign({\n background_color: '#ffffff',\n text_color: '#1f2937',\n link_color: '#1f2937',\n font_weight: '800',\n border_radius: '8px',\n padding_top: 12,\n padding_bottom: 12,\n padding_left: 14,\n padding_right: 14\n }, _border('solid', 0, '#ffffff'));\n },\n banded: function banded(accent, highlighted) {\n // Mailchimp-style yellow pill with a subtle dark \"underline\"\n // border at the bottom. Fully rounded, dark ink text. Works on\n // white/near-white card surface. The thin 1.5px bottom border\n // is the Mailchimp signature touch.\n return {\n background_color: accent,\n text_color: '#1a1a1a',\n link_color: '#1a1a1a',\n font_weight: '800',\n border_radius: '999px',\n padding_top: 13,\n padding_bottom: 13,\n padding_left: 16,\n padding_right: 16,\n border_top_style: 'solid',\n border_top_width: 0,\n border_top_color: accent,\n border_right_style: 'solid',\n border_right_width: 0,\n border_right_color: accent,\n border_bottom_style: 'solid',\n border_bottom_width: '2px',\n border_bottom_color: '#1a1a1a',\n border_left_style: 'solid',\n border_left_width: 0,\n border_left_color: accent\n };\n },\n tier: function tier(accent, highlighted) {\n // Indigo filled rounded — feels elevated / premium. Slight text\n // tracking (\"letter_spacing\") would help, but ButtonElement\n // formatter doesn't expose it. Weight 800 alone handles pop.\n return Object.assign({\n background_color: accent,\n text_color: '#ffffff',\n link_color: '#ffffff',\n font_weight: '800',\n border_radius: '10px',\n padding_top: 13,\n padding_bottom: 13,\n padding_left: 14,\n padding_right: 14\n }, _border('solid', 0, accent));\n },\n neo: function neo(accent, highlighted) {\n // Neumorphism-style button — pale surface, accent text, soft\n // border. Real neumorphism would need dual box-shadows (outer\n // light + outer dark) which ButtonElement can't express via\n // Formatter; we approximate with a thin accent border + tinted\n // bg. The card wrapper's box-shadow carries the neu feel.\n return Object.assign({\n background_color: '#eef1f6',\n text_color: accent,\n link_color: accent,\n font_weight: '700',\n border_radius: '14px',\n padding_top: 13,\n padding_bottom: 13,\n padding_left: 14,\n padding_right: 14\n }, _border('solid', '1px', '#d6dbe4'));\n }\n};\nPricingCardElement.resolveButtonFormats = function (style, accent, highlighted) {\n var fn = STYLE_BUTTON_RESOLVERS[style] || STYLE_BUTTON_RESOLVERS.highlighted;\n return fn(accent, highlighted);\n};\nPricingCardElement.STYLE_BUTTON_RESOLVERS = STYLE_BUTTON_RESOLVERS;\n\n/**\n * Per-style text-format resolvers. Each returns a dict keyed by element\n * role ('heading' | 'price' | 'muted' | 'feature') with format overrides.\n * Only keys present in the element's Formatter are applied, so unrelated\n * text-format keys (letter_spacing on Heading, text_color on PElement)\n * coexist safely.\n *\n * Styles with a dark card surface (neon, brutalist+highlighted, gradient)\n * need light text — the default dark text colors seeded at newCell time\n * would render invisibly. Editorial wants serif. Banded (Mailchimp-like)\n * also wants serif + slightly warmer tone. Glass wants navy ink to match\n * its native accent.\n */\nvar STYLE_TEXT_RESOLVERS = {\n minimal: function minimal(accent, hl) {\n return {\n heading: {\n text_color: '#111827'\n },\n price: {\n text_color: '#111827'\n },\n muted: {\n text_color: 'rgba(15,23,42,0.6)'\n },\n feature: {\n text_color: '#1f2937'\n }\n };\n },\n highlighted: function highlighted(accent, hl) {\n return {\n heading: {\n text_color: '#111827'\n },\n price: {\n text_color: '#111827'\n },\n muted: {\n text_color: 'rgba(15,23,42,0.6)'\n },\n feature: {\n text_color: '#1f2937'\n }\n };\n },\n featured: function featured(accent, hl) {\n return {\n heading: {\n text_color: '#111827'\n },\n price: {\n text_color: '#111827'\n },\n muted: {\n text_color: 'rgba(15,23,42,0.62)'\n },\n feature: {\n text_color: '#1f2937'\n }\n };\n },\n compact: function compact(accent, hl) {\n return {\n heading: {\n text_color: '#0f172a'\n },\n price: {\n text_color: '#0f172a'\n },\n muted: {\n text_color: 'rgba(15,23,42,0.58)'\n },\n feature: {\n text_color: '#1e293b'\n }\n };\n },\n glass: function glass(accent, hl) {\n // Card sets color: '#312e81' at wrapper level; reinforce that on\n // children so overrides from hardcoded newCell colors don't\n // punch through.\n return {\n heading: {\n text_color: '#1e1b4b'\n },\n price: {\n text_color: '#1e1b4b'\n },\n muted: {\n text_color: 'rgba(49,46,129,0.65)'\n },\n feature: {\n text_color: '#312e81'\n }\n };\n },\n pill: function pill(accent, hl) {\n return {\n heading: {\n text_color: '#111827'\n },\n price: {\n text_color: '#111827'\n },\n muted: {\n text_color: 'rgba(15,23,42,0.58)'\n },\n feature: {\n text_color: '#1f2937'\n }\n };\n },\n neon: function neon(accent, hl) {\n // Dark cyberpunk surface. Light text everywhere; muted = 60%.\n // Price gets a subtle glow via text-shadow — BUT formatter has\n // no text-shadow key; template wrapper supplies the shadow via\n // inherited color rules. Here we just own the colors.\n return {\n heading: {\n text_color: '#e5e7eb'\n },\n price: {\n text_color: accent\n },\n muted: {\n text_color: 'rgba(229,231,235,0.6)'\n },\n feature: {\n text_color: '#d1d5db'\n }\n };\n },\n brutalist: function brutalist(accent, hl) {\n // Highlighted brutalist card is flooded with accent + dark text\n // needed on accent backdrop. Non-highlighted: default black text\n // on white.\n if (hl) {\n return {\n heading: {\n text_color: '#ffffff'\n },\n price: {\n text_color: '#ffffff'\n },\n muted: {\n text_color: 'rgba(255,255,255,0.78)'\n },\n feature: {\n text_color: '#ffffff'\n }\n };\n }\n return {\n heading: {\n text_color: '#000000'\n },\n price: {\n text_color: '#000000'\n },\n muted: {\n text_color: 'rgba(0,0,0,0.6)'\n },\n feature: {\n text_color: '#111111'\n }\n };\n },\n editorial: function editorial(accent, hl) {\n // Warm paper card, serif, amber accent. Slightly warmer ink than\n // default black for that \"printed magazine\" feel.\n return {\n heading: {\n text_color: '#1c1917',\n font_family: 'Georgia, \"Times New Roman\", serif'\n },\n price: {\n text_color: '#1c1917',\n font_family: 'Georgia, \"Times New Roman\", serif'\n },\n muted: {\n text_color: 'rgba(28,25,23,0.65)',\n font_family: 'Georgia, \"Times New Roman\", serif'\n },\n feature: {\n text_color: '#44403c',\n font_family: 'Georgia, \"Times New Roman\", serif'\n }\n };\n },\n gradient: function gradient(accent, hl) {\n // White text on gradient card bg. Muted is 75% white (not lower —\n // goes illegible on bright gradient stops).\n return {\n heading: {\n text_color: '#ffffff'\n },\n price: {\n text_color: '#ffffff'\n },\n muted: {\n text_color: 'rgba(255,255,255,0.78)'\n },\n feature: {\n text_color: '#ffffff'\n }\n };\n },\n banded: function banded(accent, hl) {\n // Mailchimp-style: serif \"Cooper\" / \"Sharp Grotesk\" vibe →\n // Georgia fallback. Muted reads like editorial body copy.\n return {\n heading: {\n text_color: '#1c1917',\n font_family: 'Georgia, \"Times New Roman\", serif'\n },\n price: {\n text_color: '#1c1917',\n font_family: 'Georgia, \"Times New Roman\", serif'\n },\n muted: {\n text_color: 'rgba(28,25,23,0.68)'\n },\n feature: {\n text_color: '#1f2937'\n }\n };\n },\n tier: function tier(accent, hl) {\n // Deep indigo inked primary; muted stays slate. Heading gets\n // a hint of accent tint via letter_spacing would be nice but\n // Formatter owns that on a per-element basis — the heading in\n // newCell already sets 0.08em. Leave it alone.\n return {\n heading: {\n text_color: '#1e1b4b'\n },\n price: {\n text_color: '#1e1b4b'\n },\n muted: {\n text_color: 'rgba(30,27,75,0.6)'\n },\n feature: {\n text_color: '#312e81'\n }\n };\n },\n neo: function neo(accent, hl) {\n // Soft gray-blue surface wants ink that isn't pure black — it\n // fights the neumorphic glow. Slate 800 feels right.\n return {\n heading: {\n text_color: '#1e293b'\n },\n price: {\n text_color: '#1e293b'\n },\n muted: {\n text_color: 'rgba(30,41,59,0.62)'\n },\n feature: {\n text_color: '#334155'\n }\n };\n }\n};\nPricingCardElement.resolveTextFormats = function (style, accent, highlighted) {\n var fn = STYLE_TEXT_RESOLVERS[style] || STYLE_TEXT_RESOLVERS.minimal;\n return fn(accent, highlighted);\n};\nPricingCardElement.STYLE_TEXT_RESOLVERS = STYLE_TEXT_RESOLVERS;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PricingCardElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PricingCardElement.js?");
/***/ }),
/***/ "./src/includes/PricingCardsElement.js":
/*!*********************************************!*\
!*** ./src/includes/PricingCardsElement.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _GridElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./GridElement.js */ \"./src/includes/GridElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _ButtonElement_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ButtonElement.js */ \"./src/includes/ButtonElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _StyleControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./StyleControl.js */ \"./src/includes/StyleControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _DropdownControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./DropdownControl.js */ \"./src/includes/DropdownControl.js\");\n/* harmony import */ var _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./InfoBannerControl.js */ \"./src/includes/InfoBannerControl.js\");\n/* harmony import */ var _ActionButtonControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./ActionButtonControl.js */ \"./src/includes/ActionButtonControl.js\");\n/* harmony import */ var _PricingCardElement_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./PricingCardElement.js */ \"./src/includes/PricingCardElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * PricingCardsElement — a Grid of PricingCardElements (pricing plan cards).\n *\n * Extends GridElement (per Builder composition rule: only Grid subclasses may\n * host cells). Cells are PricingCardElement instances, each holding native\n * BlockElement children (Heading, PElements, Button, ListElement, etc.) that\n * the user edits with the native controls already in the codebase — no\n * HTML-blob / RichText shortcut.\n *\n * Visual treatment is driven by a single parent-level `style` prop (1 of 10\n * presets). Each card reads `this.container.style` at render time to shape\n * its wrapper (see PricingCard.template.html). Per-card metadata (highlighted,\n * badge, icon, accent_color) lives on the cell.\n *\n * Replaces retired: PricingTableElement (HTML-blob) + PricingGridElement\n * (orphan prototype). See docs/plans/DESIGN_PRICING_ELEMENT.md.\n */\n\nvar VALID_STYLES = ['minimal', 'highlighted', 'featured', 'compact', 'glass', 'pill', 'neon', 'brutalist', 'editorial', 'gradient',\n// 2026-04-18 PRO-audit round: three new presets adding distinct\n// visual languages — joined table (banded), staircase elevation\n// (tier), and soft neumorphism (neo). See DESIGN_PRICING_ELEMENT.md.\n'banded', 'tier', 'neo'];\nvar DEFAULT_STYLE = 'highlighted';\n\n// Per-style default gap between cards — MUST cover every style in\n// VALID_STYLES so setStyle() can authoritatively re-apply the right\n// spacing on every switch. Earlier version only listed the three new\n// presets (banded/tier/neo), which meant: pick \"banded\" (gap=0), then\n// switch to any other style → gap stayed 0 forever because the lookup\n// missed and the guard preserved the prior value. By covering all 13\n// the gap now always reflects the chosen style's intent.\nvar STYLE_DEFAULT_GAPS = {\n minimal: 20,\n highlighted: 20,\n featured: 24,\n compact: 8,\n glass: 20,\n pill: 20,\n neon: 20,\n brutalist: 16,\n editorial: 24,\n gradient: 20,\n banded: 0,\n tier: 16,\n neo: 24\n};\nvar PricingCardsElement = /*#__PURE__*/function (_GridElement) {\n function PricingCardsElement(template) {\n var _this;\n _classCallCheck(this, PricingCardsElement);\n _this = _callSuper(this, PricingCardsElement, [template || 'PricingCards']);\n _this.style = DEFAULT_STYLE;\n _this.cell_gap = 20;\n // Parent-level toggles — cell template reads these via its container\n // reference to decide whether to render per-cell icon / badge.\n _this.show_icons = true;\n _this.show_badges = true;\n return _this;\n }\n _inherits(PricingCardsElement, _GridElement);\n return _createClass(PricingCardsElement, [{\n key: \"getClassName\",\n value: function getClassName() {\n return 'PricingCardsElement';\n }\n }, {\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.pricing_cards');\n }\n\n // Override GridElement.isHoverable() (which returns false for plain Grids\n // because hover-highlighting a Grid that fills the canvas would be noisy).\n // Pricing Cards is a discrete visual block — users expect to hover/click\n // the whole set to select + move it.\n }, {\n key: \"isHoverable\",\n value: function isHoverable() {\n return true;\n }\n\n // Inject `style` into the parent wrapper template so the grid root can\n // emit `data-pricing-cards-style` — selectors and global style rules can\n // then target a specific preset. W0.2c: dropped the redundant\n // `if (template === 'PricingCards')` dispatch — element identity ↔\n // template = 1:1 invariant after A2 pure refactor (BUILDER.md Lesson 50).\n }, {\n key: \"renderTemplate\",\n value: function renderTemplate() {\n var vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n return _superPropGet(PricingCardsElement, \"renderTemplate\", this, 3)([_objectSpread({\n style: this.style\n }, vars)]);\n }\n }, {\n key: \"setStyle\",\n value: function setStyle(nextStyle) {\n this.style = VALID_STYLES.indexOf(nextStyle) !== -1 ? nextStyle : DEFAULT_STYLE;\n // Apply the style's default cell_gap. STYLE_DEFAULT_GAPS covers\n // every style, so the fallback branch only runs for unknown\n // keys (shouldn't happen once VALID_STYLES gates the input).\n if (Object.prototype.hasOwnProperty.call(STYLE_DEFAULT_GAPS, this.style)) {\n this.cell_gap = STYLE_DEFAULT_GAPS[this.style];\n }\n // Reset per-card visual theming so the new style's defaults take\n // effect — accent_color, button formats, and text colors all get\n // rewritten to the new style's preset. Per-card highlighted /\n // badge / icon are preserved (they're orthogonal to theming).\n this.cells.forEach(function (cell) {\n if (cell && typeof cell.accent_color !== 'undefined') cell.accent_color = '';\n if (cell && typeof cell.applyStylePreset === 'function') cell.applyStylePreset();\n });\n this.render();\n // Rebuild inspector so cell_gap slider, info-banner ({style}\n // placeholder), and any StyleControl state all reflect the new\n // preset. Without this the Range slider on Cell Gap keeps\n // showing the previous numeric value even though cell_gap was\n // just overwritten.\n this._refreshInspector();\n }\n\n // Create a seeded pricing card with default native content: Heading\n // (plan name), PElement (price), PElement (period), PElements (features)\n // and a ButtonElement CTA. Same idea as the retired PricingGridElement\n // newCell, but emits PricingCardElement (Cell subclass) with card meta.\n }, {\n key: \"newCell\",\n value: function newCell() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var planIndex = this.cells.length;\n var cell = new _PricingCardElement_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"]('PricingCard', {\n highlighted: false,\n badge: '',\n icon: '',\n accent_color: ''\n });\n cell.container = this;\n cell.formatter.setFormat('width', this._defaultWidthForNewCell());\n cell.vertical_align = 'top';\n var block = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Block');\n block.container = cell;\n block.formatter.setFormat('padding_top', 0);\n block.formatter.setFormat('padding_bottom', 0);\n block.formatter.setFormat('padding_left', 0);\n block.formatter.setFormat('padding_right', 0);\n var planName = options.planName || \"Plan \".concat(planIndex + 1);\n var planDesc = options.planDesc || 'Describe this plan in one short line.';\n var planPriceText = options.planPrice || '$0';\n var planPeriodText = options.planPeriod || 'per month';\n var planSubText = options.planSub || '';\n var features = Array.isArray(options.features) && options.features.length ? options.features : ['Feature one', 'Feature two', 'Feature three', 'Feature four'];\n var ctaText = options.ctaText || 'Get started';\n\n // Tag each element with a `_pricing_role` hint so the style\n // preset resolver knows how to theme it. Role tags let us pick\n // the right text color per style (primary vs muted vs feature)\n // without relying on positional heuristics that break when the\n // user inserts / reorders elements.\n var heading = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h3', planName);\n heading._pricing_role = 'heading';\n heading.formatter.setFormat('font_size', 18);\n heading.formatter.setFormat('font_weight', 'bolder');\n heading.formatter.setFormat('letter_spacing', '0.08em');\n var desc = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', planDesc);\n desc._pricing_role = 'muted';\n desc.formatter.setFormat('font_size', 13);\n desc.formatter.setFormat('padding_bottom', 4);\n var price = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', planPriceText);\n price._pricing_role = 'price';\n price.formatter.setFormat('font_size', 42);\n price.formatter.setFormat('font_weight', '800');\n price.formatter.setFormat('line_height', '1');\n price.formatter.setFormat('padding_top', 4);\n var period = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', planPeriodText);\n period._pricing_role = 'muted';\n period.formatter.setFormat('font_size', 14);\n var elements = [heading, desc, price, period];\n if (planSubText) {\n var sub = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', planSubText);\n sub._pricing_role = 'muted';\n sub.formatter.setFormat('font_size', 13);\n sub.formatter.setFormat('padding_bottom', 8);\n elements.push(sub);\n }\n features.forEach(function (line, i) {\n var f = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', \"\\u2713 \" + line);\n f._pricing_role = 'feature';\n f.formatter.setFormat('font_size', 14);\n f.formatter.setFormat('padding_top', 4);\n f.formatter.setFormat('padding_bottom', 4);\n // Extra breathing room above the last feature so the upcoming CTA\n // button has space to \"land\" without touching the features list.\n if (i === features.length - 1) f.formatter.setFormat('padding_bottom', 20);\n elements.push(f);\n });\n var cta = new _ButtonElement_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"]('Button', ctaText, options.ctaUrl || '#');\n cta._pricing_role = 'cta';\n // Font-size + alignment stay constant across all 10 styles — only\n // the style preset swaps color / border / radius. See\n // PricingCardElement.STYLE_BUTTON_RESOLVERS.\n cta.formatter.setFormat('font_size', 14);\n cta.formatter.setFormat('align', 'stretch');\n elements.push(cta);\n cell.appendBlock(block);\n block.appendElements(elements);\n\n // Apply the current style's preset (button + text colors).\n // Without this the CTA would render with ButtonElement's stock\n // blue — foreign to every pricing style — and text colors\n // would stay fixed-dark even on dark card surfaces (neon,\n // brutalist-highlighted, gradient). The preset is hard-written\n // to each element's Formatter so opening the inspector panel\n // shows the actual values (no \"empty bg color\" confusion).\n cell.applyStylePreset();\n return cell;\n }\n }, {\n key: \"getData\",\n value: function getData() {\n var base = _superPropGet(PricingCardsElement, \"getData\", this, 3)([]);\n base.style = this.style;\n base.show_icons = this.show_icons;\n base.show_badges = this.show_badges;\n return base;\n }\n }, {\n key: \"getStyleOptions\",\n value: function getStyleOptions() {\n return VALID_STYLES.map(function (key) {\n return {\n key: key,\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing_style.' + key + '_label'),\n thumb: PricingCardsElement.THUMBS[key] || ''\n };\n });\n }\n\n // Highlight-plan helper (parent-level). Mutates per-cell `highlighted` so\n // only cell at `index` is highlighted (0-based). Pass -1 to clear.\n }, {\n key: \"setHighlightIndex\",\n value: function setHighlightIndex(index) {\n var n = parseInt(index, 10);\n this.cells.forEach(function (cell, i) {\n if (typeof cell.highlighted === 'boolean') cell.highlighted = i === n;\n });\n this.render();\n }\n }, {\n key: \"setShowIcons\",\n value: function setShowIcons(value) {\n this.show_icons = !!value;\n this.render();\n }\n }, {\n key: \"setShowBadges\",\n value: function setShowBadges(value) {\n this.show_badges = !!value;\n this.render();\n }\n\n // Reset per-cell overrides → clears accent_color, icon, badge on each\n // card, un-highlights them all, and re-applies the currently\n // selected style's preset (button + text colors). Kept as a\n // parent-level \"Clean up\" action so the user can wipe manual\n // tweaks and start from a coherent preset. Preserves card CONTENT\n // (heading text, price text, feature lines, CTA label/URL) — only\n // visual theming is rewritten.\n }, {\n key: \"resetCards\",\n value: function resetCards() {\n this.cells.forEach(function (cell) {\n if (!cell) return;\n cell.accent_color = '';\n cell.icon = '';\n cell.badge = '';\n cell.highlighted = false;\n if (typeof cell.applyStylePreset === 'function') cell.applyStylePreset();\n });\n // Also reset parent-level toggles so \"Reset all\" is a true\n // clean-slate — if the user toggled Show icons / badges OFF\n // earlier, reset restores the as-shipped visibility too.\n this.show_icons = true;\n this.show_badges = true;\n // Re-apply the current style's gap default too — the user may\n // have dragged Cell Gap manually; reset should restore the\n // style's canonical spacing.\n if (Object.prototype.hasOwnProperty.call(STYLE_DEFAULT_GAPS, this.style)) {\n this.cell_gap = STYLE_DEFAULT_GAPS[this.style];\n }\n this.render();\n // Rebuild inspector so Highlight-plan dropdown flips back to\n // \"None\", Show-icons/badges toggles flip ON, and the Cell Gap\n // slider snaps back to the style default. Without this, the\n // canvas repaints correctly but the panel keeps stale values\n // (the bug the user reported as \"resets ko update settings\").\n this._refreshInspector();\n }\n\n // One-shot inspector rebuild — safe to call from discrete user\n // actions (reset buttons, style picker). Guarded so it only fires\n // when this element is the currently selected one; otherwise it's\n // a no-op (the panel will rebuild naturally when the element gets\n // selected). Avoids the \"renderElementControls-in-setter flicker\"\n // trap by skipping rapid-fire paths (no cell_gap slider binds to\n // this).\n }, {\n key: \"_refreshInspector\",\n value: function _refreshInspector() {\n if (!this.host) return;\n var host = this.host;\n if (typeof host.renderElementControls !== 'function') return;\n if (typeof host.getSelectedElement === 'function' && host.getSelectedElement() !== this) {\n return;\n }\n host.renderElementControls(this);\n }\n }, {\n key: \"_currentHighlightIndex\",\n value: function _currentHighlightIndex() {\n for (var i = 0; i < this.cells.length; i++) {\n if (this.cells[i] && this.cells[i].highlighted) return i;\n }\n return -1;\n }\n }, {\n key: \"_highlightOptions\",\n value: function _highlightOptions() {\n var opts = [{\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.highlight_none'),\n value: '-1'\n }];\n this.cells.forEach(function (_, i) {\n opts.push({\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.highlight_card_n').replace('{n}', i + 1),\n value: String(i)\n });\n });\n return opts;\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this;\n var parentControls = _superPropGet(PricingCardsElement, \"getControls\", this, 3)([]);\n var currentStyleLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing_style.' + this.style + '_label');\n return [new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.section_style'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.section_style_desc')), new _StyleControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.style_label'), this.style, this.getStyleOptions(), {\n setValue: function setValue(v) {\n return _this2.setStyle(v);\n }\n }),\n // Info hint — makes explicit that switching styles wipes\n // per-card visual overrides (accent / button / text colors)\n // and that badge / icon / highlight choices survive. Without\n // this, a user who custom-colored a button and then switched\n // style would wonder \"where did my color go?\". Helper text\n // surfaces the rule up-front.\n new _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.style_switch_hint').replace('{style}', currentStyleLabel)), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.highlight_label'), String(this._currentHighlightIndex()), this._highlightOptions(), function (v) {\n return _this2.setHighlightIndex(v);\n }), new _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.show_icons_label'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.show_icons_desc'), this.show_icons, function (v) {\n return _this2.setShowIcons(v);\n }), new _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.show_badges_label'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.show_badges_desc'), this.show_badges, function (v) {\n return _this2.setShowBadges(v);\n }),\n // Parent-level escape hatch — wipes accent/badge/icon/highlight\n // on every card and re-applies style preset. Useful after\n // heavy per-card experimentation.\n new _ActionButtonControl_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"]({\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_all_label'),\n hint: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_all_hint').replace('{style}', currentStyleLabel),\n buttonText: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_all_button'),\n variant: 'danger',\n onClick: function onClick() {\n return _this2.resetCards();\n }\n })].concat(_toConsumableArray(parentControls));\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var element = new this(data.template || 'PricingCards');\n var nextStyle = data.style;\n element.style = VALID_STYLES.indexOf(nextStyle) !== -1 ? nextStyle : DEFAULT_STYLE;\n element.cell_gap = typeof data.cell_gap === 'number' ? data.cell_gap : element.cell_gap;\n if (typeof data.show_icons === 'boolean') element.show_icons = data.show_icons;\n if (typeof data.show_badges === 'boolean') element.show_badges = data.show_badges;\n this.parseFormats(element, data);\n var cells = Array.isArray(data.cells) ? data.cells : [];\n cells.forEach(function (cellData) {\n // Accept: new PricingCardElement, legacy plain CellElement, or\n // Arch-A legacy cell shape (`{ details: 'HTML' }`). The ElementFactory\n // auto-migration lifts old shapes to PricingCardElement before we\n // see them here, but guard defensively:\n if (cellData && _typeof(cellData) === 'object' && !cellData.name) {\n cellData.name = 'PricingCardElement';\n cellData.template = cellData.template || 'PricingCard';\n }\n var cell = _ElementFactory_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"].createElement(cellData);\n cell.container = element;\n element.append(cell);\n });\n return element;\n }\n }]);\n}(_GridElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]); // 10 thumbnail SVGs for the style picker. 120×72 viewBox, 4 card columns.\nPricingCardsElement.THUMBS = {\n minimal: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#f9fafb\\\"/>\\n <rect x=\\\"8\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n <rect x=\\\"12\\\" y=\\\"17\\\" width=\\\"12\\\" height=\\\"2\\\" fill=\\\"#9ca3af\\\"/>\\n <rect x=\\\"40\\\" y=\\\"17\\\" width=\\\"12\\\" height=\\\"2\\\" fill=\\\"#9ca3af\\\"/>\\n <rect x=\\\"68\\\" y=\\\"17\\\" width=\\\"12\\\" height=\\\"2\\\" fill=\\\"#9ca3af\\\"/>\\n <rect x=\\\"95\\\" y=\\\"17\\\" width=\\\"12\\\" height=\\\"2\\\" fill=\\\"#9ca3af\\\"/>\\n <text x=\\\"12\\\" y=\\\"32\\\" font-family=\\\"-apple-system,sans-serif\\\" font-size=\\\"7.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$0</text>\\n <text x=\\\"40\\\" y=\\\"32\\\" font-family=\\\"-apple-system,sans-serif\\\" font-size=\\\"7.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$19</text>\\n <text x=\\\"68\\\" y=\\\"32\\\" font-family=\\\"-apple-system,sans-serif\\\" font-size=\\\"7.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$49</text>\\n <text x=\\\"95\\\" y=\\\"32\\\" font-family=\\\"-apple-system,sans-serif\\\" font-size=\\\"7.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$99</text>\\n <g fill=\\\"#d1d5db\\\">\\n <rect x=\\\"12\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"12\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"12\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1.2\\\"/>\\n <rect x=\\\"40\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"40\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"40\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1.2\\\"/>\\n <rect x=\\\"68\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"68\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"68\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1.2\\\"/>\\n <rect x=\\\"95\\\" y=\\\"38\\\" width=\\\"12\\\" height=\\\"1.2\\\"/><rect x=\\\"95\\\" y=\\\"42\\\" width=\\\"12\\\" height=\\\"1.2\\\"/><rect x=\\\"95\\\" y=\\\"46\\\" width=\\\"12\\\" height=\\\"1.2\\\"/>\\n </g>\\n <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n <rect x=\\\"95\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n</svg>\",\n highlighted: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#f9fafb\\\"/>\\n <rect x=\\\"8\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n <rect x=\\\"36\\\" y=\\\"6\\\" width=\\\"24\\\" height=\\\"60\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#ffcc2a\\\" stroke-width=\\\"1.5\\\"/>\\n <rect x=\\\"36\\\" y=\\\"6\\\" width=\\\"24\\\" height=\\\"7\\\" fill=\\\"#ffcc2a\\\"/>\\n <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n <text x=\\\"38\\\" y=\\\"11.2\\\" font-size=\\\"3\\\" font-weight=\\\"800\\\" fill=\\\"#1a1a1a\\\">POPULAR</text>\\n <text x=\\\"12\\\" y=\\\"32\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$0</text>\\n <text x=\\\"40\\\" y=\\\"32\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$49</text>\\n <text x=\\\"68\\\" y=\\\"32\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$19</text>\\n <text x=\\\"95\\\" y=\\\"32\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$99</text>\\n <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#ffcc2a\\\"/>\\n <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n <rect x=\\\"95\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n</svg>\",\n featured: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#fff5f2\\\"/>\\n <rect x=\\\"8\\\" y=\\\"14\\\" width=\\\"24\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#fff\\\" stroke=\\\"#f0d0c8\\\"/>\\n <rect x=\\\"36\\\" y=\\\"14\\\" width=\\\"24\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#fff\\\" stroke=\\\"#f0d0c8\\\"/>\\n <rect x=\\\"64\\\" y=\\\"14\\\" width=\\\"24\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#fff\\\" stroke=\\\"#f0d0c8\\\"/>\\n <rect x=\\\"92\\\" y=\\\"14\\\" width=\\\"20\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#fff\\\" stroke=\\\"#f0d0c8\\\"/>\\n <rect x=\\\"42\\\" y=\\\"10\\\" width=\\\"12\\\" height=\\\"6\\\" rx=\\\"3\\\" fill=\\\"#ff4c6a\\\"/>\\n <text x=\\\"44\\\" y=\\\"14.5\\\" font-size=\\\"3\\\" font-weight=\\\"800\\\" fill=\\\"#fff\\\">BEST</text>\\n <circle cx=\\\"20\\\" cy=\\\"24\\\" r=\\\"5\\\" fill=\\\"#ff4c6a22\\\"/>\\n <circle cx=\\\"48\\\" cy=\\\"24\\\" r=\\\"5\\\" fill=\\\"#ff4c6a22\\\"/>\\n <circle cx=\\\"76\\\" cy=\\\"24\\\" r=\\\"5\\\" fill=\\\"#ff4c6a22\\\"/>\\n <circle cx=\\\"102\\\" cy=\\\"24\\\" r=\\\"4\\\" fill=\\\"#ff4c6a22\\\"/>\\n <text x=\\\"14\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$0</text>\\n <text x=\\\"42\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$19</text>\\n <text x=\\\"70\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$49</text>\\n <text x=\\\"96\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$99</text>\\n <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#111827\\\"/>\\n <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#ff4c6a\\\"/>\\n <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#111827\\\"/>\\n <rect x=\\\"94\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#111827\\\"/>\\n</svg>\",\n compact: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#f3f4f6\\\"/>\\n <rect x=\\\"6\\\" y=\\\"8\\\" width=\\\"26\\\" height=\\\"58\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\"/>\\n <rect x=\\\"34\\\" y=\\\"8\\\" width=\\\"26\\\" height=\\\"58\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\"/>\\n <rect x=\\\"62\\\" y=\\\"8\\\" width=\\\"26\\\" height=\\\"58\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\"/>\\n <rect x=\\\"90\\\" y=\\\"8\\\" width=\\\"24\\\" height=\\\"58\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\"/>\\n <text x=\\\"10\\\" y=\\\"22\\\" font-size=\\\"4.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$0</text>\\n <text x=\\\"38\\\" y=\\\"22\\\" font-size=\\\"4.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$19</text>\\n <text x=\\\"66\\\" y=\\\"22\\\" font-size=\\\"4.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$49</text>\\n <text x=\\\"94\\\" y=\\\"22\\\" font-size=\\\"4.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$99</text>\\n <g fill=\\\"#9ca3af\\\">\\n <rect x=\\\"10\\\" y=\\\"28\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"32\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"36\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"40\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"44\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"48\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"52\\\" width=\\\"16\\\" height=\\\"0.8\\\"/>\\n <rect x=\\\"38\\\" y=\\\"28\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"32\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"36\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"40\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"44\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"48\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"52\\\" width=\\\"16\\\" height=\\\"0.8\\\"/>\\n <rect x=\\\"66\\\" y=\\\"28\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"32\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"36\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"40\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"44\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"48\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"52\\\" width=\\\"16\\\" height=\\\"0.8\\\"/>\\n <rect x=\\\"94\\\" y=\\\"28\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"32\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"36\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"40\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"44\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"48\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"52\\\" width=\\\"14\\\" height=\\\"0.8\\\"/>\\n </g>\\n <rect x=\\\"10\\\" y=\\\"58\\\" width=\\\"10\\\" height=\\\"2\\\" fill=\\\"#1b8a5a\\\"/>\\n <rect x=\\\"38\\\" y=\\\"58\\\" width=\\\"10\\\" height=\\\"2\\\" fill=\\\"#1b8a5a\\\"/>\\n <rect x=\\\"66\\\" y=\\\"58\\\" width=\\\"10\\\" height=\\\"2\\\" fill=\\\"#1b8a5a\\\"/>\\n <rect x=\\\"94\\\" y=\\\"58\\\" width=\\\"10\\\" height=\\\"2\\\" fill=\\\"#1b8a5a\\\"/>\\n</svg>\",\n glass: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <defs>\\n <linearGradient id=\\\"pc-bg-glass\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"1\\\" y2=\\\"1\\\">\\n <stop offset=\\\"0\\\" stop-color=\\\"#a5b4fc\\\"/>\\n <stop offset=\\\"0.5\\\" stop-color=\\\"#fca5a5\\\"/>\\n <stop offset=\\\"1\\\" stop-color=\\\"#fde68a\\\"/>\\n </linearGradient>\\n <linearGradient id=\\\"pc-glass\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"0\\\" y2=\\\"1\\\">\\n <stop offset=\\\"0\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"0.7\\\"/>\\n <stop offset=\\\"1\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"0.35\\\"/>\\n </linearGradient>\\n </defs>\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"url(#pc-bg-glass)\\\"/>\\n <rect x=\\\"8\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"8\\\" fill=\\\"url(#pc-glass)\\\" stroke=\\\"#ffffff\\\" stroke-opacity=\\\"0.6\\\"/>\\n <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"8\\\" fill=\\\"url(#pc-glass)\\\" stroke=\\\"#ffffff\\\" stroke-opacity=\\\"0.6\\\"/>\\n <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"8\\\" fill=\\\"url(#pc-glass)\\\" stroke=\\\"#ffffff\\\" stroke-opacity=\\\"0.6\\\"/>\\n <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"8\\\" fill=\\\"url(#pc-glass)\\\" stroke=\\\"#ffffff\\\" stroke-opacity=\\\"0.6\\\"/>\\n <text x=\\\"12\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#312e81\\\">$0</text>\\n <text x=\\\"40\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#312e81\\\">$19</text>\\n <text x=\\\"68\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#312e81\\\">$49</text>\\n <text x=\\\"95\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#312e81\\\">$99</text>\\n <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#312e81\\\"/>\\n <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#312e81\\\"/>\\n <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#312e81\\\"/>\\n <rect x=\\\"95\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#312e81\\\"/>\\n</svg>\",\n pill: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#fefce8\\\"/>\\n <rect x=\\\"8\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"12\\\" fill=\\\"#fff\\\"/>\\n <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"12\\\" fill=\\\"#fff\\\"/>\\n <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"12\\\" fill=\\\"#fff\\\"/>\\n <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"12\\\" fill=\\\"#fff\\\"/>\\n <text x=\\\"20\\\" y=\\\"26\\\" font-size=\\\"10\\\" text-anchor=\\\"middle\\\">\\uD83D\\uDE80</text>\\n <text x=\\\"48\\\" y=\\\"26\\\" font-size=\\\"10\\\" text-anchor=\\\"middle\\\">\\u26A1</text>\\n <text x=\\\"76\\\" y=\\\"26\\\" font-size=\\\"10\\\" text-anchor=\\\"middle\\\">\\uD83D\\uDC8E</text>\\n <text x=\\\"102\\\" y=\\\"26\\\" font-size=\\\"10\\\" text-anchor=\\\"middle\\\">\\uD83C\\uDFC6</text>\\n <text x=\\\"20\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" text-anchor=\\\"middle\\\" fill=\\\"#111827\\\">$0</text>\\n <text x=\\\"48\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" text-anchor=\\\"middle\\\" fill=\\\"#111827\\\">$19</text>\\n <text x=\\\"76\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" text-anchor=\\\"middle\\\" fill=\\\"#111827\\\">$49</text>\\n <text x=\\\"102\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" text-anchor=\\\"middle\\\" fill=\\\"#111827\\\">$99</text>\\n <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#f59e0b\\\"/>\\n <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#f59e0b\\\"/>\\n <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#f59e0b\\\"/>\\n <rect x=\\\"96\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#f59e0b\\\"/>\\n</svg>\",\n neon: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#0a0a0f\\\"/>\\n <rect x=\\\"8\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"#14141c\\\" stroke=\\\"#00e5ff\\\" stroke-width=\\\"0.6\\\" stroke-opacity=\\\"0.9\\\"/>\\n <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"#14141c\\\" stroke=\\\"#00e5ff\\\" stroke-width=\\\"1.6\\\"/>\\n <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"#14141c\\\" stroke=\\\"#00e5ff\\\" stroke-width=\\\"0.6\\\" stroke-opacity=\\\"0.9\\\"/>\\n <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"#14141c\\\" stroke=\\\"#00e5ff\\\" stroke-width=\\\"0.6\\\" stroke-opacity=\\\"0.9\\\"/>\\n <text x=\\\"12\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#00e5ff\\\">$0</text>\\n <text x=\\\"40\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#00e5ff\\\">$19</text>\\n <text x=\\\"68\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#00e5ff\\\">$49</text>\\n <text x=\\\"95\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#00e5ff\\\">$99</text>\\n <g fill=\\\"#6b7280\\\">\\n <rect x=\\\"12\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"12\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"12\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1\\\"/>\\n <rect x=\\\"40\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"40\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"40\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1\\\"/>\\n <rect x=\\\"68\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"68\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"68\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1\\\"/>\\n <rect x=\\\"95\\\" y=\\\"38\\\" width=\\\"12\\\" height=\\\"1\\\"/><rect x=\\\"95\\\" y=\\\"42\\\" width=\\\"12\\\" height=\\\"1\\\"/><rect x=\\\"95\\\" y=\\\"46\\\" width=\\\"12\\\" height=\\\"1\\\"/>\\n </g>\\n <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#00e5ff\\\"/>\\n <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#00e5ff\\\"/>\\n <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#00e5ff\\\"/>\\n <rect x=\\\"95\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#00e5ff\\\"/>\\n</svg>\",\n brutalist: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#fef08a\\\"/>\\n <rect x=\\\"9\\\" y=\\\"9\\\" width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#000\\\"/>\\n <rect x=\\\"8\\\" y=\\\"8\\\" width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#fff\\\" stroke=\\\"#000\\\" stroke-width=\\\"1.5\\\"/>\\n <rect x=\\\"37\\\" y=\\\"9\\\" width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#000\\\"/>\\n <rect x=\\\"36\\\" y=\\\"8\\\" width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#ff4c6a\\\" stroke=\\\"#000\\\" stroke-width=\\\"1.5\\\"/>\\n <rect x=\\\"65\\\" y=\\\"9\\\" width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#000\\\"/>\\n <rect x=\\\"64\\\" y=\\\"8\\\" width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#fff\\\" stroke=\\\"#000\\\" stroke-width=\\\"1.5\\\"/>\\n <rect x=\\\"93\\\" y=\\\"9\\\" width=\\\"20\\\" height=\\\"52\\\" fill=\\\"#000\\\"/>\\n <rect x=\\\"92\\\" y=\\\"8\\\" width=\\\"20\\\" height=\\\"52\\\" fill=\\\"#fff\\\" stroke=\\\"#000\\\" stroke-width=\\\"1.5\\\"/>\\n <text x=\\\"12\\\" y=\\\"28\\\" font-size=\\\"10\\\" font-weight=\\\"900\\\" fill=\\\"#000\\\">$0</text>\\n <text x=\\\"40\\\" y=\\\"28\\\" font-size=\\\"10\\\" font-weight=\\\"900\\\" fill=\\\"#fff\\\">$19</text>\\n <text x=\\\"68\\\" y=\\\"28\\\" font-size=\\\"10\\\" font-weight=\\\"900\\\" fill=\\\"#000\\\">$49</text>\\n <text x=\\\"95\\\" y=\\\"28\\\" font-size=\\\"10\\\" font-weight=\\\"900\\\" fill=\\\"#000\\\">$99</text>\\n <rect x=\\\"12\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" fill=\\\"#000\\\"/>\\n <rect x=\\\"40\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" fill=\\\"#000\\\"/>\\n <rect x=\\\"68\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" fill=\\\"#000\\\"/>\\n <rect x=\\\"95\\\" y=\\\"50\\\" width=\\\"14\\\" height=\\\"5\\\" fill=\\\"#000\\\"/>\\n</svg>\",\n editorial: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#faf7f2\\\"/>\\n <rect x=\\\"8\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d4d4aa\\\"/>\\n <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d4d4aa\\\"/>\\n <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d4d4aa\\\"/>\\n <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d4d4aa\\\"/>\\n <text x=\\\"12\\\" y=\\\"22\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"5\\\" font-style=\\\"italic\\\" fill=\\\"#57534e\\\">Free</text>\\n <text x=\\\"40\\\" y=\\\"22\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"5\\\" font-style=\\\"italic\\\" fill=\\\"#57534e\\\">Basic</text>\\n <text x=\\\"68\\\" y=\\\"22\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"5\\\" font-style=\\\"italic\\\" fill=\\\"#57534e\\\">Standard</text>\\n <text x=\\\"95\\\" y=\\\"22\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"5\\\" font-style=\\\"italic\\\" fill=\\\"#57534e\\\">Premium</text>\\n <rect x=\\\"12\\\" y=\\\"25\\\" width=\\\"10\\\" height=\\\"0.6\\\" fill=\\\"#b45309\\\"/>\\n <rect x=\\\"40\\\" y=\\\"25\\\" width=\\\"10\\\" height=\\\"0.6\\\" fill=\\\"#b45309\\\"/>\\n <rect x=\\\"68\\\" y=\\\"25\\\" width=\\\"10\\\" height=\\\"0.6\\\" fill=\\\"#b45309\\\"/>\\n <rect x=\\\"95\\\" y=\\\"25\\\" width=\\\"10\\\" height=\\\"0.6\\\" fill=\\\"#b45309\\\"/>\\n <text x=\\\"12\\\" y=\\\"38\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$0</text>\\n <text x=\\\"40\\\" y=\\\"38\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$19</text>\\n <text x=\\\"68\\\" y=\\\"38\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$49</text>\\n <text x=\\\"95\\\" y=\\\"38\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$99</text>\\n <rect x=\\\"12\\\" y=\\\"55\\\" width=\\\"14\\\" height=\\\"4.5\\\" rx=\\\"0\\\" fill=\\\"none\\\" stroke=\\\"#b45309\\\" stroke-width=\\\"0.8\\\"/>\\n <rect x=\\\"40\\\" y=\\\"55\\\" width=\\\"14\\\" height=\\\"4.5\\\" rx=\\\"0\\\" fill=\\\"none\\\" stroke=\\\"#b45309\\\" stroke-width=\\\"0.8\\\"/>\\n <rect x=\\\"68\\\" y=\\\"55\\\" width=\\\"14\\\" height=\\\"4.5\\\" rx=\\\"0\\\" fill=\\\"none\\\" stroke=\\\"#b45309\\\" stroke-width=\\\"0.8\\\"/>\\n <rect x=\\\"95\\\" y=\\\"55\\\" width=\\\"12\\\" height=\\\"4.5\\\" rx=\\\"0\\\" fill=\\\"none\\\" stroke=\\\"#b45309\\\" stroke-width=\\\"0.8\\\"/>\\n</svg>\",\n gradient: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <defs>\\n <linearGradient id=\\\"pc-g1\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"1\\\" y2=\\\"1\\\"><stop offset=\\\"0\\\" stop-color=\\\"#94a3b8\\\"/><stop offset=\\\"1\\\" stop-color=\\\"#cbd5e1\\\"/></linearGradient>\\n <linearGradient id=\\\"pc-g2\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"1\\\" y2=\\\"1\\\"><stop offset=\\\"0\\\" stop-color=\\\"#7c3aed\\\"/><stop offset=\\\"1\\\" stop-color=\\\"#db2777\\\"/></linearGradient>\\n <linearGradient id=\\\"pc-g3\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"1\\\" y2=\\\"1\\\"><stop offset=\\\"0\\\" stop-color=\\\"#0891b2\\\"/><stop offset=\\\"1\\\" stop-color=\\\"#06b6d4\\\"/></linearGradient>\\n <linearGradient id=\\\"pc-g4\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"1\\\" y2=\\\"1\\\"><stop offset=\\\"0\\\" stop-color=\\\"#dc2626\\\"/><stop offset=\\\"1\\\" stop-color=\\\"#f97316\\\"/></linearGradient>\\n </defs>\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#f9fafb\\\"/>\\n <rect x=\\\"8\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"url(#pc-g1)\\\"/>\\n <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"url(#pc-g2)\\\"/>\\n <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"url(#pc-g3)\\\"/>\\n <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"url(#pc-g4)\\\"/>\\n <text x=\\\"12\\\" y=\\\"30\\\" font-size=\\\"8\\\" font-weight=\\\"900\\\" fill=\\\"#fff\\\">$0</text>\\n <text x=\\\"40\\\" y=\\\"30\\\" font-size=\\\"8\\\" font-weight=\\\"900\\\" fill=\\\"#fff\\\">$19</text>\\n <text x=\\\"68\\\" y=\\\"30\\\" font-size=\\\"8\\\" font-weight=\\\"900\\\" fill=\\\"#fff\\\">$49</text>\\n <text x=\\\"95\\\" y=\\\"30\\\" font-size=\\\"8\\\" font-weight=\\\"900\\\" fill=\\\"#fff\\\">$99</text>\\n <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#fff\\\"/>\\n <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#fff\\\"/>\\n <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#fff\\\"/>\\n <rect x=\\\"95\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#fff\\\"/>\\n</svg>\",\n banded: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#fafafa\\\"/>\\n <!-- one joined bar: outer radius on ends, dividers between -->\\n <rect x=\\\"8\\\" y=\\\"10\\\" width=\\\"104\\\" height=\\\"52\\\" rx=\\\"8\\\" fill=\\\"#ffffff\\\" stroke=\\\"#e5e7eb\\\"/>\\n <line x1=\\\"34\\\" y1=\\\"14\\\" x2=\\\"34\\\" y2=\\\"58\\\" stroke=\\\"#e5e7eb\\\" stroke-width=\\\"0.6\\\"/>\\n <line x1=\\\"60\\\" y1=\\\"14\\\" x2=\\\"60\\\" y2=\\\"58\\\" stroke=\\\"#e5e7eb\\\" stroke-width=\\\"0.6\\\"/>\\n <line x1=\\\"86\\\" y1=\\\"14\\\" x2=\\\"86\\\" y2=\\\"58\\\" stroke=\\\"#e5e7eb\\\" stroke-width=\\\"0.6\\\"/>\\n <!-- highlighted cell (Standard): tinted bg + top strip -->\\n <rect x=\\\"34\\\" y=\\\"10\\\" width=\\\"26\\\" height=\\\"52\\\" fill=\\\"#fffdf0\\\"/>\\n <rect x=\\\"34\\\" y=\\\"10\\\" width=\\\"26\\\" height=\\\"6\\\" fill=\\\"#e8f1ff\\\"/>\\n <text x=\\\"38\\\" y=\\\"14.2\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"3\\\" font-style=\\\"italic\\\" fill=\\\"#1e3a8a\\\" text-decoration=\\\"underline\\\">Best value</text>\\n <!-- prices (serif) -->\\n <text x=\\\"14\\\" y=\\\"34\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$0</text>\\n <text x=\\\"40\\\" y=\\\"34\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$19</text>\\n <text x=\\\"66\\\" y=\\\"34\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$49</text>\\n <text x=\\\"92\\\" y=\\\"34\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$99</text>\\n <!-- Mailchimp-yellow CTA pills -->\\n <rect x=\\\"12\\\" y=\\\"50\\\" width=\\\"18\\\" height=\\\"6\\\" rx=\\\"3\\\" fill=\\\"#ffe01b\\\" stroke=\\\"#1a1a1a\\\" stroke-width=\\\"0.3\\\"/>\\n <rect x=\\\"38\\\" y=\\\"50\\\" width=\\\"18\\\" height=\\\"6\\\" rx=\\\"3\\\" fill=\\\"#ffe01b\\\" stroke=\\\"#1a1a1a\\\" stroke-width=\\\"0.3\\\"/>\\n <rect x=\\\"64\\\" y=\\\"50\\\" width=\\\"18\\\" height=\\\"6\\\" rx=\\\"3\\\" fill=\\\"#ffe01b\\\" stroke=\\\"#1a1a1a\\\" stroke-width=\\\"0.3\\\"/>\\n <rect x=\\\"90\\\" y=\\\"50\\\" width=\\\"18\\\" height=\\\"6\\\" rx=\\\"3\\\" fill=\\\"#ffe01b\\\" stroke=\\\"#1a1a1a\\\" stroke-width=\\\"0.3\\\"/>\\n</svg>\",\n tier: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#f5f3ff\\\"/>\\n <!-- staircase: index 0 lowest, last highest -->\\n <rect x=\\\"8\\\" y=\\\"22\\\" width=\\\"24\\\" height=\\\"44\\\" rx=\\\"5\\\" fill=\\\"#ffffff\\\" stroke=\\\"#e0e7ff\\\"/>\\n <rect x=\\\"36\\\" y=\\\"18\\\" width=\\\"24\\\" height=\\\"48\\\" rx=\\\"5\\\" fill=\\\"#ffffff\\\" stroke=\\\"#e0e7ff\\\"/>\\n <rect x=\\\"64\\\" y=\\\"14\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"5\\\" fill=\\\"#ffffff\\\" stroke=\\\"#e0e7ff\\\"/>\\n <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"56\\\" rx=\\\"5\\\" fill=\\\"#ffffff\\\" stroke=\\\"#c7d2fe\\\" stroke-width=\\\"1.5\\\"/>\\n <!-- accent chip badges -->\\n <rect x=\\\"11\\\" y=\\\"25\\\" width=\\\"6\\\" height=\\\"6\\\" rx=\\\"2\\\" fill=\\\"#4f46e530\\\"/>\\n <rect x=\\\"39\\\" y=\\\"21\\\" width=\\\"6\\\" height=\\\"6\\\" rx=\\\"2\\\" fill=\\\"#4f46e530\\\"/>\\n <rect x=\\\"67\\\" y=\\\"17\\\" width=\\\"6\\\" height=\\\"6\\\" rx=\\\"2\\\" fill=\\\"#4f46e530\\\"/>\\n <rect x=\\\"95\\\" y=\\\"13\\\" width=\\\"6\\\" height=\\\"6\\\" rx=\\\"2\\\" fill=\\\"#4f46e530\\\"/>\\n <!-- prices -->\\n <text x=\\\"12\\\" y=\\\"46\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#1e1b4b\\\">$0</text>\\n <text x=\\\"40\\\" y=\\\"42\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#1e1b4b\\\">$19</text>\\n <text x=\\\"68\\\" y=\\\"38\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#1e1b4b\\\">$49</text>\\n <text x=\\\"95\\\" y=\\\"34\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#1e1b4b\\\">$99</text>\\n <!-- indigo CTA -->\\n <rect x=\\\"12\\\" y=\\\"56\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#4f46e5\\\"/>\\n <rect x=\\\"40\\\" y=\\\"56\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#4f46e5\\\"/>\\n <rect x=\\\"68\\\" y=\\\"56\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#4f46e5\\\"/>\\n <rect x=\\\"94\\\" y=\\\"56\\\" width=\\\"14\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#4f46e5\\\"/>\\n</svg>\",\n neo: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <defs>\\n <filter id=\\\"pc-neo-soft\\\" x=\\\"-10%\\\" y=\\\"-10%\\\" width=\\\"120%\\\" height=\\\"120%\\\">\\n <feGaussianBlur stdDeviation=\\\"1.2\\\"/>\\n </filter>\\n </defs>\\n <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#e9edf3\\\"/>\\n <!-- soft-shadowed cards \\u2014 approximate neumorphism with layered rects -->\\n <g>\\n <rect x=\\\"10\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#c7cdd6\\\" opacity=\\\"0.55\\\" transform=\\\"translate(2 2)\\\"/>\\n <rect x=\\\"10\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#ffffff\\\" opacity=\\\"0.9\\\" transform=\\\"translate(-2 -2)\\\"/>\\n <rect x=\\\"10\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#e9edf3\\\"/>\\n </g>\\n <g>\\n <rect x=\\\"38\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#c7cdd6\\\" opacity=\\\"0.55\\\" transform=\\\"translate(2 2)\\\"/>\\n <rect x=\\\"38\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#ffffff\\\" opacity=\\\"0.9\\\" transform=\\\"translate(-2 -2)\\\"/>\\n <rect x=\\\"38\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#e9edf3\\\"/>\\n </g>\\n <g>\\n <rect x=\\\"66\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#c7cdd6\\\" opacity=\\\"0.55\\\" transform=\\\"translate(2 2)\\\"/>\\n <rect x=\\\"66\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#ffffff\\\" opacity=\\\"0.9\\\" transform=\\\"translate(-2 -2)\\\"/>\\n <rect x=\\\"66\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#e9edf3\\\"/>\\n </g>\\n <g>\\n <rect x=\\\"94\\\" y=\\\"12\\\" width=\\\"18\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#c7cdd6\\\" opacity=\\\"0.55\\\" transform=\\\"translate(2 2)\\\"/>\\n <rect x=\\\"94\\\" y=\\\"12\\\" width=\\\"18\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#ffffff\\\" opacity=\\\"0.9\\\" transform=\\\"translate(-2 -2)\\\"/>\\n <rect x=\\\"94\\\" y=\\\"12\\\" width=\\\"18\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#e9edf3\\\"/>\\n </g>\\n <!-- prices -->\\n <text x=\\\"13\\\" y=\\\"32\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#1e293b\\\">$0</text>\\n <text x=\\\"41\\\" y=\\\"32\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#1e293b\\\">$19</text>\\n <text x=\\\"69\\\" y=\\\"32\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#1e293b\\\">$49</text>\\n <text x=\\\"96\\\" y=\\\"32\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#1e293b\\\">$99</text>\\n <!-- periwinkle buttons with soft look -->\\n <rect x=\\\"13\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#eef1f6\\\" stroke=\\\"#d6dbe4\\\"/>\\n <rect x=\\\"41\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#eef1f6\\\" stroke=\\\"#d6dbe4\\\"/>\\n <rect x=\\\"69\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#eef1f6\\\" stroke=\\\"#d6dbe4\\\"/>\\n <rect x=\\\"96\\\" y=\\\"50\\\" width=\\\"12\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#eef1f6\\\" stroke=\\\"#d6dbe4\\\"/>\\n</svg>\"\n};\nPricingCardsElement.VALID_STYLES = VALID_STYLES;\nPricingCardsElement.DEFAULT_STYLE = DEFAULT_STYLE;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PricingCardsElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PricingCardsElement.js?");
/***/ }),
/***/ "./src/includes/PricingCardsWidget.js":
/*!********************************************!*\
!*** ./src/includes/PricingCardsWidget.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _PricingCardsElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./PricingCardsElement.js */ \"./src/includes/PricingCardsElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * PricingCardsWidget — the widget-box entry that drops a fully populated\n * PricingCardsElement onto the canvas.\n *\n * Seeds 4 realistic plan cards (Free / Basic / Standard / Premium) using\n * native elements (Heading, PElement for price / period / features,\n * ButtonElement CTA). The Standard card is highlighted with a \"Most Popular\"\n * badge + yellow accent to mirror the dominant pattern on every pricing page\n * (Mailchimp, Stripe, Vercel…). User can change style from `highlighted`\n * default to any of the other 9 presets via the StyleControl.\n *\n * Replaces retired PricingTableWidget.\n */\nvar PricingCardsWidget = /*#__PURE__*/function (_BaseWidget) {\n function PricingCardsWidget() {\n var _this;\n _classCallCheck(this, PricingCardsWidget);\n _this = _callSuper(this, PricingCardsWidget);\n var el = new _PricingCardsElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('PricingCards');\n el.style = 'highlighted';\n el.cell_gap = 20;\n el.append(el.newCell({\n planName: 'Free',\n planDesc: 'Forever free, no credit card needed.',\n planPrice: '$0',\n planPeriod: 'per month',\n features: ['Up to 500 subscribers', '1 campaign per month', 'Basic templates', 'Community support'],\n ctaText: 'Start free',\n ctaUrl: '#free'\n }));\n el.append(el.newCell({\n planName: 'Basic',\n planDesc: 'For solo creators just starting.',\n planPrice: '$19',\n planPeriod: 'per month',\n features: ['Up to 5,000 subscribers', '10 campaigns per month', 'A/B testing', 'Audience segments', 'Email support'],\n ctaText: 'Choose Basic',\n ctaUrl: '#basic'\n }));\n var standard = el.newCell({\n planName: 'Standard',\n planDesc: 'Most teams pick this one.',\n planPrice: '$49',\n planPeriod: 'per month',\n features: ['Up to 50,000 subscribers', 'Unlimited campaigns', 'Automations & journeys', 'Advanced analytics', 'Priority support'],\n ctaText: 'Choose Standard',\n ctaUrl: '#standard'\n });\n standard.highlighted = true;\n standard.badge = 'Most Popular';\n standard.icon = 'workspace_premium';\n standard.accent_color = '#ffcc2a';\n el.append(standard);\n var premium = el.newCell({\n planName: 'Premium',\n planDesc: 'For growing companies & agencies.',\n planPrice: '$99',\n planPeriod: 'per month',\n features: ['Unlimited subscribers', 'Unlimited campaigns', 'Multi-user roles & SSO', 'Dedicated IP & SLA', '24/7 phone support'],\n ctaText: 'Contact sales',\n ctaUrl: '#sales'\n });\n premium.icon = 'diamond';\n el.append(premium);\n _this.block.appendElements([el]);\n return _this;\n }\n _inherits(PricingCardsWidget, _BaseWidget);\n return _createClass(PricingCardsWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.pricing_cards');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'view_column';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PricingCardsWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PricingCardsWidget.js?");
/***/ }),
/***/ "./src/includes/RSSControl.js":
/*!************************************!*\
!*** ./src/includes/RSSControl.js ***!
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * RSSControl — combined RSS feed editor: URL + fetch, style select,\n * 6 toggle switches, 2 numeric steppers (max items, content length).\n *\n * Consumer: RSSElement (one panel section handles the whole element).\n *\n * 2026-04-18 Phase 2.29 rewrite — replaced the Bootstrap surface\n * (`.form-control form-control-sm` ×3, `.form-select form-select-sm`,\n * `.btn btn-outline-secondary`, `.input-group`, `.builder-checkbox-modern`,\n * `.toggle-label`, `.badge bg-success`, `.py-2 px-3`, `.d-flex`, plus a\n * pile of inline hex colours / pixel widths) with `.bjs-text-input`,\n * `.bjs-btn--primary`, `.bjs-select`, `.bjs-number-input`, `.bjs-toggle`,\n * and `.bjs-info-banner--{success,error,info}` inside new\n * `.bjs-rss-control` / `.bjs-rss-section` scoped classes.\n *\n * Logic upgrades:\n * - Status area uses `.bjs-info-banner` with `textContent` (no HTML injection\n * from rssHandler error payloads).\n * - Number steppers (limit + content_length) are editable — user can type,\n * blur-clamps to [min,max], arrow keys +/- step.\n * - Fetch button disables itself during in-flight request; auto-re-enables\n * in `finally()`.\n * - `textContent` used everywhere for user/server-supplied strings.\n */\nvar RSSControl = /*#__PURE__*/function () {\n function RSSControl(label, values, callback) {\n _classCallCheck(this, RSSControl);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.callback = callback;\n this.url = values.url || '';\n this.limit = values.limit || 5;\n this.style = values.style || 'classic';\n this.show_title = values.show_title !== undefined ? values.show_title : true;\n this.show_desc = values.show_desc !== undefined ? values.show_desc : true;\n this.show_date = values.show_date !== undefined ? values.show_date : true;\n this.show_image = values.show_image !== undefined ? values.show_image : true;\n this.show_link = values.show_link !== undefined ? values.show_link : false;\n this.show_author = values.show_author !== undefined ? values.show_author : false;\n this.content_length = values.content_length !== undefined ? values.content_length : 150;\n this.fetchCount = values.fetchCount;\n this._fetching = false;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-rss-control');\n this.render();\n }\n return _createClass(RSSControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var toggles = [{\n key: 'show_title',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_title')\n }, {\n key: 'show_desc',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_desc')\n }, {\n key: 'show_date',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_date')\n }, {\n key: 'show_image',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_image')\n }, {\n key: 'show_link',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_link')\n }, {\n key: 'show_author',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_author')\n }];\n var togglesHtml = toggles.map(function (t) {\n var tid = \"\".concat(_this.id, \"_\").concat(t.key);\n return \"\\n <div class=\\\"bjs-rss-row\\\">\\n <label class=\\\"bjs-rss-row-label\\\" for=\\\"\".concat(tid, \"\\\">\").concat(_this._escape(t.label), \"</label>\\n <label class=\\\"bjs-toggle\\\">\\n <input type=\\\"checkbox\\\" id=\\\"\").concat(tid, \"\\\" class=\\\"bjs-toggle-input\\\"\\n data-toggle-key=\\\"\").concat(t.key, \"\\\" \").concat(_this[t.key] ? 'checked' : '', \">\\n <span class=\\\"bjs-toggle-track\\\"></span>\\n <span class=\\\"bjs-toggle-thumb\\\"></span>\\n </label>\\n </div>\\n \");\n }).join('');\n this.domNode.innerHTML = \"\\n <section class=\\\"bjs-rss-section\\\">\\n <div class=\\\"bjs-rss-section-title\\\">\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.rss_feed')), \"</div>\\n\\n <div class=\\\"bjs-rss-url-row\\\">\\n <input type=\\\"text\\\" class=\\\"bjs-text-input\\\" data-control=\\\"url\\\"\\n value=\\\"\").concat(this._escape(this.url), \"\\\"\\n placeholder=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.enter_url')), \"\\\"\\n aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.enter_url')), \"\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-btn bjs-btn--primary\\\" data-control=\\\"fetch\\\">\\n <span>\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetch')), \"</span>\\n </button>\\n </div>\\n\\n <div class=\\\"bjs-rss-status\\\" data-control=\\\"status\\\"></div>\\n\\n <div class=\\\"bjs-rss-row\\\">\\n <label class=\\\"bjs-rss-row-label\\\" for=\\\"\").concat(this.id, \"_style\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.style')), \"</label>\\n <select id=\\\"\").concat(this.id, \"_style\\\" class=\\\"bjs-select\\\" data-control=\\\"style\\\">\\n <option value=\\\"modern\\\" \").concat(this.style === 'modern' ? 'selected' : '', \">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.style_modern')), \"</option>\\n <option value=\\\"classic\\\" \").concat(this.style === 'classic' ? 'selected' : '', \">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.style_classic')), \"</option>\\n </select>\\n </div>\\n </section>\\n\\n <section class=\\\"bjs-rss-section\\\">\\n <div class=\\\"bjs-rss-section-title\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.rss_display')), \"</div>\\n\\n <div class=\\\"bjs-rss-toggles\\\">\\n \").concat(togglesHtml, \"\\n </div>\\n\\n <div class=\\\"bjs-rss-row\\\">\\n <label class=\\\"bjs-rss-row-label\\\" for=\\\"\").concat(this.id, \"_limit\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.max_items')), \"</label>\\n <div class=\\\"bjs-number-input\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-control=\\\"limit-dec\\\" aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.decrease', 'Decrease')), \"\\\">−</button>\\n <input id=\\\"\").concat(this.id, \"_limit\\\" type=\\\"number\\\" class=\\\"bjs-number-value\\\"\\n data-control=\\\"limit\\\" value=\\\"\").concat(this.limit, \"\\\" min=\\\"1\\\" max=\\\"50\\\" step=\\\"1\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-control=\\\"limit-inc\\\" aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.increase', 'Increase')), \"\\\">+</button>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-rss-row\\\">\\n <label class=\\\"bjs-rss-row-label\\\" for=\\\"\").concat(this.id, \"_cl\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.content_length')), \"</label>\\n <div class=\\\"bjs-number-input\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-control=\\\"cl-dec\\\" aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.decrease', 'Decrease')), \"\\\">−</button>\\n <input id=\\\"\").concat(this.id, \"_cl\\\" type=\\\"number\\\" class=\\\"bjs-number-value\\\"\\n data-control=\\\"content_length\\\" value=\\\"\").concat(this.content_length, \"\\\" min=\\\"0\\\" max=\\\"1000\\\" step=\\\"10\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-control=\\\"cl-inc\\\" aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.increase', 'Increase')), \"\\\">+</button>\\n </div>\\n </div>\\n </section>\\n \");\n this._bindEvents();\n this._renderInitialStatus();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this2 = this;\n this._fetchBtn().addEventListener('click', function () {\n return _this2._handleFetch();\n });\n this._urlInput().addEventListener('keydown', function (e) {\n if (e.key === 'Enter') {\n e.preventDefault();\n _this2._handleFetch();\n }\n });\n this.domNode.querySelector('[data-control=\"style\"]').addEventListener('change', function (e) {\n _this2.style = e.target.value;\n _this2._autoApply();\n });\n this.domNode.querySelectorAll('[data-toggle-key]').forEach(function (el) {\n el.addEventListener('change', function (e) {\n _this2[e.target.dataset.toggleKey] = e.target.checked;\n _this2._autoApply();\n });\n });\n this._bindStepper('limit', {\n min: 1,\n max: 50,\n step: 1\n });\n this._bindStepper('content_length', {\n min: 0,\n max: 1000,\n step: 10\n });\n }\n }, {\n key: \"_bindStepper\",\n value: function _bindStepper(key, _ref) {\n var _this3 = this;\n var min = _ref.min,\n max = _ref.max,\n step = _ref.step;\n var decSel = key === 'limit' ? '[data-control=\"limit-dec\"]' : '[data-control=\"cl-dec\"]';\n var incSel = key === 'limit' ? '[data-control=\"limit-inc\"]' : '[data-control=\"cl-inc\"]';\n var input = this.domNode.querySelector(\"[data-control=\\\"\".concat(key, \"\\\"]\"));\n var dec = this.domNode.querySelector(decSel);\n var inc = this.domNode.querySelector(incSel);\n var clamp = function clamp(n) {\n return Math.max(min, Math.min(max, n));\n };\n var write = function write(n) {\n _this3[key] = clamp(n);\n input.value = _this3[key];\n _this3._autoApply();\n };\n dec.addEventListener('click', function () {\n return write(_this3[key] - step);\n });\n inc.addEventListener('click', function () {\n return write(_this3[key] + step);\n });\n input.addEventListener('input', function (e) {\n var raw = e.target.value;\n if (raw === '') return; /* allow partial typing */\n var n = parseFloat(raw);\n if (!isNaN(n)) {\n _this3[key] = clamp(n);\n _this3._autoApply();\n }\n });\n input.addEventListener('blur', function (e) {\n var n = parseFloat(e.target.value);\n if (isNaN(n)) {\n _this3[key] = min;\n } else {\n _this3[key] = clamp(n);\n }\n e.target.value = _this3[key];\n _this3._autoApply();\n });\n input.addEventListener('keydown', function (e) {\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n write(_this3[key] + step);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n write(_this3[key] - step);\n }\n });\n }\n }, {\n key: \"_renderInitialStatus\",\n value: function _renderInitialStatus() {\n if (this.fetchCount !== null && this.fetchCount !== undefined) {\n this._showSuccess(this.fetchCount);\n } else {\n this._statusArea().innerHTML = '';\n }\n }\n }, {\n key: \"_urlInput\",\n value: function _urlInput() {\n return this.domNode.querySelector('[data-control=\"url\"]');\n }\n }, {\n key: \"_fetchBtn\",\n value: function _fetchBtn() {\n return this.domNode.querySelector('[data-control=\"fetch\"]');\n }\n }, {\n key: \"_statusArea\",\n value: function _statusArea() {\n return this.domNode.querySelector('[data-control=\"status\"]');\n }\n }, {\n key: \"_showBanner\",\n value: function _showBanner(variant, iconName, text) {\n var variantClass = variant ? \" bjs-info-banner--\".concat(variant) : '';\n var area = this._statusArea();\n area.innerHTML = \"\\n <div class=\\\"bjs-info-banner\".concat(variantClass, \"\\\" role=\\\"status\\\">\\n <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">\").concat(iconName, \"</span>\\n <span class=\\\"bjs-info-banner-text\\\" data-control=\\\"status-text\\\"></span>\\n </div>\\n \");\n area.querySelector('[data-control=\"status-text\"]').textContent = text;\n }\n }, {\n key: \"_showError\",\n value: function _showError(msg) {\n this._showBanner('error', 'error', msg);\n }\n }, {\n key: \"_showInfo\",\n value: function _showInfo(msg) {\n this._showBanner('', 'sync', msg);\n }\n }, {\n key: \"_showSuccess\",\n value: function _showSuccess(count) {\n this.fetchCount = count;\n var label = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.items_found', 'items found');\n this._showBanner('success', 'check_circle', \"\".concat(count, \" \").concat(label));\n }\n }, {\n key: \"_autoApply\",\n value: function _autoApply() {\n this.callback.applySettings({\n url: this.url || null,\n limit: this.limit,\n style: this.style,\n show_title: this.show_title,\n show_desc: this.show_desc,\n show_date: this.show_date,\n show_image: this.show_image,\n show_link: this.show_link,\n show_author: this.show_author,\n content_length: this.content_length\n });\n }\n }, {\n key: \"_handleFetch\",\n value: function _handleFetch() {\n var _this$host$rssHandler,\n _this$host,\n _this4 = this;\n var url = this._urlInput().value.trim();\n if (!url) {\n this._showError(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.url_required'));\n return;\n }\n var rssRegex = /^(http|https):\\/\\/[^\\s$.?#].[^\\s]*$/;\n if (!rssRegex.test(url)) {\n this._showError(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.invalid_url'));\n return;\n }\n this.url = url;\n this._fetching = true;\n var fetchBtn = this._fetchBtn();\n var labelSpan = fetchBtn.querySelector('span');\n var originalText = labelSpan ? labelSpan.textContent : fetchBtn.textContent;\n if (labelSpan) labelSpan.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetching');else fetchBtn.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetching');\n fetchBtn.disabled = true;\n this._showInfo(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetching'));\n var rssHandler = (_this$host$rssHandler = (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.rssHandler) !== null && _this$host$rssHandler !== void 0 ? _this$host$rssHandler : null;\n if (!rssHandler) {\n this._showError(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.handler_missing', 'RSS handler not configured.'));\n if (labelSpan) labelSpan.textContent = originalText;else fetchBtn.textContent = originalText;\n fetchBtn.disabled = false;\n this._fetching = false;\n return;\n }\n fetch(\"\".concat(rssHandler, \"?url=\").concat(encodeURIComponent(url))).then(function (response) {\n if (!response.ok) {\n return response.json().then(function (data) {\n throw new Error(data.error || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetch_failed'));\n });\n }\n return response.json();\n }).then(function (data) {\n if (data.error) throw new Error(data.error);\n if (!data.items || !Array.isArray(data.items)) {\n throw new Error(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.invalid_format'));\n }\n _this4._showSuccess(data.count || data.items.length);\n _this4._autoApply();\n })[\"catch\"](function (error) {\n _this4._showError(error.message || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetch_failed'));\n })[\"finally\"](function () {\n _this4._fetching = false;\n if (labelSpan) labelSpan.textContent = originalText;else fetchBtn.textContent = originalText;\n fetchBtn.disabled = false;\n });\n }\n }, {\n key: \"_escape\",\n value: function _escape(s) {\n return String(s !== null && s !== void 0 ? s : '').replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<').replace(/>/g, '>');\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RSSControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RSSControl.js?");
/***/ }),
/***/ "./src/includes/RSSElement.js":
/*!************************************!*\
!*** ./src/includes/RSSElement.js ***!
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _RSSControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./RSSControl.js */ \"./src/includes/RSSControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\nvar RSSElement = /*#__PURE__*/function (_BaseElement) {\n function RSSElement(template, url, limit) {\n var _this;\n _classCallCheck(this, RSSElement);\n _this = _callSuper(this, RSSElement);\n _this.template = template;\n _this.url = url;\n _this.limit = limit || 5;\n _this.domNode = null;\n\n // Display options\n _this.style = 'classic'; // 'classic' | 'modern'\n _this.show_title = true;\n _this.show_desc = true;\n _this.show_date = true;\n _this.show_image = true;\n _this.show_link = false;\n _this.show_author = false;\n _this.content_length = 150; // 0 = no truncation\n\n // Transient state (not serialized)\n _this._items = null;\n _this._error = null;\n _this._loading = false;\n _this._fetchingUrl = null;\n _this._lastFetchedUrl = null;\n _this._lastFetchedLimit = null;\n\n // Formatter\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n padding_top: null,\n padding_right: null,\n padding_bottom: null,\n padding_left: null,\n background_color: null,\n background_image: null,\n background_position: null,\n background_size: null,\n background_repeat: null,\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_style: null,\n border_left_width: null,\n border_left_color: null,\n border_radius: null\n });\n return _this;\n }\n _inherits(RSSElement, _BaseElement);\n return _createClass(RSSElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.rss');\n }\n\n // Helper for description truncation — passed to template\n }, {\n key: \"_truncate\",\n value: function _truncate(text, maxLen) {\n if (!text) return '';\n if (!maxLen || maxLen <= 0) return text;\n return text.length > maxLen ? text.substring(0, maxLen) + '...' : text;\n }\n }, {\n key: \"_renderTemplate\",\n value: function _renderTemplate() {\n var _this$url;\n this.domNode.innerHTML = this.renderTemplate({\n url: (_this$url = this.url) !== null && _this$url !== void 0 ? _this$url : false,\n items: this._items,\n loading: this._loading,\n error: this._error,\n style: this.style,\n show_title: this.show_title,\n show_desc: this.show_desc,\n show_date: this.show_date,\n show_image: this.show_image,\n show_link: this.show_link,\n show_author: this.show_author,\n content_length: this.content_length,\n truncate: this._truncate.bind(this),\n I18n: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n // formatter auto-merged by BaseElement.renderTemplate (W0.2c)\n });\n }\n }, {\n key: \"_getRssHandler\",\n value: function _getRssHandler() {\n var _this$host$rssHandler, _this$host;\n // Read from injected host (per-instance — multi-instance safe).\n return (_this$host$rssHandler = (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.rssHandler) !== null && _this$host$rssHandler !== void 0 ? _this$host$rssHandler : null;\n }\n }, {\n key: \"_fetchFeed\",\n value: function _fetchFeed() {\n var _this2 = this;\n var rssHandler = this._getRssHandler();\n if (!this.url || !rssHandler) return;\n var fetchUrl = this.url;\n this._fetchingUrl = fetchUrl;\n this._loading = true;\n this._error = null;\n this._renderTemplate();\n fetch(\"\".concat(rssHandler, \"?url=\").concat(encodeURIComponent(this.url))).then(function (response) {\n if (!response.ok) {\n return response.json().then(function (data) {\n throw new Error(data.error || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetch_failed'));\n });\n }\n return response.json();\n }).then(function (data) {\n // Stale response guard\n if (_this2._fetchingUrl !== fetchUrl) return;\n if (data.error) {\n throw new Error(data.error);\n }\n if (!data.items || !Array.isArray(data.items)) {\n throw new Error(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.invalid_format'));\n }\n _this2._items = data.items.slice(0, _this2.limit);\n _this2._error = null;\n _this2._loading = false;\n _this2._lastFetchedUrl = fetchUrl;\n _this2._lastFetchedLimit = _this2.limit;\n _this2._fetchingUrl = null;\n _this2._renderTemplate();\n })[\"catch\"](function (error) {\n // Stale response guard\n if (_this2._fetchingUrl !== fetchUrl) return;\n _this2._items = null;\n _this2._error = error.message || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetch_failed');\n _this2._loading = false;\n _this2._fetchingUrl = null;\n _this2._renderTemplate();\n });\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n if (!this.url) {\n // No URL — show placeholder\n this._items = null;\n this._error = null;\n this._loading = false;\n this._renderTemplate();\n } else if (this._lastFetchedUrl === this.url && this._lastFetchedLimit >= this.limit && this._items) {\n // Cached items still valid — re-render with possibly updated display options\n // Trim items if limit decreased\n var displayItems = this._items.slice(0, this.limit);\n this._items = displayItems;\n this._renderTemplate();\n } else {\n // Need to fetch (new URL or limit increased)\n this._fetchFeed();\n }\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(RSSElement, \"getData\", this, 3)([])), {}, {\n url: this.url,\n limit: this.limit,\n style: this.style,\n show_title: this.show_title,\n show_desc: this.show_desc,\n show_date: this.show_date,\n show_image: this.show_image,\n show_link: this.show_link,\n show_author: this.show_author,\n content_length: this.content_length\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this3 = this;\n return [\n // RSS Feed Control (URL, style, toggles, limit, content_length)\n new _RSSControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.rss_feed'), {\n url: this.url,\n limit: this.limit,\n style: this.style,\n show_title: this.show_title,\n show_desc: this.show_desc,\n show_date: this.show_date,\n show_image: this.show_image,\n show_link: this.show_link,\n show_author: this.show_author,\n content_length: this.content_length,\n fetchCount: this._items ? this._items.length : null\n }, {\n applySettings: function applySettings(settings) {\n var urlChanged = settings.url !== _this3.url;\n var limitIncreased = settings.limit > _this3.limit;\n _this3.url = settings.url;\n _this3.limit = settings.limit;\n _this3.style = settings.style;\n _this3.show_title = settings.show_title;\n _this3.show_desc = settings.show_desc;\n _this3.show_date = settings.show_date;\n _this3.show_image = settings.show_image;\n _this3.show_link = settings.show_link;\n _this3.show_author = settings.show_author;\n _this3.content_length = settings.content_length;\n if (urlChanged || limitIncreased) {\n // Clear cache to force re-fetch\n _this3._items = null;\n _this3._lastFetchedUrl = null;\n _this3._lastFetchedLimit = null;\n }\n _this3.render();\n }\n }),\n // W3.8b — PaddingMarginControl removed. RSS items are content\n // inside a Block; parent Block.padding handles layout spacing.\n\n // Background\n new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n color: this.formatter.getFormat('background_color'),\n image: this.formatter.getFormat('background_image'),\n position: this.formatter.getFormat('background_position'),\n size: this.formatter.getFormat('background_size'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n }, {\n setBackground: function setBackground(values) {\n _this3.formatter.setFormat('background_color', values.color);\n _this3.formatter.setFormat('background_image', values.image);\n _this3.formatter.setFormat('background_position', values.position);\n _this3.formatter.setFormat('background_size', values.size);\n _this3.formatter.setFormat('background_repeat', values.repeat);\n _this3.render();\n }\n }, {\n features: ['color', 'image', 'size', 'repeat', 'gradient']\n }),\n // Border\n new _BorderControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style'),\n border_top_width: this.formatter.getFormat('border_top_width'),\n border_top_color: this.formatter.getFormat('border_top_color'),\n border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n border_left_style: this.formatter.getFormat('border_left_style'),\n border_left_width: this.formatter.getFormat('border_left_width'),\n border_left_color: this.formatter.getFormat('border_left_color'),\n border_right_style: this.formatter.getFormat('border_right_style'),\n border_right_width: this.formatter.getFormat('border_right_width'),\n border_right_color: this.formatter.getFormat('border_right_color')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this3.formatter.setFormat('border_top_style', border_top_style);\n _this3.formatter.setFormat('border_top_width', border_top_width);\n _this3.formatter.setFormat('border_top_color', border_top_color);\n _this3.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this3.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this3.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this3.formatter.setFormat('border_left_style', border_left_style);\n _this3.formatter.setFormat('border_left_width', border_left_width);\n _this3.formatter.setFormat('border_left_color', border_left_color);\n _this3.formatter.setFormat('border_right_style', border_right_style);\n _this3.formatter.setFormat('border_right_width', border_right_width);\n _this3.formatter.setFormat('border_right_color', border_right_color);\n _this3.render();\n }\n }),\n // Border Radius\n new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n setRadius: function setRadius(v) {\n _this3.formatter.setFormat('border_radius', v);\n _this3.render();\n }\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var e = new RSSElement(data.template, data.url, data.limit);\n\n // Display options (backward-compatible defaults)\n e.style = data.style || 'classic';\n e.show_title = data.show_title !== undefined ? data.show_title : true;\n e.show_desc = data.show_desc !== undefined ? data.show_desc : true;\n e.show_date = data.show_date !== undefined ? data.show_date : true;\n e.show_image = data.show_image !== undefined ? data.show_image : true;\n e.show_link = data.show_link !== undefined ? data.show_link : false;\n e.show_author = data.show_author !== undefined ? data.show_author : false;\n e.content_length = data.content_length !== undefined ? data.content_length : 150;\n\n // Formatter\n if (data.formats) {\n e.formatter.formats = data.formats;\n }\n return e;\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RSSElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RSSElement.js?");
/***/ }),
/***/ "./src/includes/RSSWidget.js":
/*!***********************************!*\
!*** ./src/includes/RSSWidget.js ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar RSSWidget = /*#__PURE__*/function (_BaseWidget) {\n function RSSWidget() {\n var _this;\n _classCallCheck(this, RSSWidget);\n _this = _callSuper(this, RSSWidget); // Call the parent class constructor\n\n // Add a RSSElement to the widget\n var rssElement = new RSSElement('RSS', null, 5);\n\n // Append the new element to the block\n _this.block.appendElements([rssElement]);\n return _this;\n }\n _inherits(RSSWidget, _BaseWidget);\n return _createClass(RSSWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.rss');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'rss_feed';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RSSWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RSSWidget.js?");
/***/ }),
/***/ "./src/includes/RadioElement.js":
/*!**************************************!*\
!*** ./src/includes/RadioElement.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SelectControl.js */ \"./src/includes/SelectControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar RadioElement = /*#__PURE__*/function (_BaseElement) {\n function RadioElement(template) {\n var _this;\n var inputName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"\";\n var items = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];\n _classCallCheck(this, RadioElement);\n _this = _callSuper(this, RadioElement);\n _this.template = template;\n _this.inputName = inputName;\n _this.items = _this.normalizeItems(items);\n _this.domNode = null;\n _this.requiredTemplateKeys = ['items'];\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({});\n return _this;\n }\n _inherits(RadioElement, _BaseElement);\n return _createClass(RadioElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.radio');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n items: this.items,\n inputName: this.inputName\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(RadioElement, \"getData\", this, 3)([])), {}, {\n inputName: this.inputName,\n items: this.items\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this;\n return [new _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radio_options'), this.items.map(function (item) {\n return {\n label: item.label,\n value: item.value\n };\n }), {\n setItems: function setItems(items) {\n _this2.items = _this2.normalizeItems(items);\n _this2.render();\n },\n setName: function setName(name) {\n _this2.inputName = name;\n _this2.render();\n }\n }, this.inputName)];\n }\n }, {\n key: \"normalizeItems\",\n value: function normalizeItems(items) {\n return (Array.isArray(items) ? items : []).map(function (item, index) {\n var _item$label, _item$value;\n return {\n label: (_item$label = item === null || item === void 0 ? void 0 : item.label) !== null && _item$label !== void 0 ? _item$label : \"Option \".concat(index + 1),\n value: (_item$value = item === null || item === void 0 ? void 0 : item.value) !== null && _item$value !== void 0 ? _item$value : \"option_\".concat(index + 1)\n };\n });\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.inputName || \"\", data.items || []), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RadioElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RadioElement.js?");
/***/ }),
/***/ "./src/includes/RadioWidget.js":
/*!*************************************!*\
!*** ./src/includes/RadioWidget.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _RadioElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./RadioElement.js */ \"./src/includes/RadioElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar RadioWidget = /*#__PURE__*/function (_BaseWidget) {\n function RadioWidget() {\n var _this;\n _classCallCheck(this, RadioWidget);\n _this = _callSuper(this, RadioWidget);\n _this.block.appendElements([new _RadioElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Radio', 'contact_method', [{\n label: 'Email',\n value: 'email'\n }, {\n label: 'Phone',\n value: 'phone'\n }, {\n label: 'SMS',\n value: 'sms'\n }])]);\n return _this;\n }\n _inherits(RadioWidget, _BaseWidget);\n return _createClass(RadioWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.radio');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'radio_button_checked';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RadioWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RadioWidget.js?");
/***/ }),
/***/ "./src/includes/RadiosControl.js":
/*!***************************************!*\
!*** ./src/includes/RadiosControl.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar RadiosControl = /*#__PURE__*/function () {\n function RadiosControl(label, value, options, callback) {\n _classCallCheck(this, RadiosControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n // Initialize properties\n this.label = label; // Label for the text control\n this.value = value; // Initial value of the text input\n this.options = options; // Options for the radio buttons\n this.callback = callback; // Callback function to handle input changes\n\n // Create the main container element\n this.domNode = document.createElement(\"div\");\n\n //\n this.render(); // Call the render method to create the UI\n }\n return _createClass(RadiosControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var radioButtons = '';\n\n // Create the radio buttons\n this.options.forEach(function (option, index) {\n var optionId = \"radio_\".concat(_this.id, \"_\").concat(index);\n radioButtons += \"\\n <input type=\\\"radio\\\" class=\\\"btn-check\\\" name=\\\"radioButton_\".concat(_this.id, \"\\\" \\n id=\\\"\").concat(optionId, \"\\\" value=\\\"\").concat(option.value, \"\\\" \\n \").concat(_this.value === option.value ? 'checked' : '', \">\\n <label class=\\\"btn btn-outline-primary py-2 builder-radio-btn builder-radio-option fw-bold\\\" for=\\\"\").concat(optionId, \"\\\">\").concat(option.label, \"</label>\\n \");\n });\n this.domNode.innerHTML = \"\\n <div class=\\\"py-2 px-3 builder-radio-container\\\">\\n <label class=\\\"form-label fw-semibold d-block mb-2 builder-radio-label\\\">\".concat(this.label, \"</label>\\n <div class=\\\"btn-group builder-radio-group\\\" role=\\\"group\\\" aria-label=\\\"\").concat(this.label, \"\\\">\\n \").concat(radioButtons, \"\\n </div>\\n </div>\\n \");\n\n // Add event listeners to all radio buttons\n var radioInputs = this.domNode.querySelectorAll(\"input[name=\\\"radioButton_\".concat(this.id, \"\\\"]\"));\n radioInputs.forEach(function (radio) {\n radio.addEventListener('change', function (e) {\n _this.value = e.target.value;\n\n // Call the callback with the new value if a callback was provided\n if (typeof _this.callback === 'function') {\n _this.callback(_this.value);\n }\n });\n });\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n // Method to set value programmatically\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.value = newValue;\n var radio = this.domNode.querySelector(\"input[value=\\\"\".concat(newValue, \"\\\"]\"));\n if (radio) {\n radio.checked = true;\n\n // Trigger the callback\n if (typeof this.callback === 'function') {\n this.callback(this.value);\n }\n }\n }\n\n // Method to get current value\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RadiosControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RadiosControl.js?");
/***/ }),
/***/ "./src/includes/RangeControl.js":
/*!**************************************!*\
!*** ./src/includes/RangeControl.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * RangeControl — slider + editable numeric value, with optional quick-preset\n * chips below. Emits `.bjs-slider` (see builder.css §8 + ui-showcase #8).\n *\n * 2026-04-18 audit (§2.12): migrated from Bootstrap `.form-range` + bare\n * value label to `.bjs-slider` primitive (range track with `--pct` progress\n * fill + editable number input + unit span). Adds optional preset chips —\n * GridElement uses [0, 8, 16, 24] for the cell-gap common-case, PageElement\n * keeps its existing flow (no presets) and just benefits from the new look.\n *\n * Failure-state audit: number input is clamped to [min, max] on blur; typed\n * values outside the range flash `.bjs-text-input.is-error` briefly (300ms)\n * via the `is-error` class then auto-correct. Invalid input (non-numeric)\n * resets to last-valid value.\n */\nvar RangeControl = /*#__PURE__*/function () {\n /**\n * @param {string} label\n * @param {number} currentValue\n * @param {number} min\n * @param {number} max\n * @param {string} unit\n * @param {number} step\n * @param {function} callback Receives the numeric value on change (debounced 100ms on slider, immediate on preset/number blur).\n * @param {object} [options]\n * @param {number[]} [options.presets] Quick-apply values shown as chips below the slider.\n * @param {string} [options.description] Sub-label text (muted, below title).\n */\n function RangeControl(label, currentValue, min, max, unit, step, callback) {\n var options = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : {};\n _classCallCheck(this, RangeControl);\n this.id = '_rng_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.min = min;\n this.max = max;\n this.unit = unit || '';\n this.step = step || 1;\n this.callback = callback || function () {};\n this.presets = Array.isArray(options.presets) ? options.presets.slice() : [];\n this.description = options.description || '';\n this.value = this._clamp(parseFloat(currentValue));\n if (isNaN(this.value)) this.value = this.min;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('range-control');\n this.render();\n this._bindEvents();\n }\n return _createClass(RangeControl, [{\n key: \"_clamp\",\n value: function _clamp(v) {\n if (isNaN(v)) return NaN;\n if (v < this.min) return this.min;\n if (v > this.max) return this.max;\n return v;\n }\n }, {\n key: \"_pct\",\n value: function _pct() {\n if (this.max === this.min) return 0;\n return (this.value - this.min) / (this.max - this.min) * 100;\n }\n }, {\n key: \"_t\",\n value: function _t(key, fallback) {\n try {\n var v = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key);\n return v && v !== key ? v : fallback;\n } catch (_e) {\n return fallback;\n }\n }\n\n /** Programmatic setter — used by sibling controls (e.g. preset chip) to\n * force a value without emitting the callback twice. */\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n var emit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n var clamped = this._clamp(parseFloat(newValue));\n if (isNaN(clamped)) return;\n this.value = clamped;\n this._syncDOM();\n if (emit) this.callback(this.value);\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }, {\n key: \"_syncDOM\",\n value: function _syncDOM() {\n var range = this.domNode.querySelector('.bjs-slider-track');\n var numInput = this.domNode.querySelector('.bjs-number-value');\n if (range) {\n range.value = this.value;\n range.style.setProperty('--pct', this._pct() + '%');\n }\n if (numInput) numInput.value = this.value;\n this._syncPresetActive();\n }\n }, {\n key: \"_syncPresetActive\",\n value: function _syncPresetActive() {\n var _this = this;\n this.domNode.querySelectorAll('[data-preset]').forEach(function (btn) {\n var pv = parseFloat(btn.getAttribute('data-preset'));\n btn.classList.toggle('is-active', !isNaN(pv) && Math.abs(pv - _this.value) < 0.01);\n });\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this2 = this;\n var pct = this._pct();\n var desc = this.description ? \"<span class=\\\"bjs-control-description\\\">\".concat(this.description, \"</span>\") : '';\n var presetChips = this.presets.length ? \"<div class=\\\"range-control-presets\\\">\" + this.presets.map(function (p) {\n var active = Math.abs(p - _this2.value) < 0.01 ? ' is-active' : '';\n // Unit is already shown on the slider's number input — keep chip\n // labels to bare values so the row doesn't read \"0px 8px 16px\".\n return \"<button type=\\\"button\\\" class=\\\"range-control-preset\".concat(active, \"\\\" data-preset=\\\"\").concat(p, \"\\\">\").concat(p, \"</button>\");\n }).join('') + \"</div>\" : '';\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-stack\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <span>\".concat(this.label, \"</span>\\n \").concat(desc, \"\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-slider\\\">\\n <input type=\\\"range\\\" class=\\\"bjs-slider-track\\\" id=\\\"\").concat(this.id, \"_slider\\\"\\n min=\\\"\").concat(this.min, \"\\\" max=\\\"\").concat(this.max, \"\\\" step=\\\"\").concat(this.step, \"\\\" value=\\\"\").concat(this.value, \"\\\"\\n style=\\\"--pct: \").concat(pct, \"%\\\">\\n <div class=\\\"bjs-slider-value\\\">\\n <input type=\\\"number\\\" class=\\\"bjs-number-value\\\"\\n min=\\\"\").concat(this.min, \"\\\" max=\\\"\").concat(this.max, \"\\\" step=\\\"\").concat(this.step, \"\\\" value=\\\"\").concat(this.value, \"\\\"\\n aria-label=\\\"\").concat(this.label, \"\\\">\\n \").concat(this.unit ? \"<span class=\\\"bjs-number-unit\\\">\".concat(this.unit, \"</span>\") : '', \"\\n </div>\\n </div>\\n \").concat(presetChips, \"\\n </div>\\n </div>\\n \");\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this3 = this;\n var range = this.domNode.querySelector('.bjs-slider-track');\n var numInput = this.domNode.querySelector('.bjs-number-value');\n var debounceTimeout = null;\n var DEBOUNCE_MS = 100;\n if (range) {\n range.addEventListener('input', function (e) {\n _this3.value = parseFloat(e.target.value);\n range.style.setProperty('--pct', _this3._pct() + '%');\n if (numInput) numInput.value = _this3.value;\n _this3._syncPresetActive();\n if (debounceTimeout) clearTimeout(debounceTimeout);\n debounceTimeout = setTimeout(function () {\n return _this3.callback(_this3.value);\n }, DEBOUNCE_MS);\n });\n }\n if (numInput) {\n numInput.addEventListener('input', function (e) {\n var raw = parseFloat(e.target.value);\n if (isNaN(raw)) return; // wait until user stops typing\n var clamped = _this3._clamp(raw);\n _this3.value = clamped;\n if (range) {\n range.value = clamped;\n range.style.setProperty('--pct', _this3._pct() + '%');\n }\n _this3._syncPresetActive();\n if (debounceTimeout) clearTimeout(debounceTimeout);\n debounceTimeout = setTimeout(function () {\n return _this3.callback(_this3.value);\n }, DEBOUNCE_MS);\n });\n numInput.addEventListener('blur', function (e) {\n var raw = parseFloat(e.target.value);\n if (isNaN(raw)) {\n // Invalid typed content — restore last valid value\n numInput.value = _this3.value;\n return;\n }\n var clamped = _this3._clamp(raw);\n if (clamped !== raw) {\n // Out-of-range typed input — flash error + auto-correct\n numInput.classList.add('is-error');\n setTimeout(function () {\n return numInput.classList.remove('is-error');\n }, 300);\n }\n _this3.value = clamped;\n numInput.value = clamped;\n _this3._syncDOM();\n _this3.callback(_this3.value);\n });\n }\n this.domNode.querySelectorAll('[data-preset]').forEach(function (btn) {\n btn.addEventListener('click', function () {\n var pv = parseFloat(btn.getAttribute('data-preset'));\n if (!isNaN(pv)) _this3.setValue(pv);\n });\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RangeControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RangeControl.js?");
/***/ }),
/***/ "./src/includes/RichTextControl.js":
/*!*****************************************!*\
!*** ./src/includes/RichTextControl.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar RichTextControl = /*#__PURE__*/function () {\n function RichTextControl(label, value, callback) {\n var formats = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n var sourceElement = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;\n _classCallCheck(this, RichTextControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = value;\n this.callback = callback;\n this.sourceElement = sourceElement;\n this.domNode = document.createElement(\"div\");\n this.isEditing = false;\n this.formats = {};\n for (var _i = 0, _Object$entries = Object.entries(formats); _i < _Object$entries.length; _i++) {\n var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),\n key = _Object$entries$_i[0],\n _value = _Object$entries$_i[1];\n if (_value !== null && _value !== undefined && _value !== \"\") {\n this.formats[key] = _value;\n }\n }\n if (this.sourceElement) this.extractStylesFromElement();\n this.render();\n }\n return _createClass(RichTextControl, [{\n key: \"extractStylesFromElement\",\n value: function extractStylesFromElement() {\n var _textElement;\n if (!this.sourceElement) return;\n var textElement = this.sourceElement.querySelector('[inline-edit=\"text\"]');\n if (!textElement) {\n var textTags = [\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"p\", \"span\", \"div\", \"td\", \"a\"];\n for (var _i2 = 0, _textTags = textTags; _i2 < _textTags.length; _i2++) {\n var tag = _textTags[_i2];\n textElement = this.sourceElement.querySelector(tag);\n if (textElement && textElement.textContent.trim()) break;\n }\n }\n if (!textElement) textElement = this.sourceElement;\n var cs = window.getComputedStyle(textElement);\n this.formats.font_family = cs.getPropertyValue(\"font-family\");\n this.formats.font_size = cs.getPropertyValue(\"font-size\");\n this.formats.font_weight = cs.getPropertyValue(\"font-weight\");\n this.formats.font_style = cs.getPropertyValue(\"font-style\");\n this.formats.font_variant = cs.getPropertyValue(\"font-variant\");\n this.formats.line_height = cs.getPropertyValue(\"line-height\");\n this.formats.color = cs.getPropertyValue(\"color\");\n this.formats.text_align = cs.getPropertyValue(\"text-align\");\n this.formats.text_decoration = cs.getPropertyValue(\"text-decoration\");\n this.formats.text_transform = cs.getPropertyValue(\"text-transform\");\n this.formats.letter_spacing = cs.getPropertyValue(\"letter-spacing\");\n this.formats.word_spacing = cs.getPropertyValue(\"word-spacing\");\n this.sourceTag = (_textElement = textElement) !== null && _textElement !== void 0 && _textElement.tagName ? textElement.tagName.toLowerCase() : null;\n for (var i = 0; i < cs.length; i++) {\n var prop = cs[i];\n var val = cs.getPropertyValue(prop);\n if (!val) continue;\n var key = prop.replace(/-/g, \"_\");\n if (this.formats[key] !== undefined) continue;\n this.formats[key] = val;\n }\n }\n }, {\n key: \"stripTags\",\n value: function stripTags(html) {\n var pre = (html || \"\").replace(/<br\\s*\\/?>/gi, \" \\n\").replace(/<\\/(p|div|h[1-6]|li|blockquote|section)>/gi, \" \\n\");\n var div = document.createElement(\"div\");\n div.innerHTML = pre;\n var raw = (div.textContent || div.innerText || \"\").replace(/\\u00A0/g, \" \");\n return raw.replace(/\\s+/g, \" \").trim();\n }\n }, {\n key: \"toPreview\",\n value: function toPreview(text) {\n var max = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 28;\n var t = (text || \"\").trim();\n if (t.length <= max) return t;\n var s = t.slice(0, max);\n var cut = s.lastIndexOf(\" \");\n if (cut > 8) s = s.slice(0, cut);\n return s + \"…\";\n }\n }, {\n key: \"_getWrappedContent\",\n value: function _getWrappedContent(tag, style) {\n var _this$value;\n var safeTag = tag || \"div\";\n var content = (_this$value = this.value) !== null && _this$value !== void 0 ? _this$value : \"\";\n var styleAttr = style ? \" style=\\\"\".concat(style, \"\\\"\") : \"\";\n return \"<\".concat(safeTag).concat(styleAttr, \" contenteditable=\\\"true\\\">\").concat(content, \"</\").concat(safeTag, \">\");\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this = this;\n var plain = this.stripTags(this.value || \"\");\n var preview = this.toPreview(plain, 500);\n\n // 2026-04-17 dark-mode pass: swapped hardcoded `#f8f9fa / #111 / #ced4da`\n // for `.bjs-*` tokens so the preview + edit button track the theme.\n // The `all: initial` reset only wipes standard property VALUES; custom\n // properties (CSS variables) still resolve inside it, so var(--bjs-*)\n // keeps working under the reset. Edit button migrated to\n // `.bjs-icon-btn` (same 28/32 px surface used elsewhere).\n this.domNode.innerHTML = \"\\n <div class=\\\"py-2 px-3 position-relative\\\">\\n <label class=\\\"form-label fw-semibold\\\">\".concat(this.label, \"</label>\\n <div class=\\\"richtext-row\\\">\\n <div class=\\\"richtext-content\\\" style=\\\"width:100% !important; max-width:100% !important;\\\">\\n <div class=\\\"js-text-preview\\\" style=\\\"\\n all: initial !important;\\n box-sizing: border-box !important;\\n display: -webkit-box !important;\\n width: 100% !important;\\n max-width: 100% !important;\\n\\n padding: 5px!important;\\n padding-left: 4px !important;\\n\\n font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif !important;\\n font-size: 13px !important;\\n line-height: 1.4 !important;\\n color: var(--bjs-text) !important;\\n\\n overflow: hidden !important;\\n text-overflow: ellipsis !important;\\n\\n -webkit-line-clamp: 3 !important;\\n -webkit-box-orient: vertical !important;\\n\\n white-space: normal !important; /* IMPORTANT */\\n\\n vertical-align: middle !important;\\n border: solid 1px var(--bjs-input-border) !important;\\n border-radius: 4px !important;\\n background-color: var(--bjs-input-bg) !important;\\n\\n \\\" title=\\\"\").concat(plain.replace(/\"/g, '"'), \"\\\">\\n \").concat(preview, \"\\n </div>\\n </div>\\n <div class=\\\"richtext-action\\\">\\n <a class=\\\"bjs-icon-btn d-inline-flex justify-content-center align-items-center\\\" data-control=\\\"edit\\\" aria-label=\\\"Edit\\\" role=\\\"button\\\" tabindex=\\\"0\\\"><span class=\\\"material-symbols-rounded\\\">edit</span></a>\\n </div>\\n </div>\\n </div>\\n \");\n this.domNode.querySelector('[data-control=\"edit\"]').addEventListener(\"click\", function () {\n _this.isEditing = true;\n _this.renderEditor();\n });\n }\n }, {\n key: \"renderEditor\",\n value: function renderEditor() {\n var _this$value2,\n _this2 = this;\n this.domNode.innerHTML = \"\\n <div class=\\\"py-2 px-3 position-relative\\\">\\n <label class=\\\"form-label fw-semibold\\\">\".concat(this.label, \"</label>\\n <div class=\\\"richtext-editor-shell\\\">\\n <div\\n id=\\\"\").concat(this.id, \"\\\"\\n class=\\\"richtext-editor-body\\\"\\n contenteditable=\\\"true\\\"\\n >\").concat((_this$value2 = this.value) !== null && _this$value2 !== void 0 ? _this$value2 : \"\", \"</div>\\n <div class=\\\"richtext-editor-toolbar\\\">\\n <div class=\\\"richtext-toolbar-row\\\">\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"bold\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.bold'), \"\\\"><strong>B</strong></button>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"italic\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.italic'), \"\\\"><em>I</em></button>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"underline\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.underline'), \"\\\"><u>U</u></button>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"strikeThrough\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.strikethrough'), \"\\\"><s>S</s></button>\\n <span class=\\\"richtext-tool-sep\\\"></span>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"superscript\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.superscript'), \"\\\"><span style=\\\"font-size:11px\\\">X<sup>2</sup></span></button>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"subscript\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.subscript'), \"\\\"><span style=\\\"font-size:11px\\\">X<sub>2</sub></span></button>\\n <span class=\\\"richtext-tool-sep\\\"></span>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn richtext-tool-color\\\" data-command=\\\"foreColor\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.text_color'), \"\\\"><span style=\\\"font-size:14px;font-weight:700\\\">A</span><input type=\\\"color\\\" class=\\\"richtext-color-picker\\\" data-for=\\\"foreColor\\\" value=\\\"#000000\\\"></button>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn richtext-tool-color\\\" data-command=\\\"hiliteColor\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.highlight'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">ink_highlighter</span><input type=\\\"color\\\" class=\\\"richtext-color-picker\\\" data-for=\\\"hiliteColor\\\" value=\\\"#ffff00\\\"></button>\\n </div>\\n <div class=\\\"richtext-toolbar-row\\\">\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"createLink\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.link'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">link</span></button>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"unlink\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.unlink'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">link_off</span></button>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"insertHorizontalRule\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.horizontal_rule'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">horizontal_rule</span></button>\\n <span class=\\\"richtext-tool-sep\\\"></span>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"undo\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.undo'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">undo</span></button>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"redo\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.redo'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">redo</span></button>\\n <span class=\\\"richtext-tool-sep\\\"></span>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"selectAll\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.select_all'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">checklist</span></button>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"unselect\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.unselect'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">deselect</span></button>\\n <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"removeFormat\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.clear_formatting'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">format_clear</span></button>\\n </div>\\n </div>\\n <div class=\\\"richtext-link-popover\\\" style=\\\"display:none;\\\">\\n <input type=\\\"text\\\" class=\\\"richtext-link-input\\\" placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.link_url_placeholder'), \"\\\">\\n <select class=\\\"richtext-link-target\\\">\\n <option value=\\\"\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link.target_self'), \"</option>\\n <option value=\\\"_blank\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link.target_blank'), \"</option>\\n </select>\\n <button type=\\\"button\\\" class=\\\"richtext-link-apply\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.link_apply'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">check</span></button>\\n <button type=\\\"button\\\" class=\\\"richtext-link-remove\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.link_remove'), \"\\\" style=\\\"display:none;\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">link_off</span></button>\\n </div>\\n </div>\\n <div class=\\\"d-flex align-items-center mt-2\\\" style=\\\"gap:4px;\\\">\\n <button class=\\\"btn btn-primary btn-sm ms-auto\\\" data-control=\\\"done\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dialog.save'), \"</button>\\n </div>\\n </div>\\n \");\n var editor = document.getElementById(this.id);\n\n // Place cursor at end of content\n try {\n var range = document.createRange();\n range.selectNodeContents(editor);\n range.collapse(false);\n var sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n } catch (_unused) {}\n editor.focus();\n var simpleCommands = [\"bold\", \"italic\", \"underline\", \"strikeThrough\", \"superscript\", \"subscript\", \"removeFormat\", \"unlink\", \"insertHorizontalRule\", \"undo\", \"redo\", \"selectAll\"];\n this.domNode.querySelectorAll(\"[data-command]\").forEach(function (control) {\n var cmd = control.getAttribute(\"data-command\");\n if (control.tagName !== \"BUTTON\") return;\n control.addEventListener(\"mousedown\", function (ev) {\n return ev.preventDefault();\n });\n if (simpleCommands.includes(cmd)) {\n control.addEventListener(\"click\", function (e) {\n e.preventDefault();\n document.execCommand(cmd, false, null);\n editor.focus();\n });\n }\n });\n\n // Color picker buttons (foreColor, hiliteColor)\n this.domNode.querySelectorAll('.richtext-color-picker').forEach(function (picker) {\n var cmd = picker.dataset[\"for\"];\n picker.addEventListener('input', function () {\n _this2._restoreSelection();\n document.execCommand(cmd, false, picker.value);\n _this2._saveSelection();\n _this2.value = editor.innerHTML;\n _this2.callback.setText(_this2.value);\n });\n // Save selection before color picker opens\n picker.closest('.richtext-tool-btn').addEventListener('click', function (e) {\n if (e.target === picker) return;\n e.preventDefault();\n _this2._saveSelection();\n picker.click();\n });\n });\n\n // Unselect button handler (collapse selection to cursor)\n var unselectBtn = this.domNode.querySelector('[data-command=\"unselect\"]');\n if (unselectBtn) {\n unselectBtn.addEventListener(\"mousedown\", function (ev) {\n return ev.preventDefault();\n });\n unselectBtn.addEventListener(\"click\", function (e) {\n e.preventDefault();\n var sel = window.getSelection();\n if (sel.rangeCount > 0) sel.collapseToEnd();\n editor.focus();\n });\n }\n\n // Link button handler\n var linkBtn = this.domNode.querySelector('[data-command=\"createLink\"]');\n if (linkBtn) {\n linkBtn.addEventListener(\"mousedown\", function (ev) {\n return ev.preventDefault();\n });\n linkBtn.addEventListener(\"click\", function (e) {\n e.preventDefault();\n _this2._handleLinkButton(editor);\n });\n }\n\n // Keyboard shortcut: Ctrl+K / Cmd+K for link\n // Keyboard shortcuts — stop propagation to prevent builder-level undo/redo\n editor.addEventListener(\"keydown\", function (e) {\n if (e.key === 'k' && (e.ctrlKey || e.metaKey)) {\n e.preventDefault();\n e.stopPropagation();\n _this2._handleLinkButton(editor);\n }\n // Ctrl+Z / Cmd+Z (undo) and Ctrl+Shift+Z / Cmd+Shift+Z (redo)\n // Must stay scoped to the editor, not bubble to builder\n if (e.key === 'z' && (e.ctrlKey || e.metaKey)) {\n e.stopPropagation();\n }\n if (e.key === 'y' && (e.ctrlKey || e.metaKey)) {\n e.stopPropagation();\n }\n });\n editor.addEventListener(\"input\", function () {\n _this2.value = editor.innerHTML;\n _this2.callback.setText(_this2.value);\n });\n this.domNode.querySelector('[data-control=\"done\"]').addEventListener(\"click\", function () {\n _this2.value = editor.innerHTML.trim();\n _this2.isEditing = false;\n _this2.callback.setText(_this2.value);\n _this2.render();\n });\n\n // Link popover event listeners\n var popover = this.domNode.querySelector('.richtext-link-popover');\n if (popover) {\n popover.querySelector('.richtext-link-apply').addEventListener('click', function () {\n _this2._applyLink(editor);\n });\n popover.querySelector('.richtext-link-remove').addEventListener('click', function () {\n _this2._removeLink(editor);\n });\n // Stop all keyboard shortcuts from bubbling to builder when in link input\n popover.addEventListener('keydown', function (e) {\n e.stopPropagation();\n });\n popover.querySelector('.richtext-link-input').addEventListener('keydown', function (e) {\n if (e.key === 'Enter') {\n e.preventDefault();\n _this2._applyLink(editor);\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n popover.style.display = 'none';\n _this2._unmarkSelection();\n _this2._restoreSelection();\n editor.focus();\n }\n });\n }\n editor.focus();\n }\n }, {\n key: \"_markSelection\",\n value: function _markSelection() {\n this._unmarkSelection();\n var sel = window.getSelection();\n if (!sel.rangeCount || sel.isCollapsed) return;\n var range = sel.getRangeAt(0);\n var rects = range.getClientRects();\n var editor = document.getElementById(this.id);\n if (!editor || !rects.length) return;\n var editorRect = editor.getBoundingClientRect();\n\n // Position-based overlay — does NOT modify DOM text, so range stays valid\n var _iterator = _createForOfIteratorHelper(rects),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var rect = _step.value;\n var overlay = document.createElement('div');\n overlay.className = 'richtext-selection-overlay';\n Object.assign(overlay.style, {\n position: 'absolute',\n top: \"\".concat(rect.top - editorRect.top, \"px\"),\n left: \"\".concat(rect.left - editorRect.left, \"px\"),\n width: \"\".concat(rect.width, \"px\"),\n height: \"\".concat(rect.height, \"px\")\n });\n editor.appendChild(overlay);\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n }\n }, {\n key: \"_unmarkSelection\",\n value: function _unmarkSelection() {\n var editor = document.getElementById(this.id);\n if (!editor) return;\n editor.querySelectorAll('.richtext-selection-overlay').forEach(function (el) {\n return el.remove();\n });\n }\n }, {\n key: \"_saveSelection\",\n value: function _saveSelection() {\n var sel = window.getSelection();\n if (sel.rangeCount > 0) {\n this._savedRange = sel.getRangeAt(0).cloneRange();\n }\n }\n }, {\n key: \"_restoreSelection\",\n value: function _restoreSelection() {\n if (!this._savedRange) return;\n var sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange);\n }\n }, {\n key: \"_findParentLink\",\n value: function _findParentLink(node) {\n while (node && node !== this.domNode) {\n if (node.tagName === 'A') return node;\n node = node.parentElement;\n }\n return null;\n }\n }, {\n key: \"_handleLinkButton\",\n value: function _handleLinkButton(editor) {\n var sel = window.getSelection();\n var popover = this.domNode.querySelector('.richtext-link-popover');\n var input = popover.querySelector('.richtext-link-input');\n var targetSelect = popover.querySelector('.richtext-link-target');\n var removeBtn = popover.querySelector('.richtext-link-remove');\n\n // Check if cursor is inside an existing link\n var existingLink = null;\n if (sel.anchorNode) {\n existingLink = this._findParentLink(sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentElement : sel.anchorNode);\n }\n if (existingLink) {\n // Select the entire link text for easy editing\n var range = document.createRange();\n range.selectNodeContents(existingLink);\n sel.removeAllRanges();\n sel.addRange(range);\n input.value = existingLink.getAttribute('href') || '';\n targetSelect.value = existingLink.getAttribute('target') || '';\n removeBtn.style.display = 'inline-flex';\n } else if (sel.isCollapsed) {\n // No text selected and not inside a link - nothing to wrap\n var linkBtn = this.domNode.querySelector('[data-command=\"createLink\"]');\n if (linkBtn) {\n linkBtn.classList.add('richtext-tool-btn-shake');\n setTimeout(function () {\n return linkBtn.classList.remove('richtext-tool-btn-shake');\n }, 400);\n }\n return;\n } else {\n input.value = '';\n targetSelect.value = '';\n removeBtn.style.display = 'none';\n }\n this._saveSelection();\n this._markSelection();\n popover.style.display = 'flex';\n input.focus();\n }\n }, {\n key: \"_applyLink\",\n value: function _applyLink(editor) {\n var popover = this.domNode.querySelector('.richtext-link-popover');\n var input = popover.querySelector('.richtext-link-input');\n var targetSelect = popover.querySelector('.richtext-link-target');\n var url = input.value.trim();\n var target = targetSelect.value;\n this._unmarkSelection();\n this._restoreSelection();\n if (url) {\n // Auto-prepend https:// if no protocol\n if (!/^https?:\\/\\//i.test(url) && !/^mailto:/i.test(url) && !/^tel:/i.test(url)) {\n url = 'https://' + url;\n }\n document.execCommand('createLink', false, url);\n\n // Set target attribute on the created link(s)\n // execCommand doesn't support target, so we set it manually\n var sel = window.getSelection();\n if (sel.anchorNode) {\n var link = this._findParentLink(sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentElement : sel.anchorNode);\n if (link) {\n if (target) {\n link.setAttribute('target', target);\n } else {\n link.removeAttribute('target');\n }\n }\n }\n } else {\n document.execCommand('unlink');\n }\n popover.style.display = 'none';\n this.value = editor.innerHTML;\n this.callback.setText(this.value);\n editor.focus();\n }\n }, {\n key: \"_removeLink\",\n value: function _removeLink(editor) {\n var popover = this.domNode.querySelector('.richtext-link-popover');\n this._unmarkSelection();\n this._restoreSelection();\n document.execCommand('unlink');\n popover.style.display = 'none';\n this.value = editor.innerHTML;\n this.callback.setText(this.value);\n editor.focus();\n }\n }, {\n key: \"getPreviewStyle\",\n value: function getPreviewStyle() {\n var keys = [\"font_family\", \"font_size\", \"font_weight\", \"font_style\", \"font_variant\", \"color\", \"line_height\", \"text_align\", \"text_decoration\", \"text_transform\", \"letter_spacing\", \"word_spacing\", \"text_indent\", \"text_shadow\", \"background_color\", \"background_image\", \"background_position\", \"background_size\", \"background_repeat\", \"padding\", \"padding_top\", \"padding_right\", \"padding_bottom\", \"padding_left\", \"margin\", \"margin_top\", \"margin_right\", \"margin_bottom\", \"margin_left\", \"border\", \"border_top\", \"border_right\", \"border_bottom\", \"border_left\", \"border_radius\", \"border_top_left_radius\", \"border_top_right_radius\", \"border_bottom_left_radius\", \"border_bottom_right_radius\", \"width\", \"height\", \"max_width\", \"min_width\", \"display\", \"vertical_align\", \"white_space\", \"word_wrap\", \"word_break\", \"overflow_wrap\"];\n var styles = [];\n for (var _i3 = 0, _keys = keys; _i3 < _keys.length; _i3++) {\n var k = _keys[_i3];\n if (this.formats[k]) {\n var p = k.replace(/_/g, \"-\");\n styles.push(\"\".concat(p, \": \").concat(this.formats[k], \" !important\"));\n }\n }\n return styles.join(\"; \");\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RichTextControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RichTextControl.js?");
/***/ }),
/***/ "./src/includes/SAlert.js":
/*!********************************!*\
!*** ./src/includes/SAlert.js ***!
\********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n\n\n/**\n * SAlert — styled modal dialog for builder notifications.\n *\n * Usage:\n * SAlert.show('Saved!'); // info (default)\n * SAlert.show('Missing {ITEMS}', 'error'); // error\n * SAlert.show('Upload complete', 'success'); // success\n */\nvar SAlert = {\n show: function show(message) {\n var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'info';\n var wrapper = document.getElementById('alertsWrapper');\n if (!wrapper) {\n wrapper = document.createElement('div');\n wrapper.id = 'alertsWrapper';\n document.body.appendChild(wrapper);\n }\n\n // Remove any existing modal\n var existing = document.getElementById('SAlertModal');\n if (existing) existing.remove();\n\n // Icon + color per type\n var config = {\n error: {\n icon: 'error',\n color: '#EF4444',\n bg: '#FEF2F2',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dialog.error') || 'Error'\n },\n success: {\n icon: 'check_circle',\n color: '#10B981',\n bg: '#F0FDF4',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dialog.success') || 'Success'\n },\n info: {\n icon: 'info',\n color: '#3B82F6',\n bg: '#EFF6FF',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dialog.info') || 'Info'\n }\n };\n var _ref = config[type] || config.info,\n icon = _ref.icon,\n color = _ref.color,\n bg = _ref.bg,\n label = _ref.label;\n wrapper.innerHTML = \"\\n <div class=\\\"modal fade\\\" id=\\\"SAlertModal\\\" tabindex=\\\"-1\\\" aria-labelledby=\\\"SAlertLabel\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"modal-dialog modal-dialog-centered\\\" style=\\\"max-width:420px;\\\">\\n <div class=\\\"modal-content\\\" style=\\\"border:none;border-radius:12px;overflow:hidden;box-shadow:0 8px 32px rgba(0,0,0,0.18);\\\">\\n <div class=\\\"modal-header\\\" style=\\\"background:\".concat(bg, \";border-bottom:none;padding:20px 24px 12px;\\\">\\n <div style=\\\"display:flex;align-items:center;gap:10px;\\\">\\n <span class=\\\"material-symbols-rounded\\\" style=\\\"color:\").concat(color, \";font-size:24px;flex-shrink:0;\\\">\").concat(icon, \"</span>\\n <span style=\\\"font-weight:600;font-size:15px;color:#1E293B;\\\" id=\\\"SAlertLabel\\\">\").concat(label, \"</span>\\n </div>\\n <button type=\\\"button\\\" class=\\\"btn-close\\\" data-bs-dismiss=\\\"modal\\\" aria-label=\\\"Close\\\" style=\\\"margin:0;opacity:0.5;\\\"></button>\\n </div>\\n <div class=\\\"modal-body\\\" id=\\\"SAlertModalBody\\\" style=\\\"padding:16px 24px 8px;font-size:14px;color:#475569;line-height:1.6;\\\">\\n </div>\\n <div class=\\\"modal-footer\\\" style=\\\"border-top:none;padding:8px 24px 20px;justify-content:flex-end;\\\">\\n <button type=\\\"button\\\"\\n class=\\\"btn btn-primary btn-sm\\\"\\n data-bs-dismiss=\\\"modal\\\"\\n style=\\\"min-width:72px;\\\">\\n \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dialog.ok') || 'OK', \"\\n </button>\\n </div>\\n </div>\\n </div>\\n </div>\\n \");\n document.getElementById('SAlertModalBody').innerHTML = message;\n var modal = new bootstrap.Modal(document.getElementById('SAlertModal'));\n modal.show();\n }\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SAlert);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SAlert.js?");
/***/ }),
/***/ "./src/includes/SectionGroupControl.js":
/*!*********************************************!*\
!*** ./src/includes/SectionGroupControl.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * SectionGroupControl — collapsible group wrapper styled like the BORDERS section.\n *\n * Usage:\n * new SectionGroupControl({\n * title: 'IMAGE SIZE',\n * description: 'Adjust width, height and bounds.',\n * children: [ ctrl1, ctrl2, ... ],\n * collapsed: false, // optional, default false\n * })\n *\n * Children are other Control instances (anything with a `domNode`). They are\n * appended into the group's body on render. Clicking the header toggles the\n * collapsed state. The control is dark-mode safe — all styling lives in\n * `.bjs-group-*` classes in builder.css, resolving through `--bjs-*` tokens.\n */\nvar SectionGroupControl = /*#__PURE__*/function () {\n function SectionGroupControl() {\n var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},\n _ref$title = _ref.title,\n title = _ref$title === void 0 ? '' : _ref$title,\n _ref$description = _ref.description,\n description = _ref$description === void 0 ? '' : _ref$description,\n _ref$children = _ref.children,\n children = _ref$children === void 0 ? [] : _ref$children,\n _ref$collapsed = _ref.collapsed,\n collapsed = _ref$collapsed === void 0 ? false : _ref$collapsed;\n _classCallCheck(this, SectionGroupControl);\n this.id = '_bjsg_' + Math.random().toString(36).substr(2, 9);\n this.title = title;\n this.description = description;\n this.children = Array.isArray(children) ? children : [];\n this.collapsed = !!collapsed;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-group');\n if (this.collapsed) this.domNode.classList.add('is-collapsed');\n this.render();\n this._bindEvents();\n }\n return _createClass(SectionGroupControl, [{\n key: \"render\",\n value: function render() {\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-group-header\\\" role=\\\"button\\\" tabindex=\\\"0\\\" aria-expanded=\\\"\".concat(!this.collapsed, \"\\\">\\n <div>\\n <span class=\\\"bjs-group-header-title\\\">\").concat(this.title, \"</span>\\n \").concat(this.description ? \"<span class=\\\"bjs-group-header-desc\\\">\".concat(this.description, \"</span>\") : '', \"\\n </div>\\n <span class=\\\"material-symbols-rounded bjs-group-header-caret\\\" aria-hidden=\\\"true\\\">keyboard_arrow_down</span>\\n </div>\\n <div class=\\\"bjs-group-body\\\"></div>\\n \");\n var body = this.domNode.querySelector('.bjs-group-body');\n this.children.forEach(function (child) {\n if (child && child.domNode) body.appendChild(child.domNode);\n });\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this = this;\n var header = this.domNode.querySelector('.bjs-group-header');\n if (!header) return;\n var toggle = function toggle() {\n _this.collapsed = !_this.collapsed;\n _this.domNode.classList.toggle('is-collapsed', _this.collapsed);\n header.setAttribute('aria-expanded', String(!_this.collapsed));\n };\n header.addEventListener('click', toggle);\n header.addEventListener('keydown', function (e) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggle();\n }\n });\n }\n\n /** Composite destroy — Builder.renderElementControls only sees the\n * outer control list (it doesn't recurse into a section's children).\n * Without this, child controls (DimensionControl, etc.) that own\n * subscribe disposers would leak listeners every time the sidebar\n * rebuilds. Idempotent: safe to call multiple times. */\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this._destroyed) return;\n this._destroyed = true;\n var _iterator = _createForOfIteratorHelper(this.children || []),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var child = _step.value;\n if (child && typeof child.destroy === 'function') {\n try {\n child.destroy();\n } catch (err) {\n /* eslint-disable-next-line no-console */console.error('[bjs:SectionGroup] child destroy threw:', err);\n }\n }\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SectionGroupControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SectionGroupControl.js?");
/***/ }),
/***/ "./src/includes/SectionLabelControl.js":
/*!*********************************************!*\
!*** ./src/includes/SectionLabelControl.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * SectionLabelControl — a non-interactive section header dropped between\n * control rows (e.g. the \"PAGE SETTINGS\" divider above Page-level block\n * padding in the Block panel).\n *\n * 2026-04-17 audit (§2.12): migrated from `.shadow-sm .text-white\n * .section-label` (Bootstrap, white-on-dark, deprecated) to\n * `.bjs-section-header` — the panel's canonical divider primitive\n * (token-driven, uppercase title, subtle bottom border, dark-mode-safe).\n *\n * Constructor accepts an optional description shown below the title for\n * sections that need one-liner guidance (\"these settings apply to the\n * page, not this block\"). Omit for a bare title.\n */\nvar SectionLabelControl = /*#__PURE__*/function () {\n function SectionLabelControl(label) {\n var description = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';\n _classCallCheck(this, SectionLabelControl);\n this.label = label;\n this.description = description;\n this.domNode = document.createElement('div');\n this.render();\n }\n return _createClass(SectionLabelControl, [{\n key: \"render\",\n value: function render() {\n var desc = this.description ? \"<span class=\\\"bjs-section-header-desc\\\">\".concat(this.description, \"</span>\") : '';\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-section-header\\\" role=\\\"heading\\\" aria-level=\\\"3\\\">\\n <div>\\n <span class=\\\"bjs-section-header-title\\\">\".concat(this.label, \"</span>\\n \").concat(desc, \"\\n </div>\\n </div>\\n \");\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SectionLabelControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SectionLabelControl.js?");
/***/ }),
/***/ "./src/includes/SegmentedTextControl.js":
/*!**********************************************!*\
!*** ./src/includes/SegmentedTextControl.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/*\n * SegmentedTextControl — sibling of AlignControl that renders text\n * labels (XS · SM · MD · LG · XL) instead of material-symbol icons. Uses\n * the canonical `.bjs-control-row` + `.bjs-segmented` shell (Sync Pass\n * 2026-04-19) so it inherits the wrap-capable + breath-room styling all\n * other segmented controls in the panel use.\n *\n * Constructor signature mirrors AlignControl for muscle-memory parity:\n * new SegmentedTextControl(label, value, callback, options)\n *\n * `options` is an array of either:\n * - 'xs' → label='xs' (auto-uppercased)\n * - { value: 'xs', label: 'XS' } → explicit label\n * - { value: 'pill', label: 'Pill', tooltip: 'Fully rounded' }\n *\n * `callback` accepts either a fn or an object with `setValue(v)` —\n * matches AlignControl's loose contract so consumers can wire either\n * shape.\n *\n * Public API:\n * .setValue(v) — programmatic update + fires callback\n * .getValue() — current value\n *\n * NOT a BaseControl subclass — this control owns no element-state\n * subscription so there's nothing to dispose. Builder.renderElementControls'\n * destroy guard is `typeof ctrl.destroy === 'function'` so the omission is\n * safe.\n */\nvar SegmentedTextControl = /*#__PURE__*/function () {\n function SegmentedTextControl(label, value, callback) {\n var _this = this;\n var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];\n var sync = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;\n _classCallCheck(this, SegmentedTextControl);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = value;\n this.callback = callback;\n this.options = (options || []).map(function (entry) {\n if (entry && _typeof(entry) === 'object') {\n return {\n value: entry.value,\n label: entry.label || String(entry.value).toUpperCase(),\n tooltip: entry.tooltip || null\n };\n }\n return {\n value: entry,\n label: String(entry).toUpperCase(),\n tooltip: null\n };\n });\n this.domNode = document.createElement('div');\n this.render();\n\n // Optional sync config — when another surface mutates element state\n // we re-read the axis via readValue() and silently patch the active\n // chip so this instance stays in step. No callback fires (silent).\n //\n // sync = { element, readValue: () => axisKeyFromElement }\n //\n // Canonical pattern for dual-surface axes (Sidebar + Settings\n // popover, Sidebar + Preset picker, etc.) — both surfaces pass a\n // readValue pointing at the SAME element.<axis_key> so state flows\n // one-way: element → control visual.\n this._syncDispose = null;\n if (sync && sync.element && typeof sync.readValue === 'function' && typeof sync.element.addSyncListener === 'function') {\n this._syncDispose = sync.element.addSyncListener('SegmentedTextControl:' + this.id, function () {\n try {\n var next = sync.readValue();\n if (next != null) _this.syncValue(next);\n } catch (_) {/* no-op — sync failures must not crash */}\n });\n }\n }\n\n /**\n * Destroy hook called by Builder.renderElementControls when the control\n * tree rebuilds. Releases the sync subscription so we don't leak\n * listeners across rebuilds.\n */\n return _createClass(SegmentedTextControl, [{\n key: \"destroy\",\n value: function destroy() {\n if (typeof this._syncDispose === 'function') {\n try {\n this._syncDispose();\n } catch (_) {/* no-op */}\n this._syncDispose = null;\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this2 = this;\n var escapeAttr = function escapeAttr(s) {\n return String(s == null ? '' : s).replace(/\"/g, '"');\n };\n var escapeText = function escapeText(s) {\n return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n };\n var buttons = this.options.map(function (opt) {\n var isActive = _this2.value === opt.value;\n var tip = opt.tooltip ? \" data-tooltip=\\\"\".concat(escapeAttr(opt.tooltip), \"\\\"\") : '';\n return \"\\n <button type=\\\"button\\\"\\n class=\\\"bjs-segmented-btn\".concat(isActive ? ' is-active' : '', \"\\\"\\n role=\\\"radio\\\"\\n aria-checked=\\\"\").concat(isActive, \"\\\"\\n data-value=\\\"\").concat(escapeAttr(opt.value), \"\\\"\").concat(tip, \"\\n tabindex=\\\"\").concat(isActive ? '0' : '-1', \"\\\">\\n \").concat(escapeText(opt.label), \"\\n </button>\\n \");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\"><span>\".concat(escapeText(this.label), \"</span></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-segmented\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(escapeAttr(this.label), \"\\\">\\n \").concat(buttons, \"\\n </div>\\n </div>\\n </div>\\n \");\n this._bindEvents();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this3 = this;\n var group = this.domNode.querySelector('.bjs-segmented');\n if (!group) return;\n group.addEventListener('click', function (e) {\n var btn = e.target.closest('.bjs-segmented-btn');\n if (!btn || !group.contains(btn)) return;\n _this3._select(btn.dataset.value, {\n focus: true\n });\n });\n\n // Keyboard nav matches AlignControl — radio group convention\n group.addEventListener('keydown', function (e) {\n if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) return;\n e.preventDefault();\n var btns = Array.from(group.querySelectorAll('.bjs-segmented-btn'));\n var idx = btns.findIndex(function (b) {\n return b.classList.contains('is-active');\n });\n var next = idx;\n if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') next = (idx - 1 + btns.length) % btns.length;else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') next = (idx + 1) % btns.length;else if (e.key === 'Home') next = 0;else if (e.key === 'End') next = btns.length - 1;\n var nb = btns[next];\n if (nb) _this3._select(nb.dataset.value, {\n focus: true\n });\n });\n }\n }, {\n key: \"_select\",\n value: function _select(value) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$focus = _ref.focus,\n focus = _ref$focus === void 0 ? false : _ref$focus;\n if (value === this.value) return;\n this.value = value;\n this._updateActive();\n if (focus) {\n var active = this.domNode.querySelector('.bjs-segmented-btn.is-active');\n if (active) active.focus();\n }\n if (typeof this.callback === 'function') this.callback(this.value);else if (this.callback && typeof this.callback.setValue === 'function') this.callback.setValue(this.value);\n }\n }, {\n key: \"_updateActive\",\n value: function _updateActive() {\n var _this4 = this;\n this.domNode.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n var isActive = btn.dataset.value === _this4.value;\n btn.classList.toggle('is-active', isActive);\n btn.setAttribute('aria-checked', String(isActive));\n btn.setAttribute('tabindex', isActive ? '0' : '-1');\n });\n }\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n if (newValue === this.value) return;\n this.value = newValue;\n this._updateActive();\n if (typeof this.callback === 'function') this.callback(this.value);else if (this.callback && typeof this.callback.setValue === 'function') this.callback.setValue(this.value);\n }\n\n /**\n * Silent value set — updates visual state only, DOES NOT fire callback.\n * Used by the sync listener so dual-surface mutations (popover +\n * sidebar) don't bounce back into apply*() and cause a feedback loop.\n */\n }, {\n key: \"syncValue\",\n value: function syncValue(newValue) {\n if (newValue === this.value) return;\n this.value = newValue;\n this._updateActive();\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SegmentedTextControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SegmentedTextControl.js?");
/***/ }),
/***/ "./src/includes/SelectControl.js":
/*!***************************************!*\
!*** ./src/includes/SelectControl.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui/sortable.js */ \"./src/includes/ui/sortable.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n/**\n * SelectControl — edits a list of {label, value} items plus a field name.\n *\n * Consumer: SelectElement, RadioElement, CheckboxElement form fields.\n * Each item surfaces two `.bjs-text-input` fields (label + value) and a\n * remove `.bjs-icon-btn--danger`. \"Add Item\" is a `.bjs-btn`.\n *\n * 2026-04-18 Phase 2.18 rewrite — drops Bootstrap `.form-control\n * form-control-sm`, `.list-group`, `.btn btn-primary`/`btn-danger`,\n * `.d-flex`, etc. Uses `.bjs-*` primitives end-to-end.\n */\nvar SelectControl = /*#__PURE__*/function () {\n function SelectControl(label, items, callback) {\n var inputName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';\n _classCallCheck(this, SelectControl);\n this.label = label;\n this.items = items || [];\n this.callback = callback;\n this.inputName = inputName;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-select-control');\n this.render();\n }\n return _createClass(SelectControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var id = this._id || (this._id = '_' + Math.random().toString(36).substr(2, 9));\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-stack\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label><span>\".concat(this.label, \"</span></label>\\n </div>\\n <div class=\\\"bjs-select-control-name\\\">\\n <label class=\\\"bjs-control-label\\\" for=\\\"\").concat(id, \"_name\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.element_name', 'Element Name'), \"</span></label>\\n <input id=\\\"\").concat(id, \"_name\\\" type=\\\"text\\\" class=\\\"bjs-text-input\\\" value=\\\"\").concat(this._escape(this.inputName), \"\\\" data-control=\\\"name-input\\\" placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.element_name_ph', 'field_name'), \"\\\">\\n </div>\\n <div class=\\\"bjs-select-control-items\\\" data-control=\\\"items\\\"></div>\\n <div class=\\\"bjs-select-control-actions\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-btn bjs-btn--primary\\\" data-control=\\\"add-item\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">add</span>\\n <span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.add_item', 'Add item'), \"</span>\\n </button>\\n </div>\\n </div>\\n \");\n var itemsContainer = this.domNode.querySelector('[data-control=\"items\"]');\n this.items.forEach(function (item, index) {\n var row = document.createElement('div');\n row.className = 'bjs-select-control-item bjs-list-item';\n row.setAttribute('data-index', String(index));\n row.innerHTML = \"\\n <div class=\\\"bjs-select-control-item-head\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-list-item-handle\\\" aria-label=\\\"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.reorder', 'Drag to reorder'), \"\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.reorder', 'Drag to reorder'), \"\\\" tabindex=\\\"0\\\">\\u2261</button>\\n <span class=\\\"bjs-select-control-item-index\\\">#\").concat(index + 1, \"</span>\\n <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-icon-btn--danger\\\" data-control=\\\"remove-item\\\" data-index=\\\"\").concat(index, \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.remove_item', 'Remove item'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">delete</span>\\n </button>\\n </div>\\n <label class=\\\"bjs-select-control-field\\\">\\n <span class=\\\"bjs-select-control-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.label', 'Label'), \"</span>\\n <input type=\\\"text\\\" class=\\\"bjs-text-input\\\" value=\\\"\").concat(_this._escape(item.label), \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"label\\\">\\n </label>\\n <label class=\\\"bjs-select-control-field\\\">\\n <span class=\\\"bjs-select-control-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.value', 'Value'), \"</span>\\n <input type=\\\"text\\\" class=\\\"bjs-text-input\\\" value=\\\"\").concat(_this._escape(item.value), \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"value\\\">\\n </label>\\n \");\n row.querySelectorAll('input[data-field]').forEach(function (inp) {\n inp.addEventListener('input', function (e) {\n var _this$callback;\n var field = e.target.dataset.field;\n var i = parseInt(e.target.dataset.index, 10);\n _this.items[i][field] = e.target.value;\n if ((_this$callback = _this.callback) !== null && _this$callback !== void 0 && _this$callback.setItems) _this.callback.setItems(_this.items);\n });\n });\n row.querySelector('[data-control=\"remove-item\"]').addEventListener('click', function (e) {\n var _this$callback2;\n var i = parseInt(e.currentTarget.dataset.index, 10);\n _this.items.splice(i, 1);\n _this.render();\n if ((_this$callback2 = _this.callback) !== null && _this$callback2 !== void 0 && _this$callback2.setItems) _this.callback.setItems(_this.items);\n });\n itemsContainer.appendChild(row);\n });\n this.domNode.querySelector('[data-control=\"add-item\"]').addEventListener('click', function () {\n var _this$callback3;\n _this.items.push({\n label: '',\n value: ''\n });\n _this.render();\n if ((_this$callback3 = _this.callback) !== null && _this$callback3 !== void 0 && _this$callback3.setItems) _this.callback.setItems(_this.items);\n });\n this.domNode.querySelector('[data-control=\"name-input\"]').addEventListener('input', function (e) {\n var _this$callback4;\n _this.inputName = e.target.value;\n if ((_this$callback4 = _this.callback) !== null && _this$callback4 !== void 0 && _this$callback4.setName) _this.callback.setName(_this.inputName);\n });\n this._bindSortable();\n }\n\n /** Phase-3 W6.2 — drag-reorder via shared bjsSortable mixin. Items are\n * the existing .bjs-select-control-item rows (aliased to .bjs-list-item\n * so the shared mixin's default selectors work). */\n }, {\n key: \"_bindSortable\",\n value: function _bindSortable() {\n var _this2 = this;\n if (this._sortable && typeof this._sortable.destroy === 'function') {\n try {\n this._sortable.destroy();\n } catch (_e) {}\n }\n var container = this.domNode.querySelector('[data-control=\"items\"]');\n if (!container) return;\n this._sortable = (0,_ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__.bjsSortable)(container, {\n itemSelector: '.bjs-list-item',\n handleSelector: '.bjs-list-item-handle',\n onReorder: function onReorder(from, to) {\n var _this2$callback;\n var _this2$items$splice = _this2.items.splice(from, 1),\n _this2$items$splice2 = _slicedToArray(_this2$items$splice, 1),\n moved = _this2$items$splice2[0];\n var adjusted = to > from ? to - 1 : to;\n _this2.items.splice(adjusted, 0, moved);\n _this2.render();\n if ((_this2$callback = _this2.callback) !== null && _this2$callback !== void 0 && _this2$callback.setItems) _this2.callback.setItems(_this2.items);\n }\n });\n }\n }, {\n key: \"_escape\",\n value: function _escape(s) {\n return String(s !== null && s !== void 0 ? s : '').replace(/\"/g, '"').replace(/</g, '<');\n }\n }, {\n key: \"getListContainer\",\n value: function getListContainer() {\n return this.domNode.querySelector('[data-control=\"items\"]');\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SelectControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SelectControl.js?");
/***/ }),
/***/ "./src/includes/SelectElement.js":
/*!***************************************!*\
!*** ./src/includes/SelectElement.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SelectControl.js */ \"./src/includes/SelectControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\nvar SelectElement = /*#__PURE__*/function (_BaseElement) {\n function SelectElement(template) {\n var _this;\n var inputName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"\";\n var items = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];\n _classCallCheck(this, SelectElement);\n _this = _callSuper(this, SelectElement);\n _this.template = template;\n _this.items = _this.normalizeItems(items);\n _this.inputName = inputName;\n _this.domNode = null;\n _this.requiredTemplateKeys = [\"items\"];\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n background_color: null,\n background_image: null,\n background_position: \"center\",\n background_size: \"100%\",\n background_repeat: \"no-repeat\",\n padding_top: null,\n padding_right: null,\n padding_bottom: null,\n padding_left: null,\n width: null,\n height: null\n });\n return _this;\n }\n _inherits(SelectElement, _BaseElement);\n return _createClass(SelectElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.select');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n items: this.items,\n inputName: this.inputName\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(SelectElement, \"getData\", this, 3)([])), {}, {\n inputName: this.inputName,\n items: this.items\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this;\n return [new _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.select_options'), this.items.map(function (item) {\n return {\n label: item.label,\n value: item.value\n };\n }), {\n setItems: function setItems(items) {\n _this2.items = _this2.normalizeItems(items);\n _this2.render();\n },\n setName: function setName(name) {\n _this2.inputName = name;\n _this2.render();\n }\n }, this.inputName),\n // W3.8b — InnerPaddingControl (intrinsic: select input breathing room).\n new InnerPaddingControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.select_padding'), {\n top: this.formatter.getFormat(\"padding_top\"),\n right: this.formatter.getFormat(\"padding_right\"),\n bottom: this.formatter.getFormat(\"padding_bottom\"),\n left: this.formatter.getFormat(\"padding_left\")\n }, {\n setValues: function setValues(values) {\n _this2.formatter.setFormat(\"padding_top\", values.top);\n _this2.formatter.setFormat(\"padding_right\", values.right);\n _this2.formatter.setFormat(\"padding_bottom\", values.bottom);\n _this2.formatter.setFormat(\"padding_left\", values.left);\n _this2.render();\n }\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.width'), this.formatter.getFormat(\"width\"), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat(\"width\", value);\n _this2.render();\n }\n }, {\n defaultValue: 320,\n minValue: 80,\n maxValue: 1600,\n suffix: \"px\",\n allowZero: false\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.height'), this.formatter.getFormat(\"height\"), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat(\"height\", value);\n _this2.render();\n }\n }, {\n defaultValue: 44,\n minValue: 24,\n maxValue: 400,\n suffix: \"px\",\n allowZero: false\n })];\n }\n }, {\n key: \"normalizeItems\",\n value: function normalizeItems(items) {\n return (Array.isArray(items) ? items : []).map(function (item, index) {\n var _item$label, _item$value;\n return {\n label: (_item$label = item === null || item === void 0 ? void 0 : item.label) !== null && _item$label !== void 0 ? _item$label : \"Option \".concat(index + 1),\n value: (_item$value = item === null || item === void 0 ? void 0 : item.value) !== null && _item$value !== void 0 ? _item$value : \"option_\".concat(index + 1)\n };\n });\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.inputName || \"\", data.items || []), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SelectElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SelectElement.js?");
/***/ }),
/***/ "./src/includes/SelectWidget.js":
/*!**************************************!*\
!*** ./src/includes/SelectWidget.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _SelectElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./SelectElement.js */ \"./src/includes/SelectElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar SelectWidget = /*#__PURE__*/function (_BaseWidget) {\n function SelectWidget() {\n var _this;\n _classCallCheck(this, SelectWidget);\n _this = _callSuper(this, SelectWidget);\n _this.block.appendElements([new _SelectElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Select', 'topic', [{\n label: 'Choose an option',\n value: ''\n }, {\n label: 'Starter',\n value: 'starter'\n }, {\n label: 'Growth',\n value: 'growth'\n }, {\n label: 'Enterprise',\n value: 'enterprise'\n }])]);\n return _this;\n }\n _inherits(SelectWidget, _BaseWidget);\n return _createClass(SelectWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.select');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'arrow_drop_down_circle';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SelectWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SelectWidget.js?");
/***/ }),
/***/ "./src/includes/SeparatorControl.js":
/*!******************************************!*\
!*** ./src/includes/SeparatorControl.js ***!
\******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * SeparatorControl — compact picker for a short divider glyph.\n *\n * Built for MenuElement, but reusable anywhere a user needs to pick\n * a short string separator (list bullets, breadcrumb dividers, etc.).\n *\n * UX: 6-slot segmented (None + 4 common glyphs + Custom). Picking\n * Custom reveals a compact 50%-width .bjs-text-input on its own row.\n *\n * No-flicker rule (2026-04-17 audit pass-4):\n * - The DOM structure is built ONCE in the constructor.\n * - The custom-input row stays mounted permanently; visibility is\n * toggled via `hidden`/display, not by re-stamping innerHTML.\n * - Clicks, keystrokes, and value changes only mutate\n * classList / aria-checked / input.value — never rebuild the HTML.\n * This keeps the text input's focus + caret position stable across\n * every interaction, including typing, and stops the preset clicks\n * from feeling twitchy.\n *\n * Value contract: `null`/`''` means \"no separator\". Any other string\n * is the raw glyph(s) to render between items.\n */\nvar SeparatorControl = /*#__PURE__*/function () {\n function SeparatorControl(label, value, callback) {\n _classCallCheck(this, SeparatorControl);\n this.label = label;\n this.value = value || null;\n this.callback = callback;\n this.domNode = document.createElement('div');\n // Custom mode is a UX flag, not value-derived. Picking Custom with\n // an empty string must still reveal the input; only clicking None /\n // a preset turns custom mode off. Initial state: infer from value\n // (non-preset non-null means we came in as custom).\n this._customMode = !!this.value && !this._isPreset(this.value);\n this._buildDom();\n this._bindEvents();\n this._syncDom();\n }\n return _createClass(SeparatorControl, [{\n key: \"_isPreset\",\n value: function _isPreset(v) {\n if (v == null || v === '') return false;\n return SeparatorControl.PRESETS.some(function (p) {\n return p.value === v;\n });\n }\n }, {\n key: \"_buildDom\",\n value: function _buildDom() {\n var presetBtns = SeparatorControl.PRESETS.map(function (p) {\n return \"<button class=\\\"bjs-segmented-btn\\\" type=\\\"button\\\" data-preset=\\\"\".concat(p.value, \"\\\" aria-label=\\\"\").concat(p.label, \"\\\" aria-checked=\\\"false\\\" role=\\\"radio\\\">\").concat(p.label, \"</button>\");\n }).join('');\n\n // Structure stays constant. Only classList/aria/input value/hidden\n // attr change on subsequent interactions.\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <label class=\\\"bjs-control-label\\\">\".concat(this.label, \"</label>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-segmented\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(this.label, \"\\\">\\n <button class=\\\"bjs-segmented-btn\\\" type=\\\"button\\\" data-action=\\\"none\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.none'), \"\\\" aria-checked=\\\"false\\\" role=\\\"radio\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.none'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">block</span>\\n </button>\\n \").concat(presetBtns, \"\\n <button class=\\\"bjs-segmented-btn\\\" type=\\\"button\\\" data-action=\\\"custom\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.custom'), \"\\\" aria-checked=\\\"false\\\" role=\\\"radio\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.custom'), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">edit</span>\\n </button>\\n </div>\\n </div>\\n </div>\\n <div class=\\\"bjs-separator-custom-row\\\" hidden>\\n <input\\n type=\\\"text\\\"\\n class=\\\"bjs-text-input bjs-separator-custom-input\\\"\\n data-control=\\\"custom-input\\\"\\n maxlength=\\\"8\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.placeholder'), \"\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.custom'), \"\\\"\\n />\\n </div>\\n \");\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this = this;\n // Events bound ONCE on the mounted structure. Interactions mutate\n // state + call _syncDom() — no innerHTML rewriting, no rebinding.\n this.domNode.querySelectorAll('[data-preset]').forEach(function (btn) {\n btn.addEventListener('click', function () {\n _this._customMode = false;\n _this.value = btn.dataset.preset;\n _this._emit();\n _this._syncDom();\n });\n });\n var noneBtn = this.domNode.querySelector('[data-action=\"none\"]');\n if (noneBtn) {\n noneBtn.addEventListener('click', function () {\n _this._customMode = false;\n _this.value = null;\n _this._emit();\n _this._syncDom();\n });\n }\n var customBtn = this.domNode.querySelector('[data-action=\"custom\"]');\n if (customBtn) {\n customBtn.addEventListener('click', function () {\n _this._customMode = true;\n if (_this._isPreset(_this.value)) _this.value = null;\n // Intentionally NO _emit() here — clicking Custom is a\n // UX mode switch, not a value change. The first keystroke\n // in the input will emit the real value.\n _this._syncDom();\n var input = _this.domNode.querySelector('[data-control=\"custom-input\"]');\n if (input) input.focus();\n });\n }\n var customInput = this.domNode.querySelector('[data-control=\"custom-input\"]');\n if (customInput) {\n customInput.addEventListener('input', function (e) {\n _this._customMode = true;\n _this.value = e.target.value || null;\n _this._emit();\n // DO NOT touch the input's .value here (would reset caret).\n // Only sync the active-chip state.\n _this._syncActiveChip();\n });\n }\n }\n\n /** Full DOM sync — used on structural state changes (preset pick, None,\n * Custom mode toggle). Does NOT rebuild HTML; only flips attributes /\n * classes / hidden. Safe to call mid-focus. */\n }, {\n key: \"_syncDom\",\n value: function _syncDom() {\n this._syncActiveChip();\n var customRow = this.domNode.querySelector('.bjs-separator-custom-row');\n var customInput = this.domNode.querySelector('[data-control=\"custom-input\"]');\n if (customRow) {\n if (this._customMode) customRow.removeAttribute('hidden');else customRow.setAttribute('hidden', '');\n }\n if (customInput) {\n // Only write back to input when we're NOT in an in-flight edit.\n // Reading document.activeElement lets us skip the write while\n // the user is actively typing; the input event keeps value and\n // state in sync anyway.\n if (document.activeElement !== customInput) {\n var desired = this._customMode && typeof this.value === 'string' ? this.value : '';\n if (customInput.value !== desired) customInput.value = desired;\n }\n }\n }\n }, {\n key: \"_syncActiveChip\",\n value: function _syncActiveChip() {\n var val = this.value;\n var customActive = this._customMode;\n var presetActive = !customActive && this._isPreset(val);\n this.domNode.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n btn.classList.remove('is-active');\n btn.setAttribute('aria-checked', 'false');\n });\n var activeBtn = customActive ? this.domNode.querySelector('[data-action=\"custom\"]') : presetActive ? this.domNode.querySelector(\"[data-preset=\\\"\".concat(CSS.escape(val), \"\\\"]\")) : this.domNode.querySelector('[data-action=\"none\"]');\n if (activeBtn) {\n activeBtn.classList.add('is-active');\n activeBtn.setAttribute('aria-checked', 'true');\n }\n }\n }, {\n key: \"_emit\",\n value: function _emit() {\n if (this.callback && this.callback.setText) {\n this.callback.setText(this.value);\n }\n }\n }]);\n}();\n_defineProperty(SeparatorControl, \"PRESETS\", [{\n value: '|',\n label: '|'\n}, {\n value: \"\\u2022\",\n label: \"\\u2022\"\n},\n// •\n{\n value: \"\\u2014\",\n label: \"\\u2014\"\n},\n// —\n{\n value: '/',\n label: '/'\n}]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SeparatorControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SeparatorControl.js?");
/***/ }),
/***/ "./src/includes/SettingsTabManager.js":
/*!********************************************!*\
!*** ./src/includes/SettingsTabManager.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var ejs_browser__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ejs-browser */ \"./node_modules/ejs-browser/lib/ejs.js\");\n/* harmony import */ var ejs_browser__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ejs_browser__WEBPACK_IMPORTED_MODULE_0__);\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar SettingsTabManager = /*#__PURE__*/function () {\n function SettingsTabManager(container) {\n _classCallCheck(this, SettingsTabManager);\n this.container = container;\n this.tabs = [];\n }\n return _createClass(SettingsTabManager, [{\n key: \"addTab\",\n value: function addTab(name, label, icon) {\n this.tabs.push({\n name: name,\n label: label,\n icon: icon\n });\n }\n }, {\n key: \"openTab\",\n value: function openTab(tabName) {\n var _this = this;\n this.tabs.forEach(function (tab) {\n if (tab.name === tabName) {\n _this.container.querySelector('[data-tab=\"' + tab.name + '\"]').classList.add('active');\n _this.container.querySelector('[data-tab-container=\"' + tab.name + '\"]').style.display = 'block';\n } else {\n _this.container.querySelector('[data-tab=\"' + tab.name + '\"]').classList.remove('active');\n _this.container.querySelector('[data-tab-container=\"' + tab.name + '\"]').style.display = 'none';\n }\n });\n }\n }, {\n key: \"getTab\",\n value: function getTab(tabName) {\n var tab = this.tabs.find(function (t) {\n return t.name === tabName;\n });\n return {\n name: tab.name,\n label: tab.label,\n icon: tab.icon,\n container: this.container.querySelector('[data-tab-container=\"' + tab.name + '\"]'),\n button: this.container.querySelector('[data-tab=\"' + tab.name + '\"]')\n };\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this2 = this;\n this.container.innerHTML = \"\\n <div class=\\\"builder-sidebar-tabs px-3 py-2 rounded-0 d-flex bg-light border-bottom\\\">\\n \".concat(this.tabs.map(function (tab, idx) {\n return \"\\n <div class=\\\"tab-item\\\" data-tab=\\\"\".concat(tab.name, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">\").concat(tab.icon, \"</span>\\n <!-- <span>\").concat(tab.label, \"</span> -->\\n </div>\\n \");\n }).join(''), \"\\n </div>\\n <div>\\n \").concat(this.tabs.map(function (tab, idx) {\n return \"\\n <div data-tab-container=\\\"\".concat(tab.name, \"\\\" style=\\\"display: none;\\\">\\n </div>\\n \");\n }).join(''), \"\\n </div>\\n \");\n\n // \n this.tabs.forEach(function (tab) {\n _this2.getTab(tab.name).button.addEventListener('click', function () {\n _this2.openTab(tab.name);\n });\n });\n\n // @todo\n document.querySelector('[data-tab=\"styles\"]').addEventListener('click', function () {\n if (window.smenu) {\n window.smenu.openTab(document.querySelector('[data-smenu=\"themes\"]'));\n }\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SettingsTabManager);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SettingsTabManager.js?");
/***/ }),
/***/ "./src/includes/SocialIconsControl.js":
/*!********************************************!*\
!*** ./src/includes/SocialIconsControl.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui/sortable.js */ \"./src/includes/ui/sortable.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\nvar SocialIconsControl = /*#__PURE__*/function () {\n function SocialIconsControl(label, items, iconPacks, callback) {\n _classCallCheck(this, SocialIconsControl);\n this.label = label;\n this.items = items; // [{ image_url, label, url }]\n this.iconPacks = iconPacks;\n this.callback = callback;\n this.domNode = document.createElement('div');\n this.render();\n }\n return _createClass(SocialIconsControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var platformOrder = ['facebook', 'instagram', 'linkedin', 'twitter', 'youtube', 'tiktok', 'pinterest'];\n var allPresets = this.getPresets();\n\n // Quick-add dropdown items\n var dropdownItems = platformOrder.map(function (key) {\n var p = allPresets[key];\n if (!p) return '';\n var icon = p.image_url ? \"<img src=\\\"\".concat(p.image_url, \"\\\" alt=\\\"\").concat(p.label, \"\\\">\") : '';\n return \"<button class=\\\"bjs-list-dropdown-item\\\" type=\\\"button\\\" data-network=\\\"\".concat(key, \"\\\">\").concat(icon, \"<span>\").concat(p.label, \"</span></button>\");\n }).join('');\n\n // List items\n var itemsHtml = this.items.map(function (item, index) {\n var thumb = item.image_url ? \"<img src=\\\"\".concat(item.image_url, \"\\\" alt=\\\"\").concat(item.label || '', \"\\\">\") : \"<span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px;color:var(--bjs-text-muted)\\\">image</span>\";\n var displayName = _this.getDisplayName(item) || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.social_item');\n\n // Platform chooser buttons\n var platformsHtml = platformOrder.map(function (key) {\n var p = allPresets[key];\n if (!p) return '';\n var icon = p.image_url ? \"<img src=\\\"\".concat(p.image_url, \"\\\" alt=\\\"\").concat(p.label, \"\\\">\") : '';\n return \"<button class=\\\"bjs-list-platform-btn\\\" type=\\\"button\\\" data-platform=\\\"\".concat(key, \"\\\" data-index=\\\"\").concat(index, \"\\\">\").concat(icon, \"<span>\").concat(p.label, \"</span></button>\");\n }).join('');\n var safeLabel = (item.label || '').replace(/\"/g, '"');\n var safeUrl = (item.url || '').replace(/\"/g, '"');\n return \"\\n <li class=\\\"bjs-list-item\\\" data-index=\\\"\".concat(index, \"\\\" aria-expanded=\\\"false\\\">\\n <button class=\\\"bjs-list-item-handle\\\" aria-label=\\\"Drag to reorder\\\" type=\\\"button\\\" tabindex=\\\"0\\\">\\u2261</button>\\n <span class=\\\"bjs-list-item-thumb\\\" data-control=\\\"thumb\\\" data-index=\\\"\").concat(index, \"\\\">\").concat(thumb, \"</span>\\n <span class=\\\"bjs-list-item-label\\\" data-control=\\\"display-label\\\" data-index=\\\"\").concat(index, \"\\\">\").concat(displayName, \"</span>\\n <div class=\\\"bjs-list-item-actions\\\">\\n <button class=\\\"bjs-icon-btn bjs-list-item-expand\\\" aria-label=\\\"Edit\\\" data-control=\\\"expand\\\" data-index=\\\"\").concat(index, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">expand_more</span>\\n </button>\\n <button class=\\\"bjs-icon-btn\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.move_up'), \"\\\" data-control=\\\"move-up\\\" data-index=\\\"\").concat(index, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">arrow_upward</span>\\n </button>\\n <button class=\\\"bjs-icon-btn\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.move_down'), \"\\\" data-control=\\\"move-down\\\" data-index=\\\"\").concat(index, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">arrow_downward</span>\\n </button>\\n <button class=\\\"bjs-icon-btn bjs-icon-btn--danger\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.delete_item'), \"\\\" data-control=\\\"remove-item\\\" data-index=\\\"\").concat(index, \"\\\">\\n <span class=\\\"material-symbols-rounded\\\">delete</span>\\n </button>\\n </div>\\n <section class=\\\"bjs-list-item-body\\\">\\n <div class=\\\"bjs-list-platforms\\\" data-control=\\\"platforms\\\" data-index=\\\"\").concat(index, \"\\\">\\n \").concat(platformsHtml, \"\\n </div>\\n <div class=\\\"bjs-list-field\\\">\\n <label class=\\\"bjs-list-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.label'), \"</label>\\n <input type=\\\"text\\\" class=\\\"bjs-list-field-input\\\" placeholder=\\\"Facebook\\\" value=\\\"\").concat(safeLabel, \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"label\\\">\\n </div>\\n <div class=\\\"bjs-list-field\\\">\\n <label class=\\\"bjs-list-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.url_label'), \"</label>\\n <input type=\\\"text\\\" class=\\\"bjs-list-field-input\\\" placeholder=\\\"https://facebook.com/yourpage\\\" value=\\\"\").concat(safeUrl, \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"url\\\">\\n </div>\\n </section>\\n </li>\\n \");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-list bjs-list--social\\\">\\n <header class=\\\"bjs-list-header\\\">\\n <span class=\\\"bjs-list-title\\\">\".concat(this.label, \"</span>\\n <div class=\\\"bjs-list-add\\\">\\n <button class=\\\"bjs-btn\\\" type=\\\"button\\\" data-control=\\\"add-item\\\">\\n <span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px;margin-right:2px\\\">add</span> \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.add'), \"\\n </button>\\n <div class=\\\"bjs-list-dropdown\\\">\\n <button class=\\\"bjs-btn bjs-btn-caret\\\" type=\\\"button\\\" data-control=\\\"dropdown-toggle\\\" aria-label=\\\"Quick add presets\\\">\\n <span class=\\\"material-symbols-rounded\\\">expand_more</span>\\n </button>\\n <div class=\\\"bjs-list-dropdown-menu\\\" data-control=\\\"dropdown-menu\\\">\\n \").concat(dropdownItems, \"\\n </div>\\n </div>\\n </div>\\n </header>\\n <ol class=\\\"bjs-list-items\\\">\\n \").concat(itemsHtml, \"\\n </ol>\\n </div>\\n \");\n this._autoFixPresets();\n this._bindEvents();\n this._bindSortable();\n }\n\n /** Phase-3 W6.2 — drag-reorder via shared bjsSortable mixin. The\n * per-item up/down buttons stay as an a11y fallback (keyboard-first)\n * but pointer users get a proper drag-and-drop. */\n }, {\n key: \"_bindSortable\",\n value: function _bindSortable() {\n var _this2 = this;\n if (this._sortable && typeof this._sortable.destroy === 'function') {\n try {\n this._sortable.destroy();\n } catch (_e) {}\n }\n var ol = this.domNode.querySelector('.bjs-list-items');\n if (!ol) return;\n this._sortable = (0,_ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__.bjsSortable)(ol, {\n itemSelector: '.bjs-list-item',\n handleSelector: '.bjs-list-item-handle',\n onReorder: function onReorder(from, to) {\n var _this2$items$splice = _this2.items.splice(from, 1),\n _this2$items$splice2 = _slicedToArray(_this2$items$splice, 1),\n moved = _this2$items$splice2[0];\n var adjusted = to > from ? to - 1 : to;\n _this2.items.splice(adjusted, 0, moved);\n _this2.render();\n _this2.callback && _this2.callback.setItems(_this2.items);\n }\n });\n }\n }, {\n key: \"_autoFixPresets\",\n value: function _autoFixPresets() {\n var _this3 = this;\n var mutated = false;\n this.items.forEach(function (item) {\n try {\n var preset = _this3.getPresetByUrl(item.url || '') || _this3.getPresetByLabel(item.label || '') || _this3.getPresetByImageUrl(item.image_url || '');\n if (preset) {\n if (!item.image_url || _this3.isDefaultThemeIconUrl(item.image_url)) {\n item.image_url = preset.image_url;\n mutated = true;\n }\n if (!item.label) {\n item.label = preset.label;\n mutated = true;\n }\n }\n } catch (_) {}\n });\n if (mutated) {\n this.callback && this.callback.setItems(this.items);\n }\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this4 = this;\n // Add item\n var addBtn = this.domNode.querySelector('[data-control=\"add-item\"]');\n if (addBtn) {\n addBtn.addEventListener('click', function () {\n _this4.items.push({\n image_url: '',\n label: '',\n url: ''\n });\n _this4.render();\n _this4.callback && _this4.callback.setItems(_this4.items);\n });\n }\n\n // Dropdown toggle\n var dropdownToggle = this.domNode.querySelector('[data-control=\"dropdown-toggle\"]');\n var dropdownMenu = this.domNode.querySelector('[data-control=\"dropdown-menu\"]');\n if (dropdownToggle && dropdownMenu) {\n dropdownToggle.addEventListener('click', function (e) {\n e.stopPropagation();\n dropdownMenu.classList.toggle('is-open');\n });\n // Close on outside click\n var closeDropdown = function closeDropdown(e) {\n if (!dropdownMenu.contains(e.target) && e.target !== dropdownToggle) {\n dropdownMenu.classList.remove('is-open');\n }\n };\n document.addEventListener('click', closeDropdown);\n // Store cleanup ref\n this._cleanupDropdown = function () {\n return document.removeEventListener('click', closeDropdown);\n };\n }\n\n // Quick-add presets from dropdown\n this.domNode.querySelectorAll('.bjs-list-dropdown-item[data-network]').forEach(function (btn) {\n btn.addEventListener('click', function (e) {\n var network = e.currentTarget.dataset.network;\n var p = _this4.getPresets()[network];\n if (!p) return;\n _this4.items.push({\n image_url: p.image_url,\n label: p.label,\n url: p.url\n });\n dropdownMenu && dropdownMenu.classList.remove('is-open');\n _this4.render();\n _this4.callback && _this4.callback.setItems(_this4.items);\n });\n });\n\n // Per-item events\n this.domNode.querySelectorAll('.bjs-list-item').forEach(function (li) {\n var _li$querySelector, _li$querySelector2, _li$querySelector3;\n var index = parseInt(li.dataset.index, 10);\n\n // Expand/collapse\n var expandBtn = li.querySelector('[data-control=\"expand\"]');\n if (expandBtn) {\n expandBtn.addEventListener('click', function (e) {\n e.preventDefault();\n var isExpanded = li.getAttribute('aria-expanded') === 'true';\n // Collapse all others\n _this4.domNode.querySelectorAll('.bjs-list-item').forEach(function (other) {\n other.setAttribute('aria-expanded', 'false');\n });\n if (!isExpanded) {\n li.setAttribute('aria-expanded', 'true');\n }\n });\n }\n\n // Remove\n (_li$querySelector = li.querySelector('[data-control=\"remove-item\"]')) === null || _li$querySelector === void 0 || _li$querySelector.addEventListener('click', function (e) {\n e.preventDefault();\n _this4.items.splice(index, 1);\n _this4.render();\n _this4.callback && _this4.callback.setItems(_this4.items);\n });\n\n // Move up\n (_li$querySelector2 = li.querySelector('[data-control=\"move-up\"]')) === null || _li$querySelector2 === void 0 || _li$querySelector2.addEventListener('click', function (e) {\n e.preventDefault();\n if (index > 0) {\n var _ref = [_this4.items[index], _this4.items[index - 1]];\n _this4.items[index - 1] = _ref[0];\n _this4.items[index] = _ref[1];\n _this4.render();\n _this4.callback && _this4.callback.setItems(_this4.items);\n }\n });\n\n // Move down\n (_li$querySelector3 = li.querySelector('[data-control=\"move-down\"]')) === null || _li$querySelector3 === void 0 || _li$querySelector3.addEventListener('click', function (e) {\n e.preventDefault();\n if (index < _this4.items.length - 1) {\n var _ref2 = [_this4.items[index], _this4.items[index + 1]];\n _this4.items[index + 1] = _ref2[0];\n _this4.items[index] = _ref2[1];\n _this4.render();\n _this4.callback && _this4.callback.setItems(_this4.items);\n }\n });\n\n // Platform quick-apply buttons\n li.querySelectorAll('.bjs-list-platform-btn[data-platform]').forEach(function (btn) {\n btn.addEventListener('click', function (e) {\n var key = e.currentTarget.dataset.platform;\n var p = _this4.getPresets()[key];\n if (!p) return;\n _this4.items[index].label = p.label;\n _this4.items[index].url = p.url;\n _this4.items[index].image_url = p.image_url;\n // Update in-place without full re-render\n _this4._updateItemDisplay(li, index);\n _this4.callback && _this4.callback.setItems(_this4.items);\n });\n });\n\n // Text input live updates\n li.querySelectorAll('input[data-field]').forEach(function (input) {\n input.addEventListener('input', function (e) {\n var field = e.target.dataset.field;\n _this4.items[index][field] = e.target.value;\n _this4._updateDisplayLabel(li, index);\n _this4.callback && _this4.callback.setItems(_this4.items);\n });\n\n // URL blur: normalize + infer preset\n if (input.dataset.field === 'url') {\n input.addEventListener('blur', function (e) {\n var url = (e.target.value || '').trim();\n var changed = false;\n if (url && !/^https?:\\/\\//i.test(url)) {\n url = 'https://' + url;\n e.target.value = url;\n _this4.items[index].url = url;\n changed = true;\n }\n var preset = _this4.getPresetByUrl(url);\n if (preset) {\n if (!_this4.items[index].image_url || _this4.isDefaultThemeIconUrl(_this4.items[index].image_url)) {\n _this4.items[index].image_url = preset.image_url;\n changed = true;\n }\n if (!_this4.items[index].label) {\n _this4.items[index].label = preset.label;\n var labelInput = li.querySelector('input[data-field=\"label\"]');\n if (labelInput) labelInput.value = preset.label;\n changed = true;\n }\n }\n if (changed) {\n _this4._updateItemDisplay(li, index);\n _this4.callback && _this4.callback.setItems(_this4.items);\n }\n });\n }\n });\n });\n }\n }, {\n key: \"_updateItemDisplay\",\n value: function _updateItemDisplay(li, index) {\n var item = this.items[index];\n // Update thumb\n var thumbEl = li.querySelector('[data-control=\"thumb\"]');\n if (thumbEl) {\n thumbEl.innerHTML = item.image_url ? \"<img src=\\\"\".concat(item.image_url, \"\\\" alt=\\\"\").concat(item.label || '', \"\\\">\") : \"<span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px;color:var(--bjs-text-muted)\\\">image</span>\";\n }\n // Update label\n this._updateDisplayLabel(li, index);\n // Update form inputs\n var labelInput = li.querySelector('input[data-field=\"label\"]');\n if (labelInput && labelInput.value !== item.label) labelInput.value = item.label || '';\n var urlInput = li.querySelector('input[data-field=\"url\"]');\n if (urlInput && urlInput.value !== item.url) urlInput.value = item.url || '';\n }\n }, {\n key: \"_updateDisplayLabel\",\n value: function _updateDisplayLabel(li, index) {\n var item = this.items[index];\n var labelEl = li.querySelector('[data-control=\"display-label\"]');\n if (labelEl) {\n labelEl.textContent = this.getDisplayName(item) || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.social_item');\n }\n }\n\n // Derive a friendly name for the item based on label or URL\n }, {\n key: \"getDisplayName\",\n value: function getDisplayName(item) {\n var label = (item.label || '').trim();\n if (label) return label;\n var url = (item.url || '').trim().toLowerCase();\n if (!url) return '';\n try {\n var u = new URL(url.startsWith('http') ? url : \"https://\".concat(url));\n var host = u.hostname.replace('www.', '');\n var map = {\n 'facebook.com': 'Facebook',\n 'fb.com': 'Facebook',\n 'instagram.com': 'Instagram',\n 'twitter.com': 'Twitter',\n 'x.com': 'X',\n 'linkedin.com': 'LinkedIn',\n 'youtube.com': 'YouTube',\n 'tiktok.com': 'TikTok',\n 'pinterest.com': 'Pinterest',\n 'threads.net': 'Threads',\n 'snapchat.com': 'Snapchat',\n 'whatsapp.com': 'WhatsApp',\n 'telegram.me': 'Telegram',\n 't.me': 'Telegram'\n };\n return map[host] || host;\n } catch (_) {\n return '';\n }\n }\n }, {\n key: \"getPresets\",\n value: function getPresets() {\n return this.iconPacks;\n }\n }, {\n key: \"isDefaultThemeIconUrl\",\n value: function isDefaultThemeIconUrl(url) {\n if (!url) return false;\n return /image\\/(BurgerCraft_theme|social_theme)\\/.*(facebook|twitter|linkedin|instagram|pinterest|youtube|tiktok).*\\.(png|jpg|jpeg|gif)$/i.test(url);\n }\n }, {\n key: \"getPresetByLabel\",\n value: function getPresetByLabel(label) {\n if (!label) return null;\n var key = label.trim().toLowerCase();\n var map = {\n facebook: 'facebook',\n instagram: 'instagram',\n linkedin: 'linkedin',\n twitter: 'twitter',\n x: 'twitter',\n 'twitter / x': 'twitter',\n youtube: 'youtube',\n tiktok: 'tiktok',\n pinterest: 'pinterest'\n };\n var k = map[key];\n return k ? this.getPresets()[k] || null : null;\n }\n }, {\n key: \"getPresetByImageUrl\",\n value: function getPresetByImageUrl(imageUrl) {\n if (!imageUrl) return null;\n var lower = imageUrl.toLowerCase();\n var pairs = [['facebook', 'facebook'], ['instagram', 'instagram'], ['linkedin', 'linkedin'], ['twitter', 'twitter'], ['/x.', 'twitter'], ['-x.', 'twitter'], ['youtube', 'youtube'], ['youtu', 'youtube'], ['tiktok', 'tiktok'], ['pinterest', 'pinterest']];\n for (var _i = 0, _pairs = pairs; _i < _pairs.length; _i++) {\n var _pairs$_i = _slicedToArray(_pairs[_i], 2),\n needle = _pairs$_i[0],\n key = _pairs$_i[1];\n if (lower.includes(needle)) return this.getPresets()[key] || null;\n }\n return null;\n }\n }, {\n key: \"getPresetByUrl\",\n value: function getPresetByUrl(url) {\n if (!url) return null;\n try {\n var u = new URL(url.startsWith('http') ? url : \"https://\".concat(url));\n var host = u.hostname.replace(/^www\\./i, '');\n var map = {\n 'facebook.com': 'facebook',\n 'fb.com': 'facebook',\n 'instagram.com': 'instagram',\n 'linkedin.com': 'linkedin',\n 'twitter.com': 'twitter',\n 'x.com': 'twitter',\n 'youtube.com': 'youtube',\n 'youtu.be': 'youtube',\n 'tiktok.com': 'tiktok',\n 'pinterest.com': 'pinterest'\n };\n var key = map[host];\n return key ? this.getPresets()[key] || null : null;\n } catch (_) {\n return null;\n }\n }\n }, {\n key: \"browserAndUpload\",\n value: function browserAndUpload(itemIndex) {\n var _this5 = this;\n var input = document.createElement('input');\n input.type = 'file';\n input.accept = 'image/*';\n input.addEventListener('change', /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(event) {\n var file, formData, response, result;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n file = event.target.files[0];\n if (file) {\n _context.next = 3;\n break;\n }\n return _context.abrupt(\"return\");\n case 3:\n formData = new FormData();\n formData.append('file', file);\n _context.prev = 5;\n _context.next = 8;\n return fetch(_this5.host.assetUploadHandler, {\n method: 'POST',\n body: formData\n });\n case 8:\n response = _context.sent;\n if (!response.ok) {\n _context.next = 14;\n break;\n }\n _context.next = 12;\n return response.json();\n case 12:\n result = _context.sent;\n if (result.url) {\n _this5.items[itemIndex].image_url = result.url;\n _this5.render();\n _this5.callback && _this5.callback.setItems(_this5.items);\n }\n case 14:\n _context.next = 19;\n break;\n case 16:\n _context.prev = 16;\n _context.t0 = _context[\"catch\"](5);\n console.error('Error uploading file:', _context.t0);\n case 19:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[5, 16]]);\n }));\n return function (_x) {\n return _ref3.apply(this, arguments);\n };\n }());\n input.click();\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SocialIconsControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SocialIconsControl.js?");
/***/ }),
/***/ "./src/includes/SocialIconsElement.js":
/*!********************************************!*\
!*** ./src/includes/SocialIconsElement.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _SocialIconsControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./SocialIconsControl.js */ \"./src/includes/SocialIconsControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\nvar SocialIconsElement = /*#__PURE__*/function (_BaseElement) {\n function SocialIconsElement(template, items) {\n var _this2;\n _classCallCheck(this, SocialIconsElement);\n // [{image_LINK: '', link: '', label: '' }, ]\n _this2 = _callSuper(this, SocialIconsElement); // Call the parent class constructor\n _this2.template = template;\n _this2.items = items;\n\n // required keys for the element template\n _this2.requiredTemplateKeys = ['items'];\n\n // Formatter\n _this2.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]({\n background_color: null,\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n // padding\n padding_top: null,\n padding_right: null,\n padding_bottom: null,\n padding_left: null\n });\n\n // more settings\n _this2.size = 30;\n _this2.gap = 10;\n _this2.align = 'center';\n return _this2;\n }\n _inherits(SocialIconsElement, _BaseElement);\n return _createClass(SocialIconsElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.social_icons');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c). Resolve relative image URLs to absolute.\n var _this = this;\n this.domNode.innerHTML = this.renderTemplate({\n items: this.items.map(function (item) {\n return _objectSpread(_objectSpread({}, item), {}, {\n image_url: _this.transferMediaAbsUrl(item.image_url)\n });\n }),\n size: this.size,\n gap: this.gap,\n align: this.align\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(SocialIconsElement, \"getData\", this, 3)([])), {}, {\n items: this.items,\n size: this.size,\n gap: this.gap,\n align: this.align\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this3 = this;\n var _this = this;\n return [new _SocialIconsControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](\n // \n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.icons_items_list'),\n // current items\n this.items.map(function (item) {\n return {\n image_url: _this.transferMediaAbsUrl(item.image_url),\n // transform relative url to absolutes one\n label: item.label,\n url: item.link\n // description: null\n };\n }),\n // icons packs — getControls() runs post-mount, so this.host is\n // guaranteed set; transferMediaAbsUrl resolves relative theme\n // asset paths to per-instance absolute URLs.\n {\n facebook: {\n label: 'Facebook',\n url: 'https://facebook.com',\n image_url: _this.transferMediaAbsUrl('master/assets/image/icons/facebook.png')\n },\n twitter: {\n label: 'Twitter',\n url: 'https://twitter.com',\n image_url: _this.transferMediaAbsUrl('master/assets/image/icons/twitter.png')\n },\n instagram: {\n label: 'Instagram',\n url: 'https://instagram.com',\n image_url: _this.transferMediaAbsUrl('master/assets/image/icons/instagram.png')\n },\n linkedin: {\n label: 'LinkedIn',\n url: 'https://linkedin.com',\n image_url: _this.transferMediaAbsUrl('master/assets/image/icons/linkedin.png')\n },\n youtube: {\n label: 'YouTube',\n url: 'https://youtube.com',\n image_url: _this.transferMediaAbsUrl('master/assets/image/icons/youtube.png')\n },\n pinterest: {\n label: 'Pinterest',\n url: 'https://pinterest.com',\n image_url: _this.transferMediaAbsUrl('master/assets/image/icons/pinterest.png')\n },\n tiktok: {\n label: 'TikTok',\n url: 'https://tiktok.com',\n image_url: _this.transferMediaAbsUrl('master/assets/image/icons/tiktok.png')\n }\n },\n // callback\n {\n setItems: function setItems(items) {\n _this.items = items.map(function (item) {\n return {\n image_url: item.image_url,\n label: item.label,\n link: item.url\n };\n });\n _this.render();\n } // more callbacks\n }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.align, {\n setValue: function setValue(value) {\n _this3.align = value;\n _this3.render();\n }\n }, ['left', 'center', 'right']), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.icon_gap'), this.gap, {\n setValue: function setValue(value) {\n _this3.gap = value;\n _this3.render();\n }\n }, {\n defaultValue: 16,\n minValue: 0,\n maxValue: 200,\n suffix: 'px',\n allowZero: false\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.icon_size'), this.size, {\n setValue: function setValue(value) {\n _this3.size = value;\n _this3.render();\n }\n }, {\n defaultValue: 16,\n minValue: 8,\n maxValue: 200,\n suffix: 'px',\n allowZero: false\n })\n\n // W3.8b — PaddingMarginControl removed. Social icons are\n // content inside a Block; parent Block.padding handles layout.\n ];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var items = Array.isArray(data.items) ? data.items : [];\n var el = new SocialIconsElement(data.template, items);\n el.size = data.size || 30;\n el.gap = data.gap || 10;\n el.align = data.align || 'center';\n return this.parseFormats(el, data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SocialIconsElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SocialIconsElement.js?");
/***/ }),
/***/ "./src/includes/StyleControl.js":
/*!**************************************!*\
!*** ./src/includes/StyleControl.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * StyleControl — compact trigger button + popover with thumbnail tiles.\n *\n * The panel row shows a current-style button (label + mini thumb + chevron).\n * Click opens a popover with all available styles rendered in a 3-column\n * grid of small (~80px) thumbnail tiles. Selecting a tile closes the popover.\n *\n * Keyboard: Enter/Space opens the dropdown, Arrow keys navigate tiles, Enter\n * selects and closes, Esc closes. ARIA: trigger=button w/ aria-haspopup,\n * popover=radiogroup with aria-checked on the current tile.\n *\n * Used by: PricingCardsElement (10 style presets). Reusable for any \"pick a\n * visual variant\" situation where compact panel space matters.\n */\nvar StyleControl = /*#__PURE__*/function () {\n function StyleControl(label, value, options, callback) {\n var config = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};\n _classCallCheck(this, StyleControl);\n this.label = label;\n this.value = value;\n this.options = Array.isArray(options) ? options : [];\n this.callback = callback;\n this.isOpen = false;\n this.id = '_' + Math.random().toString(36).slice(2, 9);\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-style-control');\n this._documentClickHandler = null;\n this._documentKeydownHandler = null;\n this.render();\n }\n return _createClass(StyleControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var current = this._currentOption();\n var currentLabel = current ? current.label : _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.style_label');\n var currentThumb = current ? current.thumb : '';\n\n // Inline caret SVG — avoids Material Symbols font dependency\n var caretSvg = '<svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" aria-hidden=\"true\" style=\"display:block\"><path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>';\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <label class=\\\"bjs-control-label\\\">\".concat(this._esc(this.label), \"</label>\\n <div class=\\\"bjs-control-input\\\">\\n <button\\n type=\\\"button\\\"\\n class=\\\"bjs-style-trigger\\\"\\n aria-haspopup=\\\"listbox\\\"\\n aria-expanded=\\\"\").concat(this.isOpen ? 'true' : 'false', \"\\\"\\n data-control=\\\"style-trigger\\\"\\n id=\\\"style-trigger-\").concat(this.id, \"\\\"\\n >\\n <span class=\\\"bjs-style-trigger-thumb\\\" aria-hidden=\\\"true\\\">\").concat(currentThumb, \"</span>\\n <span class=\\\"bjs-style-trigger-label\\\">\").concat(this._esc(currentLabel), \"</span>\\n <span class=\\\"bjs-style-trigger-caret\\\" aria-hidden=\\\"true\\\">\").concat(caretSvg, \"</span>\\n </button>\\n </div>\\n </div>\\n <div\\n class=\\\"bjs-style-popover\").concat(this.isOpen ? ' is-open' : '', \"\\\"\\n role=\\\"radiogroup\\\"\\n aria-labelledby=\\\"style-trigger-\").concat(this.id, \"\\\"\\n data-control=\\\"style-popover\\\"\\n >\\n \").concat(this.options.map(function (opt) {\n var checked = opt.key === _this.value ? 'true' : 'false';\n return \"\\n <button\\n type=\\\"button\\\"\\n class=\\\"bjs-style-tile\\\"\\n role=\\\"radio\\\"\\n aria-checked=\\\"\".concat(checked, \"\\\"\\n data-key=\\\"\").concat(_this._esc(opt.key), \"\\\"\\n tabindex=\\\"\").concat(checked === 'true' ? '0' : '-1', \"\\\"\\n >\\n <span class=\\\"bjs-style-tile-thumb\\\" aria-hidden=\\\"true\\\">\").concat(opt.thumb || '', \"</span>\\n <span class=\\\"bjs-style-tile-label\\\">\").concat(_this._esc(opt.label), \"</span>\\n </button>\\n \");\n }).join(''), \"\\n </div>\\n \");\n this._bind();\n }\n }, {\n key: \"_currentOption\",\n value: function _currentOption() {\n var _this2 = this;\n return this.options.find(function (o) {\n return o.key === _this2.value;\n }) || this.options[0] || null;\n }\n }, {\n key: \"_bind\",\n value: function _bind() {\n var _this3 = this;\n var trigger = this.domNode.querySelector('[data-control=\"style-trigger\"]');\n var popover = this.domNode.querySelector('[data-control=\"style-popover\"]');\n if (!trigger || !popover) return;\n trigger.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this3._toggle();\n });\n var tiles = Array.from(popover.querySelectorAll('.bjs-style-tile'));\n tiles.forEach(function (tile, idx) {\n tile.addEventListener('click', function (e) {\n e.preventDefault();\n _this3._select(tile.dataset.key);\n _this3._close();\n });\n tile.addEventListener('keydown', function (e) {\n var cols = 3;\n var target = null;\n if (e.key === 'ArrowRight') target = tiles[(idx + 1) % tiles.length];else if (e.key === 'ArrowLeft') target = tiles[(idx - 1 + tiles.length) % tiles.length];else if (e.key === 'ArrowDown') target = tiles[Math.min(idx + cols, tiles.length - 1)];else if (e.key === 'ArrowUp') target = tiles[Math.max(idx - cols, 0)];else if (e.key === 'Enter' || e.key === ' ') {\n _this3._select(tile.dataset.key);\n _this3._close();\n e.preventDefault();\n return;\n } else if (e.key === 'Escape') {\n _this3._close();\n trigger.focus();\n e.preventDefault();\n return;\n }\n if (target) {\n e.preventDefault();\n target.focus();\n }\n });\n });\n }\n }, {\n key: \"_toggle\",\n value: function _toggle() {\n if (this.isOpen) this._close();else this._open();\n }\n }, {\n key: \"_open\",\n value: function _open() {\n var _this4 = this;\n this.isOpen = true;\n this.render();\n // Focus current tile for keyboard users\n var active = this.domNode.querySelector('.bjs-style-tile[aria-checked=\"true\"]') || this.domNode.querySelector('.bjs-style-tile');\n if (active) active.focus();\n\n // Outside click / Esc to close\n this._documentClickHandler = function (e) {\n if (!_this4.domNode.contains(e.target)) _this4._close();\n };\n this._documentKeydownHandler = function (e) {\n if (e.key === 'Escape') _this4._close();\n };\n document.addEventListener('click', this._documentClickHandler);\n document.addEventListener('keydown', this._documentKeydownHandler);\n }\n }, {\n key: \"_close\",\n value: function _close() {\n if (!this.isOpen) return;\n this.isOpen = false;\n this.render();\n if (this._documentClickHandler) document.removeEventListener('click', this._documentClickHandler);\n if (this._documentKeydownHandler) document.removeEventListener('keydown', this._documentKeydownHandler);\n this._documentClickHandler = null;\n this._documentKeydownHandler = null;\n }\n }, {\n key: \"_select\",\n value: function _select(key) {\n if (this.value === key) return;\n this.value = key;\n this.callback && this.callback.setValue && this.callback.setValue(key);\n // Trigger + tiles will be fresh on next render (invoked by _close)\n }\n }, {\n key: \"setValue\",\n value: function setValue(value) {\n this.value = value;\n this.render();\n }\n }, {\n key: \"_esc\",\n value: function _esc(s) {\n return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''');\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (StyleControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/StyleControl.js?");
/***/ }),
/***/ "./src/includes/StylePickerControl.js":
/*!********************************************!*\
!*** ./src/includes/StylePickerControl.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseControl_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BaseControl.js */ \"./src/includes/BaseControl.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\n/* harmony import */ var _buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./buttonPresets.js */ \"./src/includes/buttonPresets.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * StylePickerControl — compound sidebar control rendering a \"Style\"\n * preview card (preset thumbnail + name + category + Change button).\n * The Change button enters the element's 'style-picker' edit mode so\n * `ButtonPresetPickerOverlay` mounts as an anchored popover next to\n * the (newly stashed) anchor rect.\n *\n * Sits in the FIRST slot of `ButtonElement.getControls()` so the user\n * sees a one-click identity swap before the granular size / radius /\n * shadow / hover / icon / width modifier rows. The click anchor is the\n * Change button itself — `_lastActionAnchorRect` stash mirrors how\n * `ButtonActionsOverlay._openLinkEditor` anchors the LinkPopover.\n *\n * Dual-view sync (SA I13)\n * ───────────────────────\n * The element's `notifySyncListeners()` fires whenever preset_id /\n * size_key / shadow / hover_effect / icon mutate (from the picker\n * overlay, programmatic loads, etc.). We subscribe via the standard\n * capability-token pattern so the summary card stays consistent\n * without a full `renderElementControls()` rebuild.\n *\n * Destroy\n * ───────\n * Extends BaseControl → addDisposer registers the subscribe-token\n * teardown. `Builder.renderElementControls` calls destroy() on every\n * outgoing control before rebuilding, so the listener auto-cleans\n * when the user selects a different element.\n */\n\n\n\n\n\nvar StylePickerControl = /*#__PURE__*/function (_BaseControl) {\n function StylePickerControl(element) {\n var _this;\n _classCallCheck(this, StylePickerControl);\n _this = _callSuper(this, StylePickerControl);\n _this.id = '_' + Math.random().toString(36).substr(2, 9);\n _this.element = element;\n _this.domNode = document.createElement('div');\n _this.render();\n\n // Re-render on element-side preset / size / shadow / hover / icon mutations\n // so the summary card always reflects current state.\n _this.bindSyncListener(element, 'StylePickerControl:' + _this.id, function () {\n _this._refresh();\n });\n return _this;\n }\n\n /* ─── Public API ─── */\n _inherits(StylePickerControl, _BaseControl);\n return _createClass(StylePickerControl, [{\n key: \"setValue\",\n value: function setValue() {/* no-op — this control reads off the element directly */}\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.element ? this.element.preset_id : null;\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n /* ─── Internals ─── */\n }, {\n key: \"_currentPreset\",\n value: function _currentPreset() {\n var id = this.element && this.element.preset_id;\n return (0,_buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__.findPreset)(id);\n }\n }, {\n key: \"_categoryLabel\",\n value: function _categoryLabel(catId) {\n var cat = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__.CATEGORIES.find(function (c) {\n return c.id === catId;\n });\n return cat ? cat.label : catId;\n }\n }, {\n key: \"_summaryLine\",\n value: function _summaryLine(preset) {\n if (!preset) {\n // No preset applied — element is on raw formatter values\n return _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.style.custom_summary', 'Custom · advanced');\n }\n var cat = this._categoryLabel(preset.category);\n var size = this.element && this.element.size_key || 'md';\n // Compact format — keeps the truncation ellipsis at bay in the\n // narrow .bp-style-meta column. \"Solid · LG\" reads cleaner than\n // \"Solid · LG size\" once truncated.\n return \"\".concat(cat, \" \\xB7 \").concat(size.toUpperCase());\n }\n }, {\n key: \"_name\",\n value: function _name(preset) {\n if (!preset) return _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.style.custom_name', 'Custom');\n return preset.label;\n }\n\n /**\n * Render the live preview thumbnail for the Style summary card.\n *\n * IMPORTANT: reads from `element.formatter.formats` (LIVE state),\n * NOT from `preset.formats` (preset's original snapshot). This way\n * any per-button customisation (custom border, hand-tuned color,\n * Advanced-section override, picking an already-customised button on\n * the page, etc.) is faithfully reflected in the sidebar preview.\n * The preset object is only consulted for icon/iconPosition + name —\n * the actual paint always tracks the live formatter.\n *\n * Edge case (`preset == null`) — element has no preset_id (raw / fully\n * custom). We STILL use the live formatter, just label it \"Custom\" via\n * the meta line. The thumbnail stays accurate.\n */\n }, {\n key: \"_renderThumb\",\n value: function _renderThumb(preset) {\n var text = this.element && this.element.text || 'Click Me';\n var f = this.element && this.element.formatter && this.element.formatter.formats || {};\n var icon = this.element && this.element.icon || preset && preset.icon || null;\n var iconPosition = this.element && this.element.icon_position || preset && preset.iconPosition || 'none';\n var styleParts = [f.background_image ? \"background:\".concat(f.background_image) : \"background:\".concat(f.background_color || '#2563eb'), f.background_color ? \"background-color:\".concat(f.background_color) : '', \"color:\".concat(f.text_color || '#fff'), f.border_top_color ? \"border:\".concat(f.border_top_width || '1px', \" \").concat(f.border_top_style || 'solid', \" \").concat(f.border_top_color) : 'border:0', \"border-radius:\".concat(f.border_radius || '6px'), f.box_shadow ? \"box-shadow:\".concat(f.box_shadow) : '', f.font_weight ? \"font-weight:\".concat(f.font_weight) : 'font-weight:500', 'font-size:12px', 'padding:4px 10px', 'text-decoration:none', 'display:inline-block', 'line-height:1.4', 'max-width:100%', 'overflow:hidden', 'text-overflow:ellipsis', 'white-space:nowrap'].filter(Boolean).join(';');\n\n // Icon side-margin picks `margin-left` for right-position and\n // `margin-right` for left-position so text always has breathing\n // room on the icon side. 8px matches the picker-cell spacing.\n var iconLeftHtml = icon ? \"<span class=\\\"bp-thumb-icon\\\" aria-hidden=\\\"true\\\" style=\\\"display:inline-flex;vertical-align:middle;margin-right:8px\\\">\".concat(_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render(icon, {\n size: 14,\n color: 'currentColor'\n }), \"</span>\") : '';\n var iconRightHtml = icon ? \"<span class=\\\"bp-thumb-icon\\\" aria-hidden=\\\"true\\\" style=\\\"display:inline-flex;vertical-align:middle;margin-left:8px\\\">\".concat(_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render(icon, {\n size: 14,\n color: 'currentColor'\n }), \"</span>\") : '';\n var iconOnlyHtml = icon ? \"<span class=\\\"bp-thumb-icon\\\" aria-hidden=\\\"true\\\" style=\\\"display:inline-flex;vertical-align:middle\\\">\".concat(_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render(icon, {\n size: 14,\n color: 'currentColor'\n }), \"</span>\") : '';\n\n // `text` is passed through innerHTML (not escaped) so HTML entities\n // like and user-authored inline markup match the rendered\n // <a> in the iframe. EJS <%- text %> in Button.template.html is\n // ALSO raw HTML → identical parsing here keeps picker/sidebar\n // WYSIWYG-accurate.\n var labelHtml;\n if (icon && iconPosition === 'only') {\n labelHtml = iconOnlyHtml;\n } else if (icon && iconPosition === 'right') {\n labelHtml = \"\".concat(text).concat(iconRightHtml);\n } else if (icon && iconPosition === 'left') {\n labelHtml = \"\".concat(iconLeftHtml).concat(text);\n } else {\n labelHtml = text;\n }\n return \"<a class=\\\"bp-thumb-spec\\\" style=\\\"\".concat(styleParts, \"\\\">\").concat(labelHtml, \"</a>\");\n }\n }, {\n key: \"_escape\",\n value: function _escape(s) {\n return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this2 = this;\n var preset = this._currentPreset();\n var tooltip = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.style.change_tooltip', 'Browse all styles');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row bjs-control-row--wide\\\">\\n <div class=\\\"bjs-control-label\\\"><span>\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.style.label', 'Style'), \"</span></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bp-style-summary\\\" data-bjs-style-summary>\\n <div class=\\\"bp-style-thumb\\\" data-bjs-style-thumb>\").concat(this._renderThumb(preset), \"</div>\\n <div class=\\\"bp-style-meta\\\">\\n <div class=\\\"bp-style-name\\\" data-bjs-style-name>\").concat(this._escape(this._name(preset)), \"</div>\\n <div class=\\\"bp-style-cat\\\" data-bjs-style-cat >\").concat(this._escape(this._summaryLine(preset)), \"</div>\\n </div>\\n <button type=\\\"button\\\" class=\\\"bp-style-change\\\" data-bjs-style-change\\n data-tooltip=\\\"\").concat(this._escape(tooltip), \"\\\" aria-label=\\\"\").concat(this._escape(tooltip), \"\\\">\\n <span class=\\\"bp-style-change-icon\\\" aria-hidden=\\\"true\\\">\").concat(_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render('palette', {\n size: 18,\n color: 'currentColor'\n }), \"</span>\\n </button>\\n </div>\\n </div>\\n </div>\\n \");\n var changeBtn = this.domNode.querySelector('[data-bjs-style-change]');\n if (changeBtn) {\n changeBtn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this2._openPicker(e);\n });\n }\n }\n }, {\n key: \"_refresh\",\n value: function _refresh() {\n // Cheap path: patch only the thumb / name / category text so the\n // Change button + its anchor don't churn (any in-flight click\n // animation stays intact).\n var preset = this._currentPreset();\n var thumb = this.domNode.querySelector('[data-bjs-style-thumb]');\n var name = this.domNode.querySelector('[data-bjs-style-name]');\n var cat = this.domNode.querySelector('[data-bjs-style-cat]');\n if (thumb) thumb.innerHTML = this._renderThumb(preset);\n if (name) name.textContent = this._name(preset);\n if (cat) cat.textContent = this._summaryLine(preset);\n }\n }, {\n key: \"_openPicker\",\n value: function _openPicker(e) {\n if (!this.element) return;\n // Stash the click rect — ButtonPresetPickerOverlay reads\n // `_lastActionAnchorRect` to anchor next to whichever surface\n // opened it (sidebar Change button OR action-bar palette pill).\n var target = e.currentTarget;\n if (target && typeof target.getBoundingClientRect === 'function') {\n this.element._lastActionAnchorRect = target.getBoundingClientRect();\n } else {\n this.element._lastActionAnchorRect = null;\n }\n if (typeof this.element.enterEditMode === 'function') {\n this.element.enterEditMode('style-picker');\n }\n }\n }]);\n}(_BaseControl_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (StylePickerControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/StylePickerControl.js?");
/***/ }),
/***/ "./src/includes/SubmitButtonElement.js":
/*!*********************************************!*\
!*** ./src/includes/SubmitButtonElement.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar SubmitButtonElement = /*#__PURE__*/function (_BaseElement) {\n function SubmitButtonElement(template, text) {\n var _this;\n _classCallCheck(this, SubmitButtonElement);\n _this = _callSuper(this, SubmitButtonElement);\n _this.template = template;\n _this.text = text;\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['text'];\n\n // Inline edit\n // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n _this.registerInlineEdit('text');\n\n // Formatter - Bootstrap button default styles\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_14__[\"default\"]({\n // align\n align: 'left',\n // text styles\n font_family: \"inherit\",\n font_weight: \"400\",\n font_size: \"16px\",\n text_color: \"#ffffff\",\n link_color: \"#ffffff\",\n paragraph_spacing: null,\n text_align: 'center',\n // left, center, right,\n line_height: \"1.5\",\n letter_spacing: null,\n text_direction: \"ltr\",\n // ltr, rtl\n\n // background - Bootstrap primary button\n background_color: \"#0d6efd\",\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n // spacing - Bootstrap button padding\n padding_top: 6,\n padding_right: 12,\n padding_bottom: 6,\n padding_left: 12,\n // border - Bootstrap button border\n border_top_style: \"solid\",\n border_top_width: \"1px\",\n border_top_color: \"#0d6efd\",\n border_right_style: \"solid\",\n border_right_width: \"1px\",\n border_right_color: \"#0d6efd\",\n border_bottom_style: \"solid\",\n border_bottom_width: \"1px\",\n border_bottom_color: \"#0d6efd\",\n border_left_width: \"1px\",\n border_left_style: \"solid\",\n border_left_color: \"#0d6efd\",\n // border radius - Bootstrap button radius\n border_radius: \"0.375rem\",\n // sizing\n width: null,\n max_width: null,\n min_width: null\n });\n return _this;\n }\n _inherits(SubmitButtonElement, _BaseElement);\n return _createClass(SubmitButtonElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.submit_button');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter + text auto-merged (W0.2c); inline-edit auto-wires (W0.2b)\n this.domNode.innerHTML = this.renderTemplate({});\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(SubmitButtonElement, \"getData\", this, 3)([])), {}, {\n text: this.text\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this,\n _this$host;\n // W3.1 — bus wiring for dual-view sync with FontPopoverOverlay.\n var busOpts = function busOpts(key) {\n var _this2$host;\n return {\n bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n elementUid: _this2.id,\n formatterKey: key\n };\n };\n return [\n // TextControl\n new _TextControl_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text'), this.text, {\n setText: function setText(text) {\n _this2.text = text;\n _this2.render();\n }\n }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('align'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('align', value);\n _this2.render();\n }\n }, ['left', 'center', 'right']), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('font_family', value);\n _this2.render();\n }\n }, busOpts('font_family')), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('font_weight', value);\n _this2.render();\n }\n }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('font_size', value);\n _this2.render();\n }\n }, _objectSpread({\n defaultValue: 16,\n minValue: 8,\n maxValue: 72,\n suffix: 'px',\n allowZero: false\n }, busOpts('font_size'))), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('text_color', value);\n _this2.render();\n }\n }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('link_color', value);\n _this2.render();\n }\n }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_alignment'), this.formatter.getFormat('text_align'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('text_align', value);\n _this2.render();\n }\n }, ['left', 'justify', 'center', 'right'], {\n bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n elementUid: this.id,\n formatterKey: 'text_align'\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('paragraph_spacing', value);\n _this2.render();\n }\n }, {\n defaultValue: 0,\n minValue: 0,\n maxValue: 50,\n suffix: 'px',\n allowZero: true\n }), new _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('line_height', value);\n _this2.render();\n }\n }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('letter_spacing', value);\n _this2.render();\n }\n }, {\n defaultValue: 0,\n minValue: -5,\n maxValue: 10,\n step: 0.1,\n suffix: 'px',\n allowZero: true,\n allowNegative: true\n }), new _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n setValue: function setValue(value) {\n _this2.formatter.setFormat('text_direction', value);\n _this2.render();\n }\n }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n color: this.formatter.getFormat('background_color'),\n image: this.formatter.getFormat('background_image'),\n position: this.formatter.getFormat('background_position'),\n size: this.formatter.getFormat('background_size'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n }, {\n setBackground: function setBackground(values) {\n _this2.formatter.setFormat('background_color', values.color);\n _this2.formatter.setFormat('background_image', values.image);\n _this2.formatter.setFormat('background_position', values.position);\n _this2.formatter.setFormat('background_size', values.size);\n _this2.formatter.setFormat('background_repeat', values.repeat);\n _this2.render();\n }\n }, {\n features: ['color', 'image', 'size', 'repeat', 'gradient']\n }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style'),\n border_top_width: this.formatter.getFormat('border_top_width'),\n border_top_color: this.formatter.getFormat('border_top_color'),\n border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n border_left_style: this.formatter.getFormat('border_left_style'),\n border_left_width: this.formatter.getFormat('border_left_width'),\n border_left_color: this.formatter.getFormat('border_left_color'),\n border_right_style: this.formatter.getFormat('border_right_style'),\n border_right_width: this.formatter.getFormat('border_right_width'),\n border_right_color: this.formatter.getFormat('border_right_color')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this2.formatter.setFormat('border_top_style', border_top_style);\n _this2.formatter.setFormat('border_top_width', border_top_width);\n _this2.formatter.setFormat('border_top_color', border_top_color);\n _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this2.formatter.setFormat('border_left_style', border_left_style);\n _this2.formatter.setFormat('border_left_width', border_left_width);\n _this2.formatter.setFormat('border_left_color', border_left_color);\n _this2.formatter.setFormat('border_right_style', border_right_style);\n _this2.formatter.setFormat('border_right_width', border_right_width);\n _this2.formatter.setFormat('border_right_color', border_right_color);\n\n // re-render\n _this2.render();\n }\n }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n setRadius: function setRadius(v) {\n _this2.formatter.setFormat('border_radius', v);\n _this2.render();\n }\n }),\n // W3.8b — InnerPaddingControl (intrinsic shape).\n new InnerPaddingControl(\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.button_padding'),\n // value\n {\n top: this.formatter.getFormat('padding_top'),\n right: this.formatter.getFormat('padding_right'),\n bottom: this.formatter.getFormat('padding_bottom'),\n left: this.formatter.getFormat('padding_left')\n },\n // callback\n {\n setValues: function setValues(values) {\n _this2.formatter.setFormat('padding_top', values.top);\n _this2.formatter.setFormat('padding_right', values.right);\n _this2.formatter.setFormat('padding_bottom', values.bottom);\n _this2.formatter.setFormat('padding_left', values.left);\n _this2.render();\n }\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.text), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SubmitButtonElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SubmitButtonElement.js?");
/***/ }),
/***/ "./src/includes/TabsManager.js":
/*!*************************************!*\
!*** ./src/includes/TabsManager.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar TabsManager = /*#__PURE__*/function () {\n function TabsManager() {\n _classCallCheck(this, TabsManager);\n this.groups = [];\n }\n return _createClass(TabsManager, [{\n key: \"addTab\",\n value: function addTab(tab, container) {\n var _this = this;\n this.groups.push({\n tab: tab,\n container: container\n });\n\n // event\n tab.addEventListener('click', function () {\n _this.openTab(tab);\n });\n }\n }, {\n key: \"openTab\",\n value: function openTab(tab) {\n this.groups.forEach(function (group) {\n if (group.tab === tab) {\n group.tab.classList.add('active');\n group.container.style.display = 'block';\n } else {\n group.tab.classList.remove('active');\n group.container.style.display = 'none';\n }\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TabsManager);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TabsManager.js?");
/***/ }),
/***/ "./src/includes/TermsConfigControl.js":
/*!********************************************!*\
!*** ./src/includes/TermsConfigControl.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * TermsConfigControl — dedicated rich control for TermsOfServiceElement.\n *\n * Bundles every compliance-shaping knob (terms body via inline edit, checkbox\n * label, required toggle, checkbox position, custom validation message) into\n * one panel section so the gate-defining UX is visually grouped and stands\n * apart from the generic styling stack underneath.\n *\n * Conditional UI:\n * • When checkboxPosition is `inline_left` / `inline_right` the checkbox\n * sits next to the terms text and uses the text itself as its label —\n * the dedicated \"Checkbox label\" input is hidden in that mode (its\n * value is preserved on the model so toggling back to below/above\n * restores it).\n *\n * Callback contract:\n * callback.setValues({ termsText?, checkboxLabel?, required?,\n * checkboxPosition?, errorMessage? })\n * The element merges + re-renders; only present keys are applied.\n */\nvar TermsConfigControl = /*#__PURE__*/function () {\n function TermsConfigControl(label, value, callback) {\n _classCallCheck(this, TermsConfigControl);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = {\n termsText: value && value.termsText != null ? String(value.termsText) : '',\n checkboxLabel: value && value.checkboxLabel != null ? String(value.checkboxLabel) : '',\n required: !!(value && value.required),\n checkboxPosition: TermsConfigControl.POSITIONS.includes(value && value.checkboxPosition) ? value.checkboxPosition : 'below',\n errorMessage: value && typeof value.errorMessage === 'string' ? value.errorMessage : ''\n };\n this.callback = callback;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-terms-config-control');\n this._labelDebounce = null;\n this._errorDebounce = null;\n this.render();\n }\n return _createClass(TermsConfigControl, [{\n key: \"render\",\n value: function render() {\n var _this$value$checkboxL, _this$value$errorMess;\n var escapeAttr = function escapeAttr(s) {\n return String(s == null ? '' : s).replace(/\"/g, '"');\n };\n var escapeText = function escapeText(s) {\n return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n };\n var presets = TermsConfigControl.getPresets();\n var presetButtons = presets.map(function (p) {\n return \"\\n <button type=\\\"button\\\"\\n class=\\\"bjs-segmented-btn\\\"\\n data-preset=\\\"\".concat(escapeAttr(p.id), \"\\\"\\n role=\\\"radio\\\"\\n aria-checked=\\\"false\\\"\\n tabindex=\\\"-1\\\">\\n \").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(p.labelKey)), \"\\n </button>\\n \");\n }).join('');\n var positions = TermsConfigControl.getPositions();\n var positionButtons = positions.map(function (p) {\n return \"\\n <button type=\\\"button\\\"\\n class=\\\"bjs-segmented-btn\\\"\\n data-position=\\\"\".concat(escapeAttr(p.id), \"\\\"\\n role=\\\"radio\\\"\\n aria-checked=\\\"false\\\"\\n tabindex=\\\"-1\\\">\\n \").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(p.labelKey)), \"\\n </button>\\n \");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-stack bjs-terms-config-control__head\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label><span>\".concat(escapeText(this.label), \"</span></label>\\n <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_settings_help')), \"</span>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-stack bjs-terms-config-control__preset\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_preset_label')), \"</span></label>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-segmented\\\" data-group=\\\"preset\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_preset_label')), \"\\\">\\n \").concat(presetButtons, \"\\n </div>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-stack bjs-terms-config-control__position\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_position_label')), \"</span></label>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-segmented\\\" data-group=\\\"position\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_position_label')), \"\\\">\\n \").concat(positionButtons, \"\\n </div>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-stack bjs-terms-config-control__label-row\\\" data-row=\\\"checkbox-label\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"terms_label_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.checkbox_label')), \"</span></label>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input id=\\\"terms_label_\").concat(this.id, \"\\\" type=\\\"text\\\" class=\\\"bjs-text-input\\\" />\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-row bjs-terms-config-control__required-row\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"terms_required_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_required')), \"</span></label>\\n <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_required_help')), \"</span>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <label class=\\\"bjs-toggle\\\">\\n <input id=\\\"terms_required_\").concat(this.id, \"\\\" type=\\\"checkbox\\\" class=\\\"bjs-toggle-input\\\" />\\n <span class=\\\"bjs-toggle-track\\\"><span class=\\\"bjs-toggle-thumb\\\"></span></span>\\n </label>\\n </div>\\n </div>\\n\\n <div class=\\\"bjs-control-stack bjs-terms-config-control__error-row\\\" data-row=\\\"error-message\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"terms_error_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_error_message')), \"</span></label>\\n <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_error_message_help')), \"</span>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <input id=\\\"terms_error_\").concat(this.id, \"\\\"\\n type=\\\"text\\\"\\n class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_error_message_placeholder')), \"\\\" />\\n </div>\\n </div>\\n\\n <p class=\\\"bjs-terms-config-control__hint\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_inline_hint')), \"</p>\\n \");\n\n // Hydrate inputs from current value\n this._labelInput().value = (_this$value$checkboxL = this.value.checkboxLabel) !== null && _this$value$checkboxL !== void 0 ? _this$value$checkboxL : '';\n this._requiredInput().checked = !!this.value.required;\n this._errorInput().value = (_this$value$errorMess = this.value.errorMessage) !== null && _this$value$errorMess !== void 0 ? _this$value$errorMess : '';\n this._syncPresetActive();\n this._syncPositionActive();\n this._syncConditionalRows();\n this._bindEvents();\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this = this;\n // Preset segmented buttons\n var presetGroup = this.domNode.querySelector('.bjs-segmented[data-group=\"preset\"]');\n if (presetGroup) {\n presetGroup.addEventListener('click', function (e) {\n var btn = e.target.closest('.bjs-segmented-btn');\n if (!btn || !presetGroup.contains(btn)) return;\n _this._applyPreset(btn.dataset.preset);\n });\n }\n\n // Position segmented buttons\n var positionGroup = this.domNode.querySelector('.bjs-segmented[data-group=\"position\"]');\n if (positionGroup) {\n positionGroup.addEventListener('click', function (e) {\n var btn = e.target.closest('.bjs-segmented-btn');\n if (!btn || !positionGroup.contains(btn)) return;\n _this._applyPosition(btn.dataset.position);\n });\n }\n\n // Checkbox-label input — debounced 200ms\n this._labelInput().addEventListener('input', function () {\n if (_this._labelDebounce) clearTimeout(_this._labelDebounce);\n _this._labelDebounce = setTimeout(function () {\n _this.value.checkboxLabel = _this._labelInput().value;\n _this._emit({\n checkboxLabel: _this.value.checkboxLabel\n });\n }, 200);\n });\n\n // Required toggle\n this._requiredInput().addEventListener('change', function (e) {\n _this.value.required = !!e.target.checked;\n _this._emit({\n required: _this.value.required\n });\n });\n\n // Custom error-message input — debounced 200ms\n this._errorInput().addEventListener('input', function () {\n if (_this._errorDebounce) clearTimeout(_this._errorDebounce);\n _this._errorDebounce = setTimeout(function () {\n _this.value.errorMessage = _this._errorInput().value;\n _this._emit({\n errorMessage: _this.value.errorMessage\n });\n }, 200);\n });\n }\n }, {\n key: \"_applyPreset\",\n value: function _applyPreset(presetId) {\n var preset = TermsConfigControl.getPresets().find(function (p) {\n return p.id === presetId;\n });\n if (!preset) return;\n var patch = {\n termsText: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(preset.textKey),\n checkboxLabel: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(preset.agreeKey),\n required: preset.required\n };\n // Reflect locally so subsequent re-renders show the new state\n this.value = _objectSpread(_objectSpread({}, this.value), patch);\n this._labelInput().value = patch.checkboxLabel;\n this._requiredInput().checked = patch.required;\n this._syncPresetActive(presetId);\n this._emit(patch);\n }\n }, {\n key: \"_applyPosition\",\n value: function _applyPosition(positionId) {\n if (!TermsConfigControl.POSITIONS.includes(positionId)) return;\n if (this.value.checkboxPosition === positionId) return;\n this.value.checkboxPosition = positionId;\n this._syncPositionActive();\n this._syncConditionalRows();\n this._emit({\n checkboxPosition: positionId\n });\n }\n }, {\n key: \"_syncPresetActive\",\n value: function _syncPresetActive() {\n var _this2 = this;\n var forcedId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n var group = this.domNode.querySelector('.bjs-segmented[data-group=\"preset\"]');\n if (!group) return;\n var presets = TermsConfigControl.getPresets();\n var matchId = forcedId;\n if (!matchId) {\n matchId = (presets.find(function (p) {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(p.textKey) === _this2.value.termsText;\n }) || {}).id || null;\n }\n group.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n var isActive = btn.dataset.preset === matchId;\n btn.classList.toggle('is-active', isActive);\n btn.setAttribute('aria-checked', isActive ? 'true' : 'false');\n btn.setAttribute('tabindex', isActive ? '0' : '-1');\n });\n }\n }, {\n key: \"_syncPositionActive\",\n value: function _syncPositionActive() {\n var group = this.domNode.querySelector('.bjs-segmented[data-group=\"position\"]');\n if (!group) return;\n var current = this.value.checkboxPosition;\n group.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n var isActive = btn.dataset.position === current;\n btn.classList.toggle('is-active', isActive);\n btn.setAttribute('aria-checked', isActive ? 'true' : 'false');\n btn.setAttribute('tabindex', isActive ? '0' : '-1');\n });\n }\n\n /**\n * Hide the checkbox-label row when the checkbox is inline with the terms\n * text — there's no separate label in that layout. Toggle visibility, do\n * NOT remove from DOM, so the value survives a position toggle round-trip.\n */\n }, {\n key: \"_syncConditionalRows\",\n value: function _syncConditionalRows() {\n var labelRow = this.domNode.querySelector('[data-row=\"checkbox-label\"]');\n if (!labelRow) return;\n var isInline = this.value.checkboxPosition === 'inline_left' || this.value.checkboxPosition === 'inline_right';\n labelRow.classList.toggle('is-hidden', isInline);\n }\n }, {\n key: \"_emit\",\n value: function _emit(patch) {\n if (this.callback && typeof this.callback.setValues === 'function') {\n this.callback.setValues(patch);\n }\n }\n }, {\n key: \"_labelInput\",\n value: function _labelInput() {\n return this.domNode.querySelector(\"#terms_label_\".concat(this.id));\n }\n }, {\n key: \"_requiredInput\",\n value: function _requiredInput() {\n return this.domNode.querySelector(\"#terms_required_\".concat(this.id));\n }\n }, {\n key: \"_errorInput\",\n value: function _errorInput() {\n return this.domNode.querySelector(\"#terms_error_\".concat(this.id));\n }\n }], [{\n key: \"getPresets\",\n value:\n /**\n * Preset boilerplate. Each preset replaces termsText + checkboxLabel and\n * sets the required flag. i18n keys are looked up at apply-time so locale\n * switches reseed correctly.\n */\n function getPresets() {\n return [{\n id: 'tos',\n labelKey: 'controls.terms_preset_tos',\n textKey: 'elements.terms_preset_tos_text',\n agreeKey: 'elements.terms_preset_tos_label',\n required: true\n }, {\n id: 'privacy',\n labelKey: 'controls.terms_preset_privacy',\n textKey: 'elements.terms_preset_privacy_text',\n agreeKey: 'elements.terms_preset_privacy_label',\n required: true\n }, {\n id: 'marketing',\n labelKey: 'controls.terms_preset_marketing',\n textKey: 'elements.terms_preset_marketing_text',\n agreeKey: 'elements.terms_preset_marketing_label',\n required: false\n }, {\n id: 'gdpr',\n labelKey: 'controls.terms_preset_gdpr',\n textKey: 'elements.terms_preset_gdpr_text',\n agreeKey: 'elements.terms_preset_gdpr_label',\n required: true\n }];\n }\n }, {\n key: \"getPositions\",\n value: function getPositions() {\n return [{\n id: 'below',\n labelKey: 'controls.terms_position_below'\n }, {\n id: 'above',\n labelKey: 'controls.terms_position_above'\n }, {\n id: 'inline_left',\n labelKey: 'controls.terms_position_inline_left'\n }, {\n id: 'inline_right',\n labelKey: 'controls.terms_position_inline_right'\n }];\n }\n }]);\n}();\n_defineProperty(TermsConfigControl, \"POSITIONS\", ['below', 'above', 'inline_left', 'inline_right']);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TermsConfigControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TermsConfigControl.js?");
/***/ }),
/***/ "./src/includes/TermsOfServiceElement.js":
/*!***********************************************!*\
!*** ./src/includes/TermsOfServiceElement.js ***!
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _TermsConfigControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./TermsConfigControl.js */ \"./src/includes/TermsConfigControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./InnerPaddingControl.js */ \"./src/includes/InnerPaddingControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * TermsOfServiceElement — compliance-gate widget for forms.\n *\n * Renders a block of legal/policy text + an \"I agree\" checkbox below it.\n * If `required` is true and the visitor submits without checking the box,\n * the host server (its form-controller + terms-acceptance rule set)\n * rejects the POST with a localized validation error.\n *\n * Singleton (v1): exactly one widget per form, fixed input name\n * `ACM_TERMS_ACCEPT`. Save-time validator (SaveFormBuilderRequest Rule 6)\n * rejects forms with >1 instance.\n */\nvar TermsOfServiceElement = /*#__PURE__*/function (_BaseElement) {\n function TermsOfServiceElement(template) {\n var _this;\n var termsText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';\n var checkboxLabel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';\n var required = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n var checkboxPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'below';\n var errorMessage = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : '';\n _classCallCheck(this, TermsOfServiceElement);\n _this = _callSuper(this, TermsOfServiceElement);\n _this.template = template;\n _this.termsText = termsText;\n _this.checkboxLabel = checkboxLabel;\n _this.required = required;\n _this.checkboxPosition = TermsOfServiceElement.CHECKBOX_POSITIONS.includes(checkboxPosition) ? checkboxPosition : 'below';\n // Custom validation message shown on the visitor-side jQuery validate\n // gate. Empty → fall through to jquery_validate_locale's default\n // (\"This field is required.\") which is already locale-aware.\n _this.errorMessage = errorMessage || '';\n // v1: reserved fixed name; the host server-side walker keys off this.\n _this.inputName = 'ACM_TERMS_ACCEPT';\n _this.domNode = null;\n _this.requiredTemplateKeys = ['termsText', 'checkboxLabel', 'inputName', 'checkboxPosition'];\n\n // Inline rich-text editing on the terms body — visitors can be linked\n // to the actual ToS URL via the inline link toolbar.\n _this.registerInlineEdit('termsText');\n\n // null defaults — let the page CSS cascade win, mirroring PElement.\n // This keeps dark themes legible without per-instance overrides.\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n font_family: null,\n font_weight: null,\n font_size: null,\n text_color: null,\n link_color: null,\n text_align: null,\n line_height: null,\n letter_spacing: null,\n background_color: null,\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n padding_top: null,\n padding_right: null,\n padding_bottom: null,\n padding_left: null,\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_style: null,\n border_left_width: null,\n border_left_color: null,\n border_radius: null\n });\n return _this;\n }\n\n // Webpack mangling guard — registry + JSON `name` field must be stable.\n _inherits(TermsOfServiceElement, _BaseElement);\n return _createClass(TermsOfServiceElement, [{\n key: \"getClassName\",\n value: function getClassName() {\n return 'TermsOfServiceElement';\n }\n }, {\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.terms_of_service');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n this.domNode.innerHTML = this.renderTemplate({\n termsText: this.termsText,\n checkboxLabel: this.checkboxLabel,\n inputName: this.inputName,\n required: this.required,\n checkboxPosition: this.checkboxPosition,\n errorMessage: this.errorMessage\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(TermsOfServiceElement, \"getData\", this, 3)([])), {}, {\n termsText: this.termsText,\n checkboxLabel: this.checkboxLabel,\n inputName: this.inputName,\n required: this.required,\n checkboxPosition: this.checkboxPosition,\n errorMessage: this.errorMessage\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this,\n _this$host;\n var setFmt = function setFmt(key) {\n return function (value) {\n _this2.formatter.setFormat(key, value);\n _this2.render();\n };\n };\n var busOpts = function busOpts(key) {\n var _this2$host;\n return {\n bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n elementUid: _this2.id,\n formatterKey: key\n };\n };\n return [new _TermsConfigControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_settings'), {\n termsText: this.termsText,\n checkboxLabel: this.checkboxLabel,\n required: this.required,\n checkboxPosition: this.checkboxPosition,\n errorMessage: this.errorMessage\n }, {\n setValues: function setValues(patch) {\n if ('termsText' in patch) _this2.termsText = patch.termsText;\n if ('checkboxLabel' in patch) _this2.checkboxLabel = patch.checkboxLabel;\n if ('required' in patch) _this2.required = !!patch.required;\n if ('checkboxPosition' in patch && TermsOfServiceElement.CHECKBOX_POSITIONS.includes(patch.checkboxPosition)) {\n _this2.checkboxPosition = patch.checkboxPosition;\n }\n if ('errorMessage' in patch) _this2.errorMessage = patch.errorMessage || '';\n _this2.render();\n }\n }), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n setValue: setFmt('font_family')\n }, busOpts('font_family')), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n setValue: setFmt('font_weight')\n }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n setValue: setFmt('font_size')\n }, _objectSpread({\n defaultValue: 14,\n minValue: 8,\n maxValue: 72,\n suffix: 'px',\n allowZero: false\n }, busOpts('font_size'))), new _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n setValue: setFmt('line_height')\n }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n setValue: setFmt('text_color')\n }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n setValue: setFmt('link_color')\n }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_alignment'), this.formatter.getFormat('text_align'), {\n setValue: setFmt('text_align')\n }, ['left', 'justify', 'center', 'right'], {\n bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n elementUid: this.id,\n formatterKey: 'text_align'\n }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n color: this.formatter.getFormat('background_color'),\n image: this.formatter.getFormat('background_image'),\n position: this.formatter.getFormat('background_position'),\n size: this.formatter.getFormat('background_size'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n }, {\n setBackground: function setBackground(values) {\n _this2.formatter.setFormat('background_color', values.color);\n _this2.formatter.setFormat('background_image', values.image);\n _this2.formatter.setFormat('background_position', values.position);\n _this2.formatter.setFormat('background_size', values.size);\n _this2.formatter.setFormat('background_repeat', values.repeat);\n _this2.render();\n }\n }, {\n features: ['color', 'image', 'size', 'repeat', 'gradient']\n }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style'),\n border_top_width: this.formatter.getFormat('border_top_width'),\n border_top_color: this.formatter.getFormat('border_top_color'),\n border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n border_left_style: this.formatter.getFormat('border_left_style'),\n border_left_width: this.formatter.getFormat('border_left_width'),\n border_left_color: this.formatter.getFormat('border_left_color'),\n border_right_style: this.formatter.getFormat('border_right_style'),\n border_right_width: this.formatter.getFormat('border_right_width'),\n border_right_color: this.formatter.getFormat('border_right_color')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this2.formatter.setFormat('border_top_style', border_top_style);\n _this2.formatter.setFormat('border_top_width', border_top_width);\n _this2.formatter.setFormat('border_top_color', border_top_color);\n _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this2.formatter.setFormat('border_left_style', border_left_style);\n _this2.formatter.setFormat('border_left_width', border_left_width);\n _this2.formatter.setFormat('border_left_color', border_left_color);\n _this2.formatter.setFormat('border_right_style', border_right_style);\n _this2.formatter.setFormat('border_right_width', border_right_width);\n _this2.formatter.setFormat('border_right_color', border_right_color);\n _this2.render();\n }\n }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n setRadius: function setRadius(v) {\n _this2.formatter.setFormat('border_radius', v);\n _this2.render();\n }\n }), new _InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.padding'), {\n top: this.formatter.getFormat('padding_top'),\n right: this.formatter.getFormat('padding_right'),\n bottom: this.formatter.getFormat('padding_bottom'),\n left: this.formatter.getFormat('padding_left')\n }, {\n setValues: function setValues(values) {\n _this2.formatter.setFormat('padding_top', values.top);\n _this2.formatter.setFormat('padding_right', values.right);\n _this2.formatter.setFormat('padding_bottom', values.bottom);\n _this2.formatter.setFormat('padding_left', values.left);\n _this2.render();\n }\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var instance = new this(data.template, data.termsText || '', data.checkboxLabel || '', data.required !== undefined ? !!data.required : true, data.checkboxPosition || 'below', typeof data.errorMessage === 'string' ? data.errorMessage : '');\n // inputName always reset to the reserved value, ignoring any saved\n // legacy/override (singleton invariant).\n instance.inputName = 'ACM_TERMS_ACCEPT';\n return this.parseFormats(instance, data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/**\n * Valid checkbox-position values. Any other string falls back to 'below'\n * via parse(), so legacy JSON written before this field shipped renders\n * identically.\n */\n_defineProperty(TermsOfServiceElement, \"CHECKBOX_POSITIONS\", ['below', 'above', 'inline_left', 'inline_right']);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TermsOfServiceElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TermsOfServiceElement.js?");
/***/ }),
/***/ "./src/includes/TermsOfServiceWidget.js":
/*!**********************************************!*\
!*** ./src/includes/TermsOfServiceWidget.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _TermsOfServiceElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TermsOfServiceElement.js */ \"./src/includes/TermsOfServiceElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar TermsOfServiceWidget = /*#__PURE__*/function (_BaseWidget) {\n function TermsOfServiceWidget() {\n var _this;\n _classCallCheck(this, TermsOfServiceWidget);\n _this = _callSuper(this, TermsOfServiceWidget);\n\n // Match form-field widgets' default block padding (top + bottom 15px)\n // so a freshly-dropped Terms widget sits flush with the field stack\n // above + the Submit button below. Mirror set on both axes — the\n // legal text often gets reasonable breathing room from the surrounding\n // form fields.\n _this.block.formatter.setFormat('padding_top', '15');\n _this.block.formatter.setFormat('padding_bottom', '15');\n\n // Sample seed: short policy line + an explicit <a> so users see the\n // link semantic immediately and can re-target via inline-edit.\n var sampleTerms = 'By submitting this form, you agree to our ' + '<a href=\"#\">Terms of Service</a> and ' + '<a href=\"#\">Privacy Policy</a>.';\n var sampleAgreeLabel = 'I agree to the terms above.';\n _this.block.appendElements([new _TermsOfServiceElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('TermsOfService', sampleTerms, sampleAgreeLabel, true, 'below', '')]);\n return _this;\n }\n _inherits(TermsOfServiceWidget, _BaseWidget);\n return _createClass(TermsOfServiceWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.terms_of_service');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'gavel';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TermsOfServiceWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TermsOfServiceWidget.js?");
/***/ }),
/***/ "./src/includes/TextCenterWidget.js":
/*!******************************************!*\
!*** ./src/includes/TextCenterWidget.js ***!
\******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar TextCenterWidget = /*#__PURE__*/function (_BaseWidget) {\n function TextCenterWidget() {\n var _this;\n _classCallCheck(this, TextCenterWidget);\n _this = _callSuper(this, TextCenterWidget); // Call the parent class constructor\n\n //\n var heading = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n heading.formatter.parseFormats({\n \"padding_bottom\": 12,\n \"text_align\": \"center\"\n });\n var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n p.formatter.parseFormats({\n \"padding_bottom\": 17,\n \"text_align\": \"center\"\n });\n\n //\n _this.block.appendElements([heading, p]);\n return _this;\n }\n _inherits(TextCenterWidget, _BaseWidget);\n return _createClass(TextCenterWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.text_center');\n }\n }, {\n key: \"getImageUrl\",\n value: function getImageUrl() {\n return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 72'%3E%0A %3Crect width='180' height='72' fill='%23F7F7F7'/%3E%0A %3Crect x='58' y='14' width='64' height='8' rx='4' fill='%23C0C0C0'/%3E%0A %3Crect x='24' y='30' width='132' height='6' rx='3' fill='%23DEDEDE'/%3E%0A %3Crect x='40' y='42' width='100' height='6' rx='3' fill='%23DEDEDE'/%3E%0A %3Crect x='68' y='56' width='44' height='12' rx='3.5' fill='%23404040'/%3E%0A%3C/svg%3E\";\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'image';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextCenterWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextCenterWidget.js?");
/***/ }),
/***/ "./src/includes/TextColorControl.js":
/*!******************************************!*\
!*** ./src/includes/TextColorControl.js ***!
\******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar TextColorControl = /*#__PURE__*/function () {\n function TextColorControl(label, value, callback) {\n _classCallCheck(this, TextColorControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n // Initialize properties\n this.label = label; // Label for the text control\n this.value = value; // Initial color value (can be null)\n this.callback = callback; // Callback function to handle input changes\n\n // Create the main container element\n this.domNode = document.createElement(\"div\");\n\n //\n this.render(); // Call the render method to create the UI\n }\n return _createClass(TextColorControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var displayValue = this.value || \"#000000\"; // Default color for color input\n var hexDisplayValue = this.value || \"not set\"; // Text for hex input when null\n\n this.domNode.innerHTML = \"<div class=\\\"py-2 ps-3 pe-3 w-100 d-flex align-items-center justify-content-between\\\">\\n <label for=\\\"\".concat(this.id, \"\\\" class=\\\"form-label fw-semibold mb-0 me-3 small\\\">\").concat(this.label, \"</label>\\n\\n <div class=\\\"d-flex align-items-center border rounded p-1 ps-2 border-default\\\" style=\\\"gap:4px;min-width:140px; max-width:140px; max-height: 32px;\\\">\\n <div id=\\\"\").concat(this.id, \"_color_container\\\" class=\\\"position-relative\\\" style=\\\"width: 20px; height: 20px;\\\">\\n <input id=\\\"\").concat(this.id, \"_color\\\" type=\\\"color\\\" value=\\\"\").concat(displayValue, \"\\\" class=\\\"form-control rounded form-control-color position-absolute\\\" style=\\\"opacity: \").concat(this.value ? 1 : 0, \";\\\">\\n <div id=\\\"\").concat(this.id, \"_transparency\\\" class=\\\"position-absolute h-100 rounded pe-none\\\" style=\\\"width: 20px; background: repeating-conic-gradient(#ccc 0% 25%, white 0% 50%) 50% / 8px 8px; display: \").concat(this.value ? 'none' : 'block', \";\\\"></div>\\n </div>\\n <input id=\\\"\").concat(this.id, \"_hex\\\" type=\\\"text\\\" value=\\\"\").concat(hexDisplayValue, \"\\\" class=\\\"form-control border-none text-center small\\\" style=\\\"height: 28px;font-size:0.875em !important;\\\" />\\n </div>\\n </div>\\n <style>\\n #\").concat(this.id, \"_color {\\n border: none;\\n padding: 0;\\n width: 20px;\\n height: 20px;\\n }\\n #\").concat(this.id, \"_hex {\\n border: none;\\n text-align: center;\\n }\\n </style>\\n \");\n\n // nodes\n this.colorInput = this.domNode.querySelector(\"#\".concat(this.id, \"_color\"));\n this.hexInput = this.domNode.querySelector(\"#\".concat(this.id, \"_hex\"));\n this.transparencyDiv = this.domNode.querySelector(\"#\".concat(this.id, \"_transparency\"));\n\n // sync handlers\n var notify = function notify(val) {\n _this.value = val;\n // Update transparency indicator visibility\n if (_this.transparencyDiv && _this.colorInput) {\n if (val === null || val === undefined) {\n _this.transparencyDiv.style.display = 'block';\n _this.colorInput.style.opacity = '0';\n } else {\n _this.transparencyDiv.style.display = 'none';\n _this.colorInput.style.opacity = '1';\n }\n }\n if (typeof _this.callback === \"function\") {\n _this.callback(val);\n } else if (_this.callback && typeof _this.callback.setValue === \"function\") {\n _this.callback.setValue(val);\n }\n };\n this.colorInput.addEventListener(\"input\", function (e) {\n var v = e.target.value;\n _this.hexInput.value = v;\n notify(v);\n });\n this.hexInput.addEventListener(\"focus\", function (e) {\n // Clear \"not set\" text when user focuses on the input\n if (e.target.value === \"not set\") {\n e.target.value = \"\";\n }\n });\n this.hexInput.addEventListener(\"blur\", function (e) {\n // If user leaves the input empty, show \"not set\" and set value to null\n if (e.target.value.trim() === \"\") {\n e.target.value = \"not set\";\n _this.value = null;\n notify(null);\n }\n });\n this.hexInput.addEventListener(\"change\", function (e) {\n var v = e.target.value.trim();\n\n // If empty or \"not set\", set to null\n if (v === \"\" || v === \"not set\") {\n _this.value = null;\n _this.hexInput.value = \"not set\";\n notify(null);\n return;\n }\n if (!v.startsWith(\"#\")) v = \"#\" + v;\n // basic validation to 3/6 hex chars\n if (/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(v)) {\n _this.colorInput.value = v;\n _this.hexInput.value = v;\n notify(v);\n } else {\n // revert to last known good\n _this.hexInput.value = _this.value || \"not set\";\n }\n });\n\n // keep UI in sync if value was set programmatically before render\n // this.setValue(this.value);\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n\n // Method to set value programmatically\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.value = newValue;\n if (this.colorInput && this.hexInput) {\n if (newValue === null || newValue === undefined) {\n this.colorInput.value = \"#000000\"; // Default color for color input\n this.colorInput.style.opacity = '0';\n this.hexInput.value = \"not set\";\n if (this.transparencyDiv) {\n this.transparencyDiv.style.display = 'block';\n }\n } else {\n this.colorInput.value = newValue;\n this.colorInput.style.opacity = '1';\n this.hexInput.value = newValue;\n if (this.transparencyDiv) {\n this.transparencyDiv.style.display = 'none';\n }\n }\n }\n\n // Support both function and object with setValue\n if (typeof this.callback === \"function\") {\n this.callback(this.value);\n } else if (this.callback && typeof this.callback.setValue === \"function\") {\n this.callback.setValue(this.value);\n }\n }\n\n // Method to get current value\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextColorControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextColorControl.js?");
/***/ }),
/***/ "./src/includes/TextControl.js":
/*!*************************************!*\
!*** ./src/includes/TextControl.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * TextControl — multi-line textarea bound to a single string.\n *\n * 2026-04-18 (Phase 2.22) rewrite — drops Bootstrap `.form-control`,\n * `.form-label`, `.py-2 px-3` utility classes. Uses `.bjs-control-stack`\n * + `.bjs-textarea` primitive. Debounces the setText callback 200ms so\n * the canvas doesn't churn on every keystroke (Lesson 19 no-flicker).\n */\nvar TextControl = /*#__PURE__*/function () {\n function TextControl(label, value, callback) {\n _classCallCheck(this, TextControl);\n this.id = '_' + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = value;\n this.callback = callback;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-text-control');\n this.render();\n }\n return _createClass(TextControl, [{\n key: \"render\",\n value: function render() {\n var _this$value,\n _this = this;\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-stack\\\">\\n <div class=\\\"bjs-control-label\\\">\\n <label for=\\\"\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label>\\n </div>\\n <div class=\\\"bjs-control-input\\\">\\n <textarea id=\\\"\").concat(this.id, \"\\\" class=\\\"bjs-textarea\\\" name=\\\"text\\\" rows=\\\"3\\\"></textarea>\\n </div>\\n </div>\\n \");\n this.getTextInput().value = (_this$value = this.value) !== null && _this$value !== void 0 ? _this$value : '';\n var t = null;\n this.getTextInput().addEventListener('input', function () {\n if (t) clearTimeout(t);\n t = setTimeout(function () {\n return _this.callback.setText(_this.getText());\n }, 200);\n });\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"getTextInput\",\n value: function getTextInput() {\n return this.domNode.querySelector('textarea[name=\"text\"]');\n }\n }, {\n key: \"getText\",\n value: function getText() {\n return this.getTextInput().value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextControl.js?");
/***/ }),
/***/ "./src/includes/TextDirectionControl.js":
/*!**********************************************!*\
!*** ./src/includes/TextDirectionControl.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar TextDirectionControl = /*#__PURE__*/function () {\n function TextDirectionControl(label, value, callback) {\n _classCallCheck(this, TextDirectionControl);\n this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n this.label = label;\n this.value = value;\n this.callback = callback;\n this.options = [{\n icon: \"format_textdirection_l_to_r\",\n value: \"ltr\"\n }, {\n icon: \"format_textdirection_r_to_l\",\n value: \"rtl\"\n }];\n this.domNode = document.createElement(\"div\");\n this.render();\n }\n return _createClass(TextDirectionControl, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n var buttons = this.options.map(function (option) {\n var isActive = _this.value === option.value;\n return \"\\n <button type=\\\"button\\\"\\n class=\\\"bjs-segmented-btn\".concat(isActive ? ' is-active' : '', \"\\\"\\n role=\\\"radio\\\"\\n aria-checked=\\\"\").concat(isActive, \"\\\"\\n data-value=\\\"\").concat(option.value, \"\\\"\\n data-tooltip=\\\"\").concat(option.value, \"\\\"\\n aria-label=\\\"\").concat(option.value, \"\\\"\\n tabindex=\\\"\").concat(isActive ? '0' : '-1', \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\").concat(option.icon, \"</span>\\n </button>\\n \");\n }).join('');\n this.domNode.innerHTML = \"\\n <div class=\\\"bjs-control-row\\\">\\n <div class=\\\"bjs-control-label\\\"><span>\".concat(this.label, \"</span></div>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-segmented\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(this.label, \"\\\">\\n \").concat(buttons, \"\\n </div>\\n </div>\\n </div>\\n \");\n this._bindEvents();\n }\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this2 = this;\n var group = this.domNode.querySelector('.bjs-segmented');\n if (!group) return;\n group.addEventListener('click', function (e) {\n var btn = e.target.closest('.bjs-segmented-btn');\n if (!btn || !group.contains(btn)) return;\n _this2._selectValue(btn.dataset.value, {\n focus: true\n });\n });\n group.addEventListener('keydown', function (e) {\n if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) return;\n e.preventDefault();\n var buttons = Array.from(group.querySelectorAll('.bjs-segmented-btn'));\n var currentIndex = buttons.findIndex(function (b) {\n return b.classList.contains('is-active');\n });\n var nextIndex = currentIndex;\n if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n nextIndex = (currentIndex - 1 + buttons.length) % buttons.length;\n } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n nextIndex = (currentIndex + 1) % buttons.length;\n } else if (e.key === 'Home') {\n nextIndex = 0;\n } else if (e.key === 'End') {\n nextIndex = buttons.length - 1;\n }\n var nextBtn = buttons[nextIndex];\n if (nextBtn) _this2._selectValue(nextBtn.dataset.value, {\n focus: true\n });\n });\n }\n }, {\n key: \"_selectValue\",\n value: function _selectValue(value) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$focus = _ref.focus,\n focus = _ref$focus === void 0 ? false : _ref$focus;\n if (value === this.value) return;\n this.value = value;\n this._updateActiveState();\n this._fireCallback();\n if (focus) {\n var activeBtn = this.domNode.querySelector('.bjs-segmented-btn.is-active');\n if (activeBtn) try {\n activeBtn.focus();\n } catch (e) {}\n }\n }\n }, {\n key: \"_updateActiveState\",\n value: function _updateActiveState() {\n var _this3 = this;\n this.domNode.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n var active = btn.dataset.value === _this3.value;\n btn.classList.toggle('is-active', active);\n btn.setAttribute('aria-checked', active);\n btn.setAttribute('tabindex', active ? '0' : '-1');\n });\n }\n }, {\n key: \"_fireCallback\",\n value: function _fireCallback() {\n if (typeof this.callback === 'function') {\n this.callback(this.value);\n } else if (this.callback && typeof this.callback.setValue === 'function') {\n this.callback.setValue(this.value);\n }\n }\n }, {\n key: \"afterRender\",\n value: function afterRender() {}\n }, {\n key: \"setValue\",\n value: function setValue(newValue) {\n this.value = newValue;\n this._updateActiveState();\n this._fireCallback();\n }\n }, {\n key: \"getValue\",\n value: function getValue() {\n return this.value;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextDirectionControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextDirectionControl.js?");
/***/ }),
/***/ "./src/includes/TextDoubleWidget.js":
/*!******************************************!*\
!*** ./src/includes/TextDoubleWidget.js ***!
\******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar TextDoubleWidget = /*#__PURE__*/function (_BaseWidget) {\n function TextDoubleWidget() {\n var _this;\n _classCallCheck(this, TextDoubleWidget);\n _this = _callSuper(this, TextDoubleWidget); // Call the parent class constructor\n\n //\n var grid = new GridElement('Grid');\n grid.cell_gap = 20;\n var cell1 = new CellElement('Cell');\n cell1.formatter.setFormat('width', 50);\n var cell2 = new CellElement('Cell');\n cell2.formatter.setFormat('width', 50);\n grid.appendCells([cell1, cell2]);\n _this.block.appendElements([grid]);\n\n //\n var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n p.formatter.parseFormats({\n \"padding_bottom\": 17\n });\n\n //\n var p_2 = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n p_2.formatter.parseFormats({\n \"padding_bottom\": 17\n });\n\n //\n var block1 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n block1.appendElements([p]);\n var block2 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n block2.appendElements([p_2]);\n\n //\n cell1.appendBlock(block1);\n cell2.appendBlock(block2);\n return _this;\n }\n _inherits(TextDoubleWidget, _BaseWidget);\n return _createClass(TextDoubleWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.text_double');\n }\n }, {\n key: \"getImageUrl\",\n value: function getImageUrl() {\n return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 72'%3E%0A %3Crect width='200' height='72' fill='%23F7F7F7'/%3E%0A %3Crect x='14' y='14' width='56' height='8' rx='4' fill='%23C0C0C0'/%3E%0A %3Crect x='14' y='28' width='80' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='14' y='38' width='68' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='14' y='52' width='36' height='10' rx='3' fill='%23404040'/%3E%0A %3Crect x='108' y='14' width='56' height='8' rx='4' fill='%23C0C0C0'/%3E%0A %3Crect x='108' y='28' width='80' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='108' y='38' width='68' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A %3Crect x='108' y='52' width='36' height='10' rx='3' fill='%23404040'/%3E%0A%3C/svg%3E\";\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'image';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextDoubleWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextDoubleWidget.js?");
/***/ }),
/***/ "./src/includes/TextInlineKeyboardShortcuts.js":
/*!*****************************************************!*\
!*** ./src/includes/TextInlineKeyboardShortcuts.js ***!
\*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * TextInlineKeyboardShortcuts — W6.3 (TEXT_INLINE_PLAN, 2026-04-24).\n *\n * Keyboard shortcut dispatcher scoped to inline-text hosts. Fires only\n * when the iframe's `activeElement` is inside a `[data-bjs-inline-text]`\n * ancestor AND is not a nested native input. Captures on the iframe\n * document so we run BEFORE the browser's native handler — most\n * shortcuts prevent-default and route through the canonical toolbar\n * pipeline (`_applyExecCommand` / formatter / sanitizer) so rich\n * formatting stays deterministic across engines.\n *\n * Shortcuts shipped (13):\n *\n * ⌘B / Ctrl+B bold\n * ⌘I / Ctrl+I italic\n * ⌘U / Ctrl+U underline\n * ⌘⇧X / Ctrl+⇧X strikethrough\n * ⌘K / Ctrl+K open Link popover (requires selection + toolbar)\n * ⌘⇧K / Ctrl+⇧K unlink (remove link)\n * ⌘⌥C / Ctrl+⌥C copy format (stash computed style on builder._formatClipboard)\n * ⌘⌥V / Ctrl+⌥V paste format (wrap selection in <span style>)\n * ⌘\\ / Ctrl+\\ clear format (execCommand removeFormat)\n * ⌘⇧L / Ctrl+⇧L align left\n * ⌘⇧E / Ctrl+⇧E align center\n * ⌘⇧R / Ctrl+⇧R align right\n * ⌘⇧J / Ctrl+⇧J justify\n *\n * Deferred to W2.3 (needs `ElementFactory.retype()`):\n * ⌘⌥0 paragraph (P)\n * ⌘⌥1-6 heading H1-H6\n * ⌘⌥Q quote (→ BlockquoteElement)\n *\n * Coexistence with ⌘Z undo (PLAN_UNDO_REDO): the history handler in\n * `Builder._historyInit` EXPLICITLY skips contenteditable targets, so\n * undo/redo inside inline text is handled by the browser's native\n * contenteditable undo stack — we intentionally do NOT bind ⌘Z here.\n *\n * Scope check (HARD RULE T1 consequence): target must be a descendant\n * of a `[data-bjs-inline-text]` host AND not inside a nested input.\n * Typing ⌘B in the sidebar does nothing here; typing ⌘B in a P\n * inline-edit toggles bold.\n *\n * Dispatcher design: capture-phase listener on the iframe document so\n * a shortcut's preventDefault runs BEFORE the browser's contenteditable\n * default would. This avoids the \"⌘B toggled twice\" bug that happens\n * when both our handler and the native execCommand fire.\n */\n\n\n\nvar TextInlineKeyboardShortcuts = /*#__PURE__*/function () {\n function TextInlineKeyboardShortcuts(builder) {\n _classCallCheck(this, TextInlineKeyboardShortcuts);\n if (!builder) {\n throw new Error('TextInlineKeyboardShortcuts: builder required');\n }\n this._builder = builder;\n this._doc = null;\n this._handler = this._onKeyDown.bind(this);\n this._attached = false;\n }\n return _createClass(TextInlineKeyboardShortcuts, [{\n key: \"attach\",\n value: function attach() {\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n if (!idoc) return;\n if (this._attached && this._doc === idoc) return;\n // Detach from a previous doc if the iframe was recreated.\n if (this._attached && this._doc && this._doc !== idoc) {\n this._doc.removeEventListener('keydown', this._handler, true);\n }\n this._doc = idoc;\n idoc.addEventListener('keydown', this._handler, true);\n this._attached = true;\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-inline-kbd', 'attached');\n }\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (!this._attached || !this._doc) return;\n this._doc.removeEventListener('keydown', this._handler, true);\n this._attached = false;\n this._doc = null;\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-inline-kbd', 'destroyed');\n }\n\n /* ── dispatcher ──────────────────────────────────────────── */\n }, {\n key: \"_onKeyDown\",\n value: function _onKeyDown(e) {\n var mod = e.metaKey || e.ctrlKey;\n if (!mod) return;\n\n // Scope check — target must be inside an inline-text host AND\n // not a nested native input (which owns its own key semantics).\n var target = e.target;\n if (!target || target.nodeType !== 1) return;\n var host = typeof target.closest === 'function' ? target.closest('[data-bjs-inline-text]') : null;\n if (!host) return;\n var tag = target.tagName && target.tagName.toLowerCase();\n if (tag === 'input' || tag === 'textarea' || tag === 'select') return;\n var key = (e.key || '').toLowerCase();\n var shift = e.shiftKey;\n var alt = e.altKey;\n\n // Dispatch matrix. Every captured shortcut prevents default +\n // stops propagation so the browser's native handler (or a\n // higher-level listener) doesn't double-fire.\n var handled = false;\n if (!shift && !alt) {\n // Plain ⌘/Ctrl + single key.\n switch (key) {\n case 'b':\n handled = this._execCommand('bold', null);\n break;\n case 'i':\n handled = this._execCommand('italic', null);\n break;\n case 'u':\n handled = this._execCommand('underline', null);\n break;\n case 'k':\n handled = this._openLinkPopover();\n break;\n case '\\\\':\n handled = this._execCommand('removeFormat', null);\n break;\n }\n } else if (shift && !alt) {\n switch (key) {\n case 'x':\n handled = this._execCommand('strikeThrough', null);\n break;\n case 'k':\n handled = this._removeLink();\n break;\n case 'l':\n handled = this._applyAlign('left');\n break;\n case 'e':\n handled = this._applyAlign('center');\n break;\n case 'r':\n handled = this._applyAlign('right');\n break;\n case 'j':\n handled = this._applyAlign('justify');\n break;\n }\n } else if (alt && !shift) {\n switch (key) {\n case 'c':\n handled = this._copyFormat();\n break;\n case 'v':\n handled = this._pasteFormat();\n break;\n // ⌘⌥1-6, ⌘⌥0, ⌘⌥Q deferred — see W2.3 (ElementFactory.retype).\n }\n }\n if (handled) {\n e.preventDefault();\n e.stopPropagation();\n }\n }\n\n /* ── action routes ──────────────────────────────────────── */\n\n /**\n * Route through `iframeDoc.execCommand` then `InlineSanitizer.normalize`\n * on the inline-text host so `<b>/<i>/<font>` divergent browser\n * outputs canonicalise to `<strong>/<em>/<span style>`. Mirrors the\n * toolbar's `_applyExecCommand` shape but without the char-offset\n * save/restore (the shortcut fires from a keydown inside the\n * contenteditable — the browser's own input event handles the\n * rest of the setText → innerHTML rewrite + selection restore).\n */\n }, {\n key: \"_execCommand\",\n value: function _execCommand(cmd, value) {\n var idoc = this._doc;\n if (!idoc) return false;\n var ok = false;\n try {\n ok = idoc.execCommand(cmd, false, value);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:execCommand:' + cmd, err);\n return false;\n }\n if (ok) this._normalizeActiveHost();\n this._refreshTracker();\n return true; // we preventDefault regardless so browser doesn't double-fire\n }\n }, {\n key: \"_applyAlign\",\n value: function _applyAlign(side) {\n var element = this._resolveActiveElement();\n if (!element || !element.formatter || typeof element.formatter.setFormat !== 'function') {\n return false;\n }\n try {\n element.formatter.setFormat('text_align', side);\n if (typeof element.applyFormatStyles === 'function') {\n element.applyFormatStyles();\n } else if (typeof element.render === 'function') {\n element.render();\n }\n if (this._builder.events && typeof this._builder.events.emit === 'function') {\n this._builder.events.emit('formatter:change', {\n elementUid: element.id,\n key: 'text_align',\n value: side,\n source: 'text-inline-kbd'\n });\n }\n this._refreshTracker();\n return true;\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:align:' + side, err);\n return false;\n }\n }\n }, {\n key: \"_openLinkPopover\",\n value: function _openLinkPopover() {\n var toolbar = this._builder._textInlineToolbar;\n if (!toolbar || !toolbar._mounted) return false;\n // Toolbar's own click handler is the canonical path — reuse the\n // Link button so the single-popover invariant the toolbar owns\n // stays intact (closes color/font/more/AI siblings before opening).\n var btn = toolbar.domNode && toolbar.domNode.querySelector('[data-link-btn]');\n if (!btn) return false;\n try {\n if (typeof toolbar._toggleLinkPopover === 'function') {\n toolbar._toggleLinkPopover(btn);\n return true;\n }\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:link-popover', err);\n }\n return false;\n }\n }, {\n key: \"_removeLink\",\n value: function _removeLink() {\n // `unlink` strips an anchor whose selection covers it. Same\n // path the More menu's Remove Link item uses, but without the\n // pre-dispatch disabled-state check (the browser's execCommand\n // is a no-op when selection has no <a>, so we don't have to\n // pre-check — false return from execCommand is silent).\n return this._execCommand('unlink', null);\n }\n\n /**\n * Snapshot the selection's computed style onto `builder._formatClipboard`\n * — same shape as `TextInlineToolbarOverlay._doCopyFormat`. No toolbar\n * dependency (uses activeElement's iframe host + getComputedStyle).\n */\n }, {\n key: \"_copyFormat\",\n value: function _copyFormat() {\n var idoc = this._doc;\n var iwin = idoc && idoc.defaultView;\n if (!idoc || !iwin) return false;\n var sel = iwin.getSelection();\n if (!sel || sel.rangeCount === 0) return false;\n var range = sel.getRangeAt(0);\n var ac = range.commonAncestorContainer;\n var el = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n if (!el) return false;\n var cs;\n try {\n cs = iwin.getComputedStyle(el);\n } catch (_) {\n return false;\n }\n if (!cs) return false;\n this._builder._formatClipboard = {\n fontFamily: cs.fontFamily || '',\n fontWeight: cs.fontWeight || '',\n fontStyle: cs.fontStyle || '',\n fontSize: cs.fontSize || '',\n color: cs.color || '',\n backgroundColor: cs.backgroundColor || '',\n textDecorationLine: cs.textDecorationLine || cs.textDecoration || '',\n letterSpacing: cs.letterSpacing || '',\n lineHeight: cs.lineHeight || ''\n };\n return true;\n }\n\n /**\n * Wrap the current selection in a `<span style>` carrying the\n * snapshotted clipboard. No-ops if clipboard empty — a fresh\n * ⌘⌥C Copy Format primes it.\n */\n }, {\n key: \"_pasteFormat\",\n value: function _pasteFormat() {\n var snap = this._builder._formatClipboard;\n if (!snap) return false;\n var idoc = this._doc;\n var iwin = idoc && idoc.defaultView;\n if (!idoc || !iwin) return false;\n var sel = iwin.getSelection();\n if (!sel || sel.rangeCount === 0) return false;\n var range = sel.getRangeAt(0);\n if (range.collapsed) return false;\n var css = this._cssFromFormat(snap);\n if (!css) return false;\n var innerHtml = '';\n try {\n var frag = range.cloneContents();\n var tmp = idoc.createElement('div');\n tmp.appendChild(frag);\n innerHtml = tmp.innerHTML;\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:paste-format:clone', err);\n return false;\n }\n if (!innerHtml) return false;\n var wrapped = \"<span style=\\\"\".concat(css, \"\\\">\").concat(innerHtml, \"</span>\");\n try {\n idoc.execCommand('insertHTML', false, wrapped);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:paste-format:insert', err);\n return false;\n }\n this._normalizeActiveHost();\n this._refreshTracker();\n return true;\n }\n\n /* ── helpers ─────────────────────────────────────────────── */\n }, {\n key: \"_cssFromFormat\",\n value: function _cssFromFormat(snap) {\n if (!snap) return '';\n var isDefaultDecoration = function isDefaultDecoration(v) {\n return !v || v === 'none' || v === 'initial' || v === 'inherit';\n };\n var isTransparent = function isTransparent(v) {\n return !v || v === 'rgba(0, 0, 0, 0)' || v === 'transparent';\n };\n var isAutoOrNormal = function isAutoOrNormal(v) {\n return !v || v === 'normal' || v === 'auto';\n };\n var parts = [];\n if (snap.fontFamily && snap.fontFamily !== 'inherit') parts.push(\"font-family: \".concat(snap.fontFamily));\n if (snap.fontWeight && snap.fontWeight !== '400' && snap.fontWeight !== 'normal') parts.push(\"font-weight: \".concat(snap.fontWeight));\n if (snap.fontStyle && snap.fontStyle !== 'normal') parts.push(\"font-style: \".concat(snap.fontStyle));\n if (snap.fontSize) parts.push(\"font-size: \".concat(snap.fontSize));\n if (snap.color) parts.push(\"color: \".concat(snap.color));\n if (!isTransparent(snap.backgroundColor)) parts.push(\"background-color: \".concat(snap.backgroundColor));\n if (!isDefaultDecoration(snap.textDecorationLine)) parts.push(\"text-decoration: \".concat(snap.textDecorationLine));\n if (!isAutoOrNormal(snap.letterSpacing)) parts.push(\"letter-spacing: \".concat(snap.letterSpacing));\n if (!isAutoOrNormal(snap.lineHeight)) parts.push(\"line-height: \".concat(snap.lineHeight));\n return parts.join('; ');\n }\n\n /**\n * Find the inline-text host that currently owns the iframe's active\n * selection + normalize its markup in place. Same rationale as\n * `TextInlineToolbarOverlay._normalizeHost` — after any execCommand,\n * the browser's markup (Safari/Firefox/Chromium) is canonicalised\n * so round-trip invariants hold.\n */\n }, {\n key: \"_normalizeActiveHost\",\n value: function _normalizeActiveHost() {\n var idoc = this._doc;\n if (!idoc) return;\n var active = idoc.activeElement;\n var host = active && typeof active.closest === 'function' ? active.closest('[data-bjs-inline-text]') : null;\n if (!host) return;\n try {\n _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].normalize(host);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:normalize', err);\n }\n }\n }, {\n key: \"_refreshTracker\",\n value: function _refreshTracker() {\n var tracker = this._builder.textSelectionTracker;\n if (tracker && typeof tracker.refresh === 'function') {\n try {\n tracker.refresh();\n } catch (_) {}\n }\n }\n\n /**\n * Resolve the element instance for the currently-focused inline-text\n * host. Uses the marker's `data-bjs-inline-text` uid (W0.2b) +\n * `builder.uiManager.elements` registry — same shape as the toolbar's\n * `_resolveCurrentElement` but independent of toolbar mount state.\n */\n }, {\n key: \"_resolveActiveElement\",\n value: function _resolveActiveElement() {\n var idoc = this._doc;\n if (!idoc) return null;\n var active = idoc.activeElement;\n if (!active || typeof active.closest !== 'function') return null;\n var host = active.closest('[data-bjs-inline-text]');\n if (!host) return null;\n var uid = host.getAttribute('data-bjs-inline-text');\n if (!uid) return null;\n var uiMgr = this._builder && this._builder.uiManager;\n if (!uiMgr || !Array.isArray(uiMgr.elements)) return null;\n return uiMgr.elements.find(function (el) {\n return el && el.id === uid;\n }) || null;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextInlineKeyboardShortcuts);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextInlineKeyboardShortcuts.js?");
/***/ }),
/***/ "./src/includes/TextInputElement.js":
/*!******************************************!*\
!*** ./src/includes/TextInputElement.js ***!
\******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar TextInputElement = /*#__PURE__*/function (_BaseElement) {\n function TextInputElement(template, inputName, inputValue, placeholder) {\n var _this;\n _classCallCheck(this, TextInputElement);\n _this = _callSuper(this, TextInputElement); // Call the parent class constructor\n _this.template = template;\n _this.inputName = inputName;\n _this.inputValue = inputValue;\n _this.placeholder = placeholder;\n _this.required = false;\n _this.type = 'text';\n _this.domNode = null;\n _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]({\n align: null,\n font_family: null,\n font_weight: null,\n font_size: null,\n text_color: null,\n text_align: null,\n line_height: null,\n letter_spacing: null,\n background_color: null,\n background_image: null,\n background_position: null,\n background_size: null,\n background_repeat: null,\n padding_top: null,\n padding_right: null,\n padding_bottom: null,\n padding_left: null,\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_style: null,\n border_left_width: null,\n border_left_color: null,\n border_radius: null,\n width: null,\n max_width: null,\n min_width: null\n });\n return _this;\n }\n _inherits(TextInputElement, _BaseElement);\n return _createClass(TextInputElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.text_input');\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n name: this.inputName,\n value: this.inputValue,\n placeholder: this.placeholder,\n required: this.required,\n type: this.type\n });\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(TextInputElement, \"getData\", this, 3)([])), {}, {\n inputName: this.inputName,\n inputValue: this.inputValue,\n placeholder: this.placeholder,\n type: this.type || 'text',\n required: this.required || false\n });\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this2 = this;\n return [\n // TextControl\n new _TextControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.name'),\n // value\n this.inputName,\n // callback\n {\n // set name\n setText: function setText(inputName) {\n _this2.inputName = inputName;\n _this2.render();\n }\n }),\n // TextControl\n new _TextControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.value'),\n // value\n this.inputValue,\n // callback\n {\n // set value\n setText: function setText(inputValue) {\n _this2.inputValue = inputValue;\n _this2.render();\n }\n }),\n // TextControl\n new _TextControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.placeholder'),\n // value\n this.placeholder,\n // callback\n {\n // set text\n setText: function setText(placeholder) {\n _this2.placeholder = placeholder;\n _this2.render();\n }\n }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n color: this.formatter.getFormat('background_color', '#ffffff'),\n image: this.formatter.getFormat('background_image', ''),\n position: this.formatter.getFormat('background_position', 'center'),\n size: this.formatter.getFormat('background_size', '100'),\n repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n }, {\n setBackground: function setBackground(values) {\n _this2.formatter.setFormat('background_color', values.color);\n _this2.formatter.setFormat('background_image', values.image);\n _this2.formatter.setFormat('background_position', values.position);\n _this2.formatter.setFormat('background_size', values.size);\n _this2.formatter.setFormat('background_repeat', values.repeat);\n _this2.render();\n }\n }, {\n features: ['color', 'image', 'size', 'repeat', 'gradient']\n }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style'),\n border_top_width: this.formatter.getFormat('border_top_width'),\n border_top_color: this.formatter.getFormat('border_top_color'),\n border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n border_left_style: this.formatter.getFormat('border_left_style'),\n border_left_width: this.formatter.getFormat('border_left_width'),\n border_left_color: this.formatter.getFormat('border_left_color'),\n border_right_style: this.formatter.getFormat('border_right_style'),\n border_right_width: this.formatter.getFormat('border_right_width'),\n border_right_color: this.formatter.getFormat('border_right_color')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this2.formatter.setFormat('border_top_style', border_top_style);\n _this2.formatter.setFormat('border_top_width', border_top_width);\n _this2.formatter.setFormat('border_top_color', border_top_color);\n _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this2.formatter.setFormat('border_left_style', border_left_style);\n _this2.formatter.setFormat('border_left_width', border_left_width);\n _this2.formatter.setFormat('border_left_color', border_left_color);\n _this2.formatter.setFormat('border_right_style', border_right_style);\n _this2.formatter.setFormat('border_right_width', border_right_width);\n _this2.formatter.setFormat('border_right_color', border_right_color);\n\n // re-render\n _this2.render();\n }\n }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n setRadius: function setRadius(v) {\n _this2.formatter.setFormat('border_radius', v);\n _this2.render();\n }\n }),\n // W3.8b — InnerPaddingControl (intrinsic: input breathing room).\n new InnerPaddingControl(\n // label\n _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.padding'),\n // value\n {\n top: this.formatter.getFormat('padding_top'),\n right: this.formatter.getFormat('padding_right'),\n bottom: this.formatter.getFormat('padding_bottom'),\n left: this.formatter.getFormat('padding_left')\n },\n // callback\n {\n setValues: function setValues(values) {\n _this2.formatter.setFormat('padding_top', values.top);\n _this2.formatter.setFormat('padding_right', values.right);\n _this2.formatter.setFormat('padding_bottom', values.bottom);\n _this2.formatter.setFormat('padding_left', values.left);\n _this2.render();\n }\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n var e = new this(data.template, data.inputName, data.inputValue, data.placeholder);\n e.required = data.required || false;\n e.type = data.type || 'text';\n return this.parseFormats(e, data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextInputElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextInputElement.js?");
/***/ }),
/***/ "./src/includes/TextLeftWidget.js":
/*!****************************************!*\
!*** ./src/includes/TextLeftWidget.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar TextLeftWidget = /*#__PURE__*/function (_BaseWidget) {\n function TextLeftWidget() {\n var _this;\n _classCallCheck(this, TextLeftWidget);\n _this = _callSuper(this, TextLeftWidget); // Call the parent class constructor\n\n //\n var grid = new GridElement('Grid');\n grid.cell_gap = 20;\n var cell1 = new CellElement('Cell');\n cell1.formatter.setFormat('width', 50);\n var cell2 = new CellElement('Cell');\n cell2.formatter.setFormat('width', 50);\n grid.appendCells([cell1, cell2]);\n _this.block.appendElements([grid]);\n\n //\n var heading = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n heading.formatter.parseFormats({\n \"padding_bottom\": 12\n });\n var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n p.formatter.parseFormats({\n \"padding_bottom\": 17\n });\n\n //\n var block1 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n block1.appendElements([heading]);\n var block2 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n block2.appendElements([p]);\n\n //\n cell1.appendBlock(block1);\n cell2.appendBlock(block2);\n return _this;\n }\n _inherits(TextLeftWidget, _BaseWidget);\n return _createClass(TextLeftWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.text_left');\n }\n }, {\n key: \"getImageUrl\",\n value: function getImageUrl() {\n return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 72'%3E%0A %3Crect width='180' height='72' fill='%23F7F7F7'/%3E%0A %3Crect x='14' y='14' width='64' height='8' rx='4' fill='%23C0C0C0'/%3E%0A %3Crect x='14' y='30' width='152' height='6' rx='3' fill='%23DEDEDE'/%3E%0A %3Crect x='14' y='42' width='120' height='6' rx='3' fill='%23DEDEDE'/%3E%0A %3Crect x='14' y='56' width='44' height='12' rx='3.5' fill='%23404040'/%3E%0A%3C/svg%3E\";\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'image';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextLeftWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextLeftWidget.js?");
/***/ }),
/***/ "./src/includes/TextSelectionTracker.js":
/*!**********************************************!*\
!*** ./src/includes/TextSelectionTracker.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SelectionGuard: () => (/* binding */ SelectionGuard),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * TextSelectionTracker — single source of truth for \"what text range is the\n * user currently selecting on the canvas?\".\n *\n * Per TEXT_INLINE_PLAN W0.3 + HARD RULE T1, every selection-aware overlay\n * (floating toolbar, color popover, link-on-selection popover, font popover,\n * advanced popover, AI rewrite, slash menu) mounts from `text-selection:*`\n * bus events and nothing else — never from element click, never from body\n * event. Centralising the listener chain here (one pair of selectionchange\n * + mouseup handlers on the iframe doc) keeps that invariant from drifting.\n *\n * Scope — only tracks selections whose anchor AND focus nodes are inside a\n * `[data-bjs-inline-text]` ancestor (marker stamped by\n * `BaseElement._wireInlineEdit()`, TEXT_INLINE_PLAN W0.2b). Anything else\n * — selection outside an inline text surface, collapsed caret, or a cross-\n * surface selection (anchor in one paragraph, focus in a different one) —\n * emits `text-selection:clear` so subscribers tear down cleanly.\n *\n * Emits on `builder.events` (CanvasHighlightBus):\n * 'text-selection:change' { elementUid, range, rect, text, formats }\n * 'text-selection:clear' { elementUid }\n *\n * `elementUid` uses `BaseElement.id` per HARD RULE E (never `.uid`).\n *\n * `formats` is introspection-only; write paths (bold, italic, link, etc.)\n * live in the toolbar overlays that ship in later waves. Keys covered:\n * bold / italic / underline / strikeThrough (from `queryCommandState`) +\n * link / linkHref / linkTarget (ancestor `<a>` walk inside the host) +\n * align / fontFamily / fontSize / fontWeight / color (computed style of\n * the range's common ancestor). A selection-aware subscriber should treat\n * any missing key as \"unknown, render `.is-mixed`\".\n *\n * Event timing:\n * - `selectionchange` fires MANY times during a drag-select; coalesced\n * into one emit via `debounceMs` (default 50ms — UIManager Lesson I1).\n * - `mouseup` fast-paths an emit without debounce so the toolbar paints\n * on the release frame.\n * - `_emitClear()` is idempotent — after the first clear, re-clears are\n * no-ops until a non-empty selection fires next.\n */\nvar TextSelectionTracker = /*#__PURE__*/function () {\n /**\n * @param {Object} opts\n * @param {Document} opts.doc — iframe contentDocument (the builder canvas).\n * @param {Object} opts.bus — `builder.events` CanvasHighlightBus.\n * @param {number} [opts.debounceMs=50] — selectionchange coalesce window.\n */\n function TextSelectionTracker() {\n var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},\n doc = _ref.doc,\n bus = _ref.bus,\n _ref$debounceMs = _ref.debounceMs,\n debounceMs = _ref$debounceMs === void 0 ? 50 : _ref$debounceMs;\n _classCallCheck(this, TextSelectionTracker);\n if (!doc) {\n throw new Error('TextSelectionTracker: `doc` is required (pass iframe.contentDocument).');\n }\n if (!bus || typeof bus.emit !== 'function') {\n throw new Error('TextSelectionTracker: `bus` must expose .emit() (pass builder.events).');\n }\n this._doc = doc;\n this._bus = bus;\n this._debounceMs = Math.max(0, debounceMs | 0);\n this._timer = null;\n this._attached = false;\n\n // Last emitted payload — null when cleared. Drives `getCurrent()`\n // + idempotent `_emitClear()` (second clear is a no-op; if we\n // emit clear without previous state, subscribers like the\n // toolbar would tear down a mount that never happened).\n this._lastPayload = null;\n this._onSelectionChange = this._onSelectionChange.bind(this);\n this._onMouseUp = this._onMouseUp.bind(this);\n }\n\n /** Start listening. Idempotent. */\n return _createClass(TextSelectionTracker, [{\n key: \"attach\",\n value: function attach() {\n if (this._attached) return;\n this._doc.addEventListener('selectionchange', this._onSelectionChange);\n this._doc.addEventListener('mouseup', this._onMouseUp, true);\n this._attached = true;\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-selection-tracker', 'attached');\n }\n\n /** Stop listening; clear any pending timer + emit a final clear. */\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (!this._attached) return;\n this._doc.removeEventListener('selectionchange', this._onSelectionChange);\n this._doc.removeEventListener('mouseup', this._onMouseUp, true);\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = null;\n }\n this._emitClear();\n this._attached = false;\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-selection-tracker', 'destroyed');\n }\n\n /** Most recently emitted payload (or null if currently cleared). */\n }, {\n key: \"getCurrent\",\n value: function getCurrent() {\n return this._lastPayload;\n }\n\n /**\n * Force a synchronous recompute + emit. Use after programmatic DOM\n * mutations that do NOT fire selectionchange (e.g. toolbar format\n * apply that re-reads its buttons' `.is-active` state).\n */\n }, {\n key: \"refresh\",\n value: function refresh() {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = null;\n }\n this._recompute();\n }\n\n /* ── Private ─────────────────────────────────────────────────── */\n }, {\n key: \"_onSelectionChange\",\n value: function _onSelectionChange() {\n var _this = this;\n if (this._timer) clearTimeout(this._timer);\n this._timer = setTimeout(function () {\n _this._timer = null;\n _this._recompute();\n }, this._debounceMs);\n }\n }, {\n key: \"_onMouseUp\",\n value: function _onMouseUp() {\n // Emit immediately on release — the 50ms debounce swallows the\n // last selectionchange otherwise, which produces a visible lag\n // before the floating toolbar appears.\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = null;\n }\n this._recompute();\n }\n }, {\n key: \"_recompute\",\n value: function _recompute() {\n var win = this._doc.defaultView;\n if (!win) return;\n var sel = win.getSelection();\n if (!sel || sel.rangeCount === 0) return this._emitClear();\n var range = sel.getRangeAt(0);\n if (range.collapsed) return this._emitClear();\n var anchorHost = this._closestInlineHost(sel.anchorNode);\n var focusHost = this._closestInlineHost(sel.focusNode);\n\n // Both ends must be inside the SAME inline-text surface — cross-\n // surface ranges have no single `elementUid` (HARD RULE E) and no\n // single-element toolbar can own them.\n if (!anchorHost || !focusHost || anchorHost !== focusHost) {\n return this._emitClear();\n }\n var elementUid = anchorHost.getAttribute('data-bjs-inline-text');\n if (!elementUid) return this._emitClear();\n var payload = {\n elementUid: elementUid,\n range: range.cloneRange(),\n rect: range.getBoundingClientRect(),\n text: range.toString(),\n formats: this._introspectFormats(anchorHost, range)\n };\n this._lastPayload = payload;\n this._bus.emit('text-selection:change', payload);\n }\n }, {\n key: \"_emitClear\",\n value: function _emitClear() {\n var prev = this._lastPayload;\n if (!prev) return; // idempotent — nothing to tear down\n this._lastPayload = null;\n this._bus.emit('text-selection:clear', {\n elementUid: prev.elementUid\n });\n }\n }, {\n key: \"_closestInlineHost\",\n value: function _closestInlineHost(node) {\n if (!node) return null;\n var el = node.nodeType === 1 /* ELEMENT_NODE */ ? node : node.parentElement;\n if (!el || typeof el.closest !== 'function') return null;\n return el.closest('[data-bjs-inline-text]');\n }\n }, {\n key: \"_introspectFormats\",\n value: function _introspectFormats(host, range) {\n var doc = this._doc;\n var win = doc.defaultView;\n var safe = function safe(cmd) {\n try {\n return !!doc.queryCommandState(cmd);\n } catch (_) {\n return false;\n }\n };\n var container = range.commonAncestorContainer;\n var anchorEl = container.nodeType === 1 ? container : container.parentElement;\n var style = anchorEl && win ? win.getComputedStyle(anchorEl) : null;\n\n // Link detection — walk ancestors up to but not past the inline\n // host. We never look outside the text surface; an <a> that wraps\n // the whole element (LinkElement's root) counts — that's valid\n // because the selection is still \"inside a link\".\n var linkHref = null;\n var linkTarget = null;\n var cursor = anchorEl;\n while (cursor && cursor !== host) {\n if (cursor.tagName === 'A') {\n linkHref = cursor.getAttribute('href') || null;\n linkTarget = cursor.getAttribute('target') || null;\n break;\n }\n cursor = cursor.parentElement;\n }\n // Edge case: host itself is the <a> (LinkElement.template.html is\n // `<a><%- text %></a>`). Recognise link state even though the walk\n // above stops at host.\n if (!linkHref && host.tagName === 'A') {\n linkHref = host.getAttribute('href') || null;\n linkTarget = host.getAttribute('target') || null;\n }\n return {\n bold: safe('bold'),\n italic: safe('italic'),\n underline: safe('underline'),\n strikeThrough: safe('strikeThrough'),\n link: !!linkHref,\n linkHref: linkHref,\n linkTarget: linkTarget,\n align: style ? style.textAlign : null,\n fontFamily: style ? style.fontFamily : null,\n fontSize: style ? style.fontSize : null,\n fontWeight: style ? style.fontWeight : null,\n color: style ? style.color : null\n };\n }\n }]);\n}();\n/**\n * SelectionGuard — W5.2 (TEXT_INLINE_PLAN, 2026-04-24).\n *\n * Save + restore the iframe's text selection across popover mount /\n * interaction cycles so the user's highlight survives clicking into\n * popover inputs. Addresses the UX regression where opening a\n * FontPopoverOverlay / ColorPopoverOverlay / LinkOnSelectionPopoverOverlay\n * shifts focus to the popover's own inputs (selects, number steppers,\n * URL fields), which — on some Chromium builds — collapses the iframe\n * selection the user painted.\n *\n * Save/restore strategy: character offsets against the inline-text host,\n * not Range references. Rationale (same as W1.1 `_saveSelectionOffsets`\n * precedent):\n * - Range objects hold node references; after `setText → innerHTML =`\n * rebuilds those nodes, the Range points to detached nodes.\n * - Char offsets are invariant under any innerHTML rewrite (text\n * content survives, only the node chunks change).\n * - TreeWalker(SHOW_TEXT) resolves offsets back to live nodes after\n * the rebuild.\n *\n * API:\n * SelectionGuard.save(builder) → snapshot | null\n * SelectionGuard.restore(builder, snapshot)\n * SelectionGuard.run(builder, fn) → fn() wrapped in save/restore\n * (supports async fn via finally)\n *\n * Consumers call `SelectionGuard.save(this._builder)` on popover open,\n * stash the snapshot, and call `.restore(this._builder, snapshot)` on\n * popover close. Alternatively, wrap a single apply handler with `.run()`\n * when the guard's scope is just one operation.\n *\n * Retirement plan: when W5.1 refactors every inline-text element to\n * `applyFormatStyles()` (no innerHTML rebuild on format apply), the\n * char-offset shim becomes unnecessary — Range references will survive\n * the format write, and Selection APIs can track the live range without\n * manual save/restore. SelectionGuard will slim to a thin range-clone\n * pattern or retire entirely. Keep the API stable so the transition\n * is transparent to callers.\n */\nvar SelectionGuard = /*#__PURE__*/function () {\n function SelectionGuard() {\n _classCallCheck(this, SelectionGuard);\n }\n return _createClass(SelectionGuard, null, [{\n key: \"save\",\n value:\n /**\n * Snapshot the current selection's char offsets within its inline-text\n * host. Returns `null` when no iframe selection is live OR the\n * selection is outside any `[data-bjs-inline-text]` surface.\n *\n * @param {Builder} owner\n * @returns {{elementUid: string, start: number, end: number} | null}\n */\n function save(owner) {\n if (!owner) return null;\n var idoc = owner.iframe && owner.iframe.contentDocument;\n var iwin = idoc && idoc.defaultView;\n if (!idoc || !iwin) return null;\n\n // Prefer the tracker's last payload (non-collapsed, inline-scoped).\n // Fall back to the live iframe selection so callers without a\n // toolbar-sourced payload still get coverage.\n var range = null;\n var inlineHostEl = null;\n var tracker = owner.textSelectionTracker;\n if (tracker && typeof tracker.getCurrent === 'function') {\n var payload = tracker.getCurrent();\n if (payload && payload.range) {\n range = payload.range;\n inlineHostEl = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(payload.elementUid, \"\\\"]\"));\n }\n }\n if (!range) {\n var sel = iwin.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n var live = sel.getRangeAt(0);\n if (live.collapsed) return null;\n var ac = live.commonAncestorContainer;\n var el = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n inlineHostEl = el && typeof el.closest === 'function' ? el.closest('[data-bjs-inline-text]') : null;\n if (!inlineHostEl) return null;\n range = live;\n }\n if (!inlineHostEl) return null;\n var uid = inlineHostEl.getAttribute('data-bjs-inline-text');\n if (!uid) return null;\n try {\n var pre = idoc.createRange();\n pre.selectNodeContents(inlineHostEl);\n pre.setEnd(range.startContainer, range.startOffset);\n var start = pre.toString().length;\n var end = start + range.toString().length;\n return {\n elementUid: uid,\n start: start,\n end: end\n };\n } catch (_) {\n return null;\n }\n }\n\n /**\n * Restore a previously-saved snapshot. Idempotent + defensive:\n * silently skips when the host vanished from the DOM (element\n * deleted) or the offsets no longer map to valid text nodes\n * (content shorter after apply). Notifies the tracker so any\n * subscribers re-read state.\n *\n * Skips if the tracker was EXPLICITLY cleared between save + restore\n * — covers the \"selection-clear cascade closes a popover that had\n * a saved snapshot\" case. Reviving the selection there would re-\n * mount the toolbar the user just dismissed (e.g. by clicking on\n * canvas outside the inline-text host).\n */\n }, {\n key: \"restore\",\n value: function restore(owner, snapshot) {\n if (!owner || !snapshot) return;\n // If the tracker has no current payload AND was non-null when we\n // saved (i.e. someone deliberately cleared it via\n // `text-selection:clear`), the user's intent is \"selection gone\"\n // — don't revive it. The save() path only produces a snapshot\n // when a selection was live, so a null tracker at restore time\n // means clear happened between the two.\n var trackerRef = owner.textSelectionTracker;\n if (trackerRef && typeof trackerRef.getCurrent === 'function' && trackerRef.getCurrent() === null) {\n return;\n }\n var idoc = owner.iframe && owner.iframe.contentDocument;\n var iwin = idoc && idoc.defaultView;\n if (!idoc || !iwin) return;\n var inlineHostEl = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(snapshot.elementUid, \"\\\"]\"));\n if (!inlineHostEl) return;\n\n // TreeWalker resolves char offsets → live text nodes after any\n // intervening innerHTML rebuild. NodeFilter.SHOW_TEXT = 4.\n var walker = idoc.createTreeWalker(inlineHostEl, 4, null, false);\n var count = 0;\n var startNode = null,\n startOffset = 0;\n var endNode = null,\n endOffset = 0;\n var node;\n while (node = walker.nextNode()) {\n var len = node.textContent.length;\n var nextCount = count + len;\n if (!startNode && nextCount >= snapshot.start) {\n startNode = node;\n startOffset = snapshot.start - count;\n }\n if (!endNode && nextCount >= snapshot.end) {\n endNode = node;\n endOffset = snapshot.end - count;\n break;\n }\n count = nextCount;\n }\n // Clamp to host extents — prefer a collapsed caret over a throw.\n if (!startNode) {\n startNode = inlineHostEl;\n startOffset = 0;\n }\n if (!endNode) {\n endNode = startNode;\n endOffset = Math.min(startOffset, (startNode.textContent || '').length);\n }\n try {\n var range = idoc.createRange();\n range.setStart(startNode, startOffset);\n range.setEnd(endNode, endOffset);\n var sel = iwin.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n } catch (_) {\n return;\n }\n\n // Refresh the tracker so subscribers see the restored range in\n // the next tick. The tracker's debounce may coalesce this with\n // any in-flight selectionchange — `refresh()` bypasses the\n // debounce synchronously.\n var tracker = owner.textSelectionTracker;\n if (tracker && typeof tracker.refresh === 'function') {\n try {\n tracker.refresh();\n } catch (_) {}\n }\n }\n\n /**\n * Wrap a function with save/restore. Handles both sync and async\n * callbacks — for async, restore fires on `.finally()` so errors\n * don't leak selection state. Returns the callback's result.\n */\n }, {\n key: \"run\",\n value: function run(owner, fn) {\n var snap = SelectionGuard.save(owner);\n var result;\n try {\n result = fn();\n } catch (err) {\n SelectionGuard.restore(owner, snap);\n throw err;\n }\n if (result && typeof result.then === 'function') {\n return result.then(function (v) {\n SelectionGuard.restore(owner, snap);\n return v;\n }, function (err) {\n SelectionGuard.restore(owner, snap);\n throw err;\n });\n }\n SelectionGuard.restore(owner, snap);\n return result;\n }\n }]);\n}();\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextSelectionTracker);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextSelectionTracker.js?");
/***/ }),
/***/ "./src/includes/ToolbarPositioner.js":
/*!*******************************************!*\
!*** ./src/includes/ToolbarPositioner.js ***!
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * ToolbarPositioner — geometry + attachment utility for floating toolbars.\n *\n * Has two faces:\n *\n * (1) **Pure** `compute({ anchor | elementRect, toolbar, ... })` — returns\n * `{ top, left, side, didFlip, didClamp }` in viewport (fixed) coords.\n * Zero DOM access, zero side effects. Callers that already have a\n * rect in hand stay on this path (BaseElement's actions-box + image\n * toolbar paths — both pre-date the W0.4 anchor extension).\n *\n * (2) **Stateful** `attach({ anchor, target, ... })` — mounts a floating\n * toolbar DOM node on top of an anchor (Range, DOMRect, or HTMLElement)\n * and keeps it pinned through `window scroll` (capture) + `resize` +\n * `ResizeObserver` (Element anchors only). Returns a handle with\n * `{ dispose, reposition, getLast }`. Every selection-aware overlay\n * in W1-W4 mounts via this path.\n *\n * History:\n * - PLAN_EFFECT W0.3 (2026-04-19) — shipped `compute()` with `elementRect`.\n * - TEXT_INLINE_PLAN W0.4 (2026-04-20) — extends `compute()` to accept\n * `anchor: Range | DOMRect | HTMLElement`, adds `offset` / `flip` /\n * `collisionPadding` input aliases, adds `attach()` stateful helper.\n * Backward-compatible — `elementRect` + `gap` + `margin` callers keep\n * working unchanged.\n *\n * Iframe note:\n * Both `compute` and `attach` expect anchors already in the viewport\n * coordinate space of the window that holds the `target`. Callers whose\n * anchor lives inside an iframe MUST pre-shift the anchor's rect by the\n * iframe's `getBoundingClientRect()` — there is no one-size-fits-all\n * iframe math (e.g. the builder canvas iframe offsets differ from the\n * showcase page's inline anchors). Keeping the utility window-agnostic\n * makes iframe math a caller decision, not a hidden assumption.\n *\n * Algorithm (unchanged from W0.3):\n * 1. Resolve preferred side. If fits, keep. If not AND flip=true, try\n * the other side. If neither fits, pick the roomier side.\n * 2. Clamp horizontal into [margin, viewport.width - toolbar.width -\n * margin]. Toolbar wider than viewport-2m → snap to margin (caller\n * owns truncation).\n * 3. top = above → element.top - toolbar.height - gap;\n * below → element.top + element.height + gap.\n *\n * NOT for:\n * - Positioning of `.selected-box` — that hugs element geometry via\n * `matchingDomNode` (no flip needed).\n * - Anchored popovers with arrow pointers — use `AnchoredPopoverOverlay`\n * which owns arrow math. This utility stays arrow-agnostic.\n */\nvar ToolbarPositioner = /*#__PURE__*/function () {\n function ToolbarPositioner() {\n _classCallCheck(this, ToolbarPositioner);\n }\n return _createClass(ToolbarPositioner, null, [{\n key: \"DEFAULTS\",\n get:\n /**\n * Default input values. Exposed for test introspection + consumer\n * discoverability. Callers can merge partial input over these.\n */\n function get() {\n return {\n gap: 3,\n margin: 8,\n preferredSide: 'above',\n flip: true\n };\n }\n\n /**\n * Resolve an `anchor: Range | DOMRect | HTMLElement` into a plain\n * `{ top, left, width, height }` rect in viewport coordinates. Returned\n * values are numbers the positioner's math can consume directly.\n *\n * @param {Range|DOMRect|HTMLElement|{top,left,width,height}} anchor\n * @returns {{top:number,left:number,width:number,height:number}}\n */\n }, {\n key: \"rectFromAnchor\",\n value: function rectFromAnchor(anchor) {\n if (!anchor) {\n throw new Error('ToolbarPositioner.rectFromAnchor: anchor is required');\n }\n\n // Plain rect-shape passthrough — covers legacy `elementRect` callers\n // + DOMRect instances in older engines that expose { top, left, width,\n // height } but not the full Geometry interface.\n if (Number.isFinite(anchor.top) && Number.isFinite(anchor.left) && Number.isFinite(anchor.width) && Number.isFinite(anchor.height)) {\n return {\n top: anchor.top,\n left: anchor.left,\n width: anchor.width,\n height: anchor.height\n };\n }\n\n // Range / Element — `getBoundingClientRect` returns viewport coords\n // in the window where the node lives. If node is inside an iframe,\n // caller must translate; see the iframe-note in the class header.\n if (typeof anchor.getBoundingClientRect === 'function') {\n var r = anchor.getBoundingClientRect();\n return {\n top: r.top,\n left: r.left,\n width: r.width,\n height: r.height\n };\n }\n throw new Error('ToolbarPositioner.rectFromAnchor: anchor must be Range, DOMRect, ' + 'HTMLElement, or {top,left,width,height}. Got: ' + Object.prototype.toString.call(anchor));\n }\n\n /**\n * Compute a flipped + clamped toolbar position.\n *\n * @param {Object} input\n * @param {Range|DOMRect|HTMLElement} [input.anchor]\n * Preferred — any kind of anchor. Resolved via `rectFromAnchor()`.\n * @param {{top:number,left:number,width:number,height:number}} [input.elementRect]\n * Legacy — used when `anchor` is absent. Kept verbatim for\n * backward compatibility with W0.3 callers.\n * @param {{width:number,height:number}} input.toolbar\n * Desired toolbar outer dimensions in px.\n * @param {{width:number,height:number}} [input.viewport]\n * Viewport bounds. Falls back to `window.innerWidth/innerHeight`.\n * @param {number} [input.gap=3] / [input.offset]\n * Gap between element edge and toolbar. `offset` is a W0.4 alias.\n * @param {number} [input.margin=8] / [input.collisionPadding]\n * Minimum distance from viewport edge. `collisionPadding` is a W0.4 alias.\n * @param {'above'|'below'} [input.preferredSide='above']\n * @param {boolean} [input.flip=true]\n * When false, the positioner keeps `preferredSide` even if the toolbar\n * would overflow. `didFlip` is always false in that case. Useful for\n * tooltips/popovers that need a stable side (arrow direction).\n *\n * @returns {{\n * top: number,\n * left: number,\n * side: 'above'|'below',\n * didFlip: boolean,\n * didClamp: boolean,\n * }}\n *\n * @throws {Error} if required inputs are malformed — caller bug, not a\n * runtime condition the positioner should silently swallow.\n */\n }, {\n key: \"compute\",\n value: function compute(input) {\n if (!input || _typeof(input) !== 'object') {\n throw new Error('ToolbarPositioner.compute: input object required');\n }\n\n // Resolve rect — `anchor` wins over `elementRect` when both given.\n var elementRect;\n if (input.anchor !== undefined && input.anchor !== null) {\n elementRect = ToolbarPositioner.rectFromAnchor(input.anchor);\n } else if (input.elementRect) {\n elementRect = input.elementRect;\n } else {\n throw new Error('ToolbarPositioner.compute: anchor or elementRect required');\n }\n var toolbar = input.toolbar;\n if (!toolbar) {\n throw new Error('ToolbarPositioner.compute: toolbar required');\n }\n for (var _i = 0, _arr = ['top', 'left', 'width', 'height']; _i < _arr.length; _i++) {\n var k = _arr[_i];\n if (!Number.isFinite(elementRect[k])) {\n throw new Error(\"ToolbarPositioner.compute: elementRect.\".concat(k, \" must be finite number\"));\n }\n }\n for (var _i2 = 0, _arr2 = ['width', 'height']; _i2 < _arr2.length; _i2++) {\n var _k = _arr2[_i2];\n if (!Number.isFinite(toolbar[_k]) || toolbar[_k] < 0) {\n throw new Error(\"ToolbarPositioner.compute: toolbar.\".concat(_k, \" must be finite non-negative number\"));\n }\n }\n\n // Input aliases — `offset` → `gap`, `collisionPadding` → `margin`.\n // Legacy `gap` / `margin` still win when both are passed (explicit\n // old-world caller intent).\n var gap = Number.isFinite(input.gap) ? input.gap : Number.isFinite(input.offset) ? input.offset : ToolbarPositioner.DEFAULTS.gap;\n var margin = Number.isFinite(input.margin) ? input.margin : Number.isFinite(input.collisionPadding) ? input.collisionPadding : ToolbarPositioner.DEFAULTS.margin;\n var preferredSide = input.preferredSide === 'below' ? 'below' : ToolbarPositioner.DEFAULTS.preferredSide;\n var flipEnabled = input.flip === undefined ? ToolbarPositioner.DEFAULTS.flip : !!input.flip;\n var viewport = input.viewport || {\n // Fall back to window dims; tests should pass explicit viewport.\n width: typeof window !== 'undefined' ? window.innerWidth : 0,\n height: typeof window !== 'undefined' ? window.innerHeight : 0\n };\n if (!Number.isFinite(viewport.width) || !Number.isFinite(viewport.height)) {\n throw new Error('ToolbarPositioner.compute: viewport.width/height must be finite numbers');\n }\n\n // Space available on each side of the element.\n var spaceAbove = elementRect.top - gap;\n var spaceBelow = viewport.height - (elementRect.top + elementRect.height) - gap;\n var fitsAbove = spaceAbove >= toolbar.height;\n var fitsBelow = spaceBelow >= toolbar.height;\n var side;\n var didFlip = false;\n if (!flipEnabled) {\n // Flip disabled — honor preferredSide unconditionally.\n side = preferredSide;\n } else if (preferredSide === 'above') {\n if (fitsAbove) {\n side = 'above';\n } else if (fitsBelow) {\n side = 'below';\n didFlip = true;\n } else {\n // Neither fits. Pick the roomier side — lesser evil.\n side = spaceBelow > spaceAbove ? 'below' : 'above';\n didFlip = side !== preferredSide;\n }\n } else {\n // preferredSide === 'below'\n if (fitsBelow) {\n side = 'below';\n } else if (fitsAbove) {\n side = 'above';\n didFlip = true;\n } else {\n side = spaceAbove > spaceBelow ? 'above' : 'below';\n didFlip = side !== preferredSide;\n }\n }\n var top = side === 'above' ? elementRect.top - toolbar.height - gap : elementRect.top + elementRect.height + gap;\n\n // Horizontal clamp. Raw left = element's left edge (toolbar\n // anchored to the start of the element). Callers that want a\n // centered / right-aligned anchor can pre-shift elementRect or\n // anchor before calling — keeps the utility anchor-agnostic.\n var rawLeft = elementRect.left;\n var maxLeft = Math.max(margin, viewport.width - toolbar.width - margin);\n var minLeft = margin;\n var left;\n var didClamp = false;\n if (rawLeft < minLeft) {\n left = minLeft;\n didClamp = true;\n } else if (rawLeft > maxLeft) {\n left = maxLeft;\n didClamp = true;\n } else {\n left = rawLeft;\n }\n return {\n top: top,\n left: left,\n side: side,\n didFlip: didFlip,\n didClamp: didClamp\n };\n }\n\n /**\n * Mount a floating toolbar `target` on top of `anchor` and keep it\n * pinned through viewport scroll / resize / anchor resize.\n *\n * Side effects on `target`:\n * - Sets `position: fixed` + computed `top` / `left`.\n * - Adds `data-side` / `data-did-flip` / `data-did-clamp` diagnostic\n * attributes mirroring the last compute result (CSS can tint on\n * non-preferred side).\n * - Does NOT touch display / visibility / z-index — caller owns\n * those (we'd overwrite a host's own style discipline otherwise).\n *\n * Listeners installed:\n * - `window.scroll` on capture phase — catches nested scroll\n * containers without re-attaching per container.\n * - `window.resize`.\n * - `ResizeObserver` on `anchor` when anchor is an HTMLElement.\n * Range and DOMRect anchors have no observable size source — the\n * caller must `handle.reposition()` after DOM mutations that\n * change the range's rect (selectionchange covers most).\n *\n * @param {Object} input\n * @param {Range|DOMRect|HTMLElement|Function} input.anchor\n * A live Range / Element whose rect the toolbar follows, a fixed\n * DOMRect, or a `() => rectShape | Range | DOMRect | Element`\n * callback the positioner invokes on every reposition (useful\n * when the anchor is derived, e.g. \"last selection range\").\n * @param {HTMLElement} input.target\n * The DOM node to position. Must already be attached to the\n * document (the positioner does not append it).\n * @param {{width:number,height:number}} [input.viewport]\n * Override viewport dims (tests + iframe contexts).\n * @param {number} [input.offset] Alias for gap.\n * @param {number} [input.gap]\n * @param {number} [input.collisionPadding] Alias for margin.\n * @param {number} [input.margin]\n * @param {'above'|'below'} [input.preferredSide]\n * @param {boolean} [input.flip]\n * @param {Function} [input.onUpdate] Called after every reposition with the compute result.\n *\n * @returns {{\n * dispose: () => void,\n * reposition: () => void,\n * getLast: () => Object | null,\n * }}\n */\n }, {\n key: \"attach\",\n value: function attach(input) {\n if (!input || _typeof(input) !== 'object') {\n throw new Error('ToolbarPositioner.attach: input object required');\n }\n var anchor = input.anchor,\n target = input.target,\n onUpdate = input.onUpdate;\n if (!anchor) {\n throw new Error('ToolbarPositioner.attach: anchor is required');\n }\n if (!target || typeof target.getBoundingClientRect !== 'function') {\n throw new Error('ToolbarPositioner.attach: target must be an HTMLElement');\n }\n var resolveAnchor = typeof anchor === 'function' ? anchor : function () {\n return anchor;\n };\n var last = null;\n var disposed = false;\n var reposition = function reposition() {\n if (disposed) return;\n\n // Resolve anchor afresh — for Range anchors the caller-held\n // range may have shifted; for callback anchors we call every\n // reposition.\n var resolved;\n try {\n resolved = resolveAnchor();\n } catch (err) {\n // Anchor resolution failure (detached range, null target) is\n // a runtime condition — skip this frame, keep listening. No\n // swallowed silent failure: surface via console.warn so a\n // developer investigating a stuck toolbar sees it (HARD\n // RULE T6).\n // eslint-disable-next-line no-console\n if (typeof console !== 'undefined') console.warn('[bjs] ToolbarPositioner.attach anchor resolver threw:', err);\n return;\n }\n if (!resolved) return;\n\n // Toolbar size comes from the target's own rect — callers don't\n // have to feed dimensions in. Measured pre-position to avoid\n // reading a post-position rect (which would depend on the last\n // compute's output and drift).\n var toolbarRect = target.getBoundingClientRect();\n var toolbar = {\n width: toolbarRect.width,\n height: toolbarRect.height\n };\n var pos;\n try {\n pos = ToolbarPositioner.compute({\n anchor: resolved,\n toolbar: toolbar,\n viewport: input.viewport,\n gap: input.gap,\n offset: input.offset,\n margin: input.margin,\n collisionPadding: input.collisionPadding,\n preferredSide: input.preferredSide,\n flip: input.flip\n });\n } catch (err) {\n // eslint-disable-next-line no-console\n if (typeof console !== 'undefined') console.warn('[bjs] ToolbarPositioner.attach compute threw:', err);\n return;\n }\n last = pos;\n target.style.position = 'fixed';\n target.style.top = pos.top + 'px';\n target.style.left = pos.left + 'px';\n target.dataset.side = pos.side;\n target.dataset.didFlip = String(pos.didFlip);\n target.dataset.didClamp = String(pos.didClamp);\n if (typeof onUpdate === 'function') {\n try {\n onUpdate(pos);\n } catch (err) {\n // eslint-disable-next-line no-console\n if (typeof console !== 'undefined') console.warn('[bjs] ToolbarPositioner.attach onUpdate threw:', err);\n }\n }\n };\n\n // Scroll listener in capture phase — catches nested scroll\n // containers (sidebar, panel) without needing per-container\n // re-wiring. Resize on window. Element anchors add a\n // ResizeObserver so the toolbar follows element size changes\n // (e.g. image resize popups).\n var win = typeof window !== 'undefined' ? window : null;\n if (win) {\n win.addEventListener('scroll', reposition, true);\n win.addEventListener('resize', reposition);\n }\n var resizeObserver = null;\n if (anchor && anchor.nodeType === 1 /* ELEMENT_NODE */ && typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(reposition);\n resizeObserver.observe(anchor);\n }\n\n // Initial position.\n reposition();\n return {\n dispose: function dispose() {\n if (disposed) return;\n disposed = true;\n if (win) {\n win.removeEventListener('scroll', reposition, true);\n win.removeEventListener('resize', reposition);\n }\n if (resizeObserver) {\n resizeObserver.disconnect();\n resizeObserver = null;\n }\n },\n reposition: reposition,\n getLast: function getLast() {\n return last;\n }\n };\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ToolbarPositioner);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ToolbarPositioner.js?");
/***/ }),
/***/ "./src/includes/TooltipManager.js":
/*!****************************************!*\
!*** ./src/includes/TooltipManager.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ getTooltipManager: () => (/* binding */ getTooltipManager)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/*\n * TooltipManager — singleton DOM tooltip for BuilderJS.\n *\n * Why a JS manager instead of pure CSS `::after` pseudo-elements:\n * CSS pseudo-elements CAN'T escape an ancestor that clips overflow\n * (sidebars, scrollable panels, popovers). The tooltip gets visually\n * truncated at the clipping edge — exactly the \"Enable CSS crop &\n * fo…\" bug the user reported 2026-04-19. Portalling the tooltip into\n * `<body>` with `position: fixed` bypasses every ancestor's clip.\n *\n * Attributes honoured:\n * - data-tooltip=\"Text\" (required)\n * - data-tooltip-placement=\"top|bottom|left|right\" (default \"top\")\n * - data-tooltip-align=\"start|center|end\" (default \"center\")\n * - data-tooltip-disabled (hides tooltip)\n *\n * Arrow points at the trigger's center regardless of alignment — the\n * whole reason callers opt into `align=end` is that the tooltip body\n * should slide sideways but the arrow must still unambiguously\n * identify which button it belongs to.\n *\n * Showcase docs: demo/ui-showcase.html — \"Tooltips\" section.\n */\n\nvar PLACEMENTS = ['top', 'bottom', 'left', 'right'];\nvar ALIGNS = ['start', 'center', 'end'];\nvar GAP = 8; // px between trigger edge and tooltip\nvar ARROW_SIZE = 5; // matches CSS ::before triangle border width\nvar VIEWPORT_PADDING = 4; // keep tooltip this far from viewport edges\nvar TooltipManager = /*#__PURE__*/function () {\n function TooltipManager() {\n _classCallCheck(this, TooltipManager);\n this._tip = null;\n this._arrow = null;\n this._target = null;\n this._rafId = null;\n\n // Bound handlers so add/removeEventListener pair up.\n this._onPointerOver = this._onPointerOver.bind(this);\n this._onPointerOut = this._onPointerOut.bind(this);\n this._onFocusIn = this._onFocusIn.bind(this);\n this._onFocusOut = this._onFocusOut.bind(this);\n this._onReposition = this._onReposition.bind(this);\n\n // Delegated, capture-phase so we catch events regardless of\n // which subtree the trigger lives in (sidebar, iframe wrapper,\n // canvas overlay, etc.).\n document.addEventListener('pointerover', this._onPointerOver, true);\n document.addEventListener('pointerout', this._onPointerOut, true);\n document.addEventListener('focusin', this._onFocusIn, true);\n document.addEventListener('focusout', this._onFocusOut, true);\n }\n\n /** Find the closest [data-tooltip] ancestor of `node`, honoring\n * Shadow DOM via composedPath when the event provides one. */\n return _createClass(TooltipManager, [{\n key: \"_resolveTrigger\",\n value: function _resolveTrigger(node) {\n if (!node || typeof node.closest !== 'function') return null;\n var t = node.closest('[data-tooltip]');\n if (!t) return null;\n if (t.hasAttribute('data-tooltip-disabled')) return null;\n if (!t.getAttribute('data-tooltip')) return null;\n return t;\n }\n }, {\n key: \"_onPointerOver\",\n value: function _onPointerOver(e) {\n var t = this._resolveTrigger(e.target);\n if (!t || t === this._target) return;\n this._show(t);\n }\n }, {\n key: \"_onPointerOut\",\n value: function _onPointerOut(e) {\n if (!this._target) return;\n // Treat as \"left the trigger\" only when relatedTarget sits OUTSIDE\n // the current trigger. Moving between children of the trigger\n // should keep the tooltip open.\n if (e.relatedTarget && this._target.contains(e.relatedTarget)) return;\n this._hide();\n }\n }, {\n key: \"_onFocusIn\",\n value: function _onFocusIn(e) {\n var t = this._resolveTrigger(e.target);\n if (!t) return;\n this._show(t);\n }\n }, {\n key: \"_onFocusOut\",\n value: function _onFocusOut() {\n // Keyboard focus moved away — always hide. Hover handlers will\n // re-show on the next pointerover if the pointer still sits on\n // the original trigger.\n this._hide();\n }\n }, {\n key: \"_onReposition\",\n value: function _onReposition() {\n var _this = this;\n if (!this._target || !document.body.contains(this._target)) {\n this._hide();\n return;\n }\n // Coalesce scroll/resize storms into one rAF frame.\n if (this._rafId) return;\n this._rafId = requestAnimationFrame(function () {\n _this._rafId = null;\n _this._position();\n });\n }\n }, {\n key: \"_ensureTip\",\n value: function _ensureTip() {\n if (this._tip) return;\n this._tip = document.createElement('div');\n this._tip.className = 'bjs-tooltip';\n this._tip.setAttribute('role', 'tooltip');\n this._arrow = document.createElement('div');\n this._arrow.className = 'bjs-tooltip-arrow';\n this._tip.appendChild(this._arrow);\n this._label = document.createElement('span');\n this._label.className = 'bjs-tooltip-label';\n this._tip.appendChild(this._label);\n document.body.appendChild(this._tip);\n }\n }, {\n key: \"_show\",\n value: function _show(target) {\n this._ensureTip();\n var text = target.getAttribute('data-tooltip') || '';\n var placement = PLACEMENTS.includes(target.getAttribute('data-tooltip-placement')) ? target.getAttribute('data-tooltip-placement') : 'top';\n var align = ALIGNS.includes(target.getAttribute('data-tooltip-align')) ? target.getAttribute('data-tooltip-align') : 'center';\n this._target = target;\n this._label.textContent = text;\n this._tip.dataset.placement = placement;\n this._tip.dataset.align = align;\n this._tip.classList.add('is-visible');\n this._position();\n\n // Reposition only while visible. Capture-phase so we catch\n // scrolls inside the sidebar + iframe + main doc.\n window.addEventListener('scroll', this._onReposition, true);\n window.addEventListener('resize', this._onReposition, true);\n }\n }, {\n key: \"_hide\",\n value: function _hide() {\n if (!this._tip) return;\n this._tip.classList.remove('is-visible');\n this._target = null;\n if (this._rafId) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n window.removeEventListener('scroll', this._onReposition, true);\n window.removeEventListener('resize', this._onReposition, true);\n }\n }, {\n key: \"_position\",\n value: function _position() {\n if (!this._tip || !this._target) return;\n\n // Hide while measuring so the tip's own rect doesn't reflect an\n // off-screen position that shifted the document. `visibility:\n // hidden` keeps it measurable without showing a flash.\n var prev = this._tip.style.visibility;\n this._tip.style.visibility = 'hidden';\n this._tip.style.top = '0px';\n this._tip.style.left = '0px';\n var tr = this._target.getBoundingClientRect();\n var size = this._tip.getBoundingClientRect();\n var placement = this._tip.dataset.placement || 'top';\n var align = this._tip.dataset.align || 'center';\n var top = 0;\n var left = 0;\n\n // 1. Axis-of-placement: distance from the trigger edge.\n if (placement === 'top') top = tr.top - size.height - GAP;else if (placement === 'bottom') top = tr.bottom + GAP;else if (placement === 'left') left = tr.left - size.width - GAP;else left = tr.right + GAP;\n\n // 2. Axis-of-alignment: where along the trigger edge we anchor.\n if (placement === 'top' || placement === 'bottom') {\n if (align === 'start') left = tr.left;else if (align === 'end') left = tr.right - size.width;else left = tr.left + (tr.width - size.width) / 2;\n } else {\n if (align === 'start') top = tr.top;else if (align === 'end') top = tr.bottom - size.height;else top = tr.top + (tr.height - size.height) / 2;\n }\n\n // 3. Viewport clamp — safety net so a `center`-aligned tooltip\n // near the right rail still stays on-screen. Caller can still\n // flip `align=end` to avoid the clamp arrow/body mismatch.\n var maxLeft = window.innerWidth - size.width - VIEWPORT_PADDING;\n var maxTop = window.innerHeight - size.height - VIEWPORT_PADDING;\n left = Math.max(VIEWPORT_PADDING, Math.min(left, maxLeft));\n top = Math.max(VIEWPORT_PADDING, Math.min(top, maxTop));\n this._tip.style.left = left + 'px';\n this._tip.style.top = top + 'px';\n\n // 4. Arrow stays pointed at the trigger's center. After body\n // clamping, the offset between trigger-center and tip-edge\n // can shift, so recompute arrow offset each time.\n this._positionArrow(tr, size, left, top, placement);\n this._tip.style.visibility = prev || '';\n }\n }, {\n key: \"_positionArrow\",\n value: function _positionArrow(triggerRect, tipSize, tipLeft, tipTop, placement) {\n if (!this._arrow) return;\n var arrow = this._arrow;\n // Reset\n arrow.style.top = arrow.style.left = arrow.style.right = arrow.style.bottom = '';\n if (placement === 'top' || placement === 'bottom') {\n var triggerCenterX = triggerRect.left + triggerRect.width / 2;\n var offsetX = Math.max(ARROW_SIZE * 2, Math.min(triggerCenterX - tipLeft, tipSize.width - ARROW_SIZE * 2));\n arrow.style.left = offsetX + 'px';\n } else {\n var triggerCenterY = triggerRect.top + triggerRect.height / 2;\n var offsetY = Math.max(ARROW_SIZE * 2, Math.min(triggerCenterY - tipTop, tipSize.height - ARROW_SIZE * 2));\n arrow.style.top = offsetY + 'px';\n }\n }\n\n /** Force-refresh position. Callers that move/resize a trigger\n * synchronously while the tooltip is up (rare — most state flips\n * come from clicks that already trigger pointerout → hide) can\n * call this to avoid a stale frame. */\n }, {\n key: \"refresh\",\n value: function refresh() {\n if (this._target) this._position();\n }\n }, {\n key: \"destroy\",\n value: function destroy() {\n this._hide();\n document.removeEventListener('pointerover', this._onPointerOver, true);\n document.removeEventListener('pointerout', this._onPointerOut, true);\n document.removeEventListener('focusin', this._onFocusIn, true);\n document.removeEventListener('focusout', this._onFocusOut, true);\n if (this._tip && this._tip.parentNode) this._tip.parentNode.removeChild(this._tip);\n this._tip = this._arrow = this._label = this._target = null;\n }\n }]);\n}(); // Singleton — constructor side-effects install the delegated listeners.\n// Callers just import this file; no `new` needed at use sites.\nvar _instance = null;\nfunction getTooltipManager() {\n if (!_instance && typeof document !== 'undefined') {\n _instance = new TooltipManager();\n }\n return _instance;\n}\n\n// Auto-activate on module load. The constructor only attaches passive\n// document listeners — zero work happens until a `[data-tooltip]`\n// element is hovered. This lets pages that load `dist/builder.js`\n// (e.g. ui-showcase.html) benefit from tooltips without needing to\n// construct a full Builder instance.\nif (typeof document !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', function () {\n return getTooltipManager();\n }, {\n once: true\n });\n } else {\n getTooltipManager();\n }\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TooltipManager);\n\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TooltipManager.js?");
/***/ }),
/***/ "./src/includes/UIManager.js":
/*!***********************************!*\
!*** ./src/includes/UIManager.js ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\n/* harmony import */ var _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PointerCaptureRegistry.js */ \"./src/includes/PointerCaptureRegistry.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\nvar UIManager = /*#__PURE__*/function () {\n function UIManager(builder) {\n _classCallCheck(this, UIManager);\n this.builder = builder;\n this.elements = [];\n this.hoveringElements = [];\n this.dragOveringElements = [];\n this.draggableItems = [];\n this.draggingItem = null;\n }\n return _createClass(UIManager, [{\n key: \"init\",\n value: function init() {\n var _this = this;\n // clear drag over elements\n this.elements = [];\n this.hoveringElements = [];\n this.dragOveringElements = [];\n this.draggableItems = [];\n this.draggingItem = null;\n\n // remove effects\n this.elements.forEach(function (el) {\n el.removeHoverHightlight();\n el.removeDropHighlight();\n el.removeContainerHightlight();\n el.removeContainerDropHightlight();\n });\n\n // ─────────────────────────────────────────────────────────────────\n // CLEAR-HOVER-ON-LEAVE-CANVAS\n // ─────────────────────────────────────────────────────────────────\n //\n // Hover highlights, container highlights and the drag-anchor live\n // inside the builder iframe. Their show/hide is driven by mouseover\n // / mouseout listeners attached to elements *inside* that iframe\n // (see handleElementEvents). Those listeners are scoped to the\n // iframe document, so once the mouse crosses the iframe boundary\n // into the parent document (sidebar, toolbar, gray canvas around\n // the iframe, anywhere) the iframe stops receiving mouse events\n // and the hover state can get \"stuck\" — the last hovered block\n // keeps its highlight and the \"Block\" tag stays floating even\n // though the cursor is now over the WidgetsBox or the toolbar.\n //\n // Fix: listen for mouseover on the parent document. Anything that\n // is NOT the iframe element itself means the mouse is somewhere in\n // the parent doc — i.e. it has left the canvas — so we wipe all\n // hover state. The previous implementation only fired when the\n // target was exactly `mainContainer` (the gray grid wrapper around\n // the iframe), which left every other parent-doc region (sidebar,\n // toolbar, anywhere outside #MainContainer) as dead zones where\n // the hover state never got cleared.\n //\n // Why `e.target !== this.builder.iframe` is the right test:\n // • Mouse over iframe area → e.target == iframe → DON'T clear\n // (mouse is back on the canvas; iframe-internal listeners\n // take over the hover state).\n // • Mouse over any other parent-doc element → CLEAR.\n // • Mouse moving inside the iframe contents → no parent-doc\n // mouseover at all (separate document), so this handler is\n // not invoked and the iframe-internal listeners run instead.\n //\n // Regression: e2e/hover-clear-on-leave-canvas.spec.js\n // ─────────────────────────────────────────────────────────────────\n document.addEventListener('mouseover', function (e) {\n if (e.target === _this.builder.iframe) {\n // Mouse is back over the canvas — let iframe-internal\n // listeners handle the hover state.\n return;\n }\n\n // ─────────────────────────────────────────────────────────\n // EXEMPT DRAG ANCHORS — CRITICAL for Chrome + Safari\n // ─────────────────────────────────────────────────────────\n // Drag anchors (the floating \"hand\" handles) live in the\n // MAIN document (document.body), so any mouseover on them\n // is a parent-doc event. Without this exemption, the\n // clear-on-leave-iframe logic below would treat hovering\n // the hand icon as \"mouse has left the canvas\", wipe the\n // hover state, and hide the anchor — producing a rapid\n // flicker loop and making the hand impossible to grab\n // (especially bad on Safari where the anchor vanishes\n // between repaints).\n //\n // Skip the clear for anything that IS a drag-anchor or\n // sits INSIDE one, plus the element settings toolbar\n // (mc-element-controls) which also lives outside the\n // iframe and must not nuke hover state.\n // ─────────────────────────────────────────────────────────\n if (e.target && typeof e.target.closest === 'function') {\n if (e.target.closest('.drag-anchor')) {\n return;\n }\n if (e.target.closest('[data-element-controls]')) {\n return;\n }\n // ─────────────────────────────────────────────────────\n // Phase 1.1 (§4.I6): canvas overlays live in parent doc\n // same as drag anchors. Without this exemption, hovering\n // any `.bjs-ovl` node would wipe hover state → overlay\n // unmounts → cursor back on iframe → overlay re-mounts\n // → flicker loop. BaseOverlay.mount() always adds the\n // class. See docs/archived/OVERLAY_PLAN.md §4.I6.\n // ─────────────────────────────────────────────────────\n if (e.target.closest('.bjs-ovl')) {\n // Phase 1.6 — additionally cancel any pending 50 ms\n // unmount timer. Cursor left the iframe block (mouseout\n // fired + scheduled the timeout) and crossed onto the\n // parent-doc overlay. Without this cancel, the timeout\n // still fires and unmounts the overlay out from under\n // the cursor (the `.bjs-ovl` exemption above only\n // prevents the PARENT-DOC hover-clear from also wiping\n // state — it doesn't touch the iframe-mouseout timer).\n // Legacy `.drag-anchor` worked because hideDragAnchor\n // was `display:none`; the DOM stayed alive for re-entry.\n // Overlay path destroys the DOM, so we must keep the\n // overlay ALIVE while the cursor is on it.\n // See docs/core/OVERLAY.md §7.4 + OVERLAY_PLAN.md §5 D53.\n if (_this._hideTimeout) {\n clearTimeout(_this._hideTimeout);\n _this._hideTimeout = null;\n }\n return;\n }\n }\n\n // Mouse is somewhere in the parent document outside the iframe\n // (sidebar, toolbar, anywhere). Wipe all hover state so nothing\n // stays \"stuck\" on a block the user is no longer pointing at.\n _this.elements.forEach(function (el) {\n el.removeHoverHightlight();\n if (el.container) {\n el.container.removeContainerHightlight();\n }\n if (el.getDragAnchor) {\n el.hideDragAnchor();\n }\n\n // Phase 1.6 — unmount 'hover'-trigger overlays too. Legacy\n // `hideDragAnchor()` is enough for widgets (keeps their DOM\n // but toggles display). Blocks moved to the overlay path —\n // their anchor DOM must be destroyed when cursor leaves\n // the canvas entirely (sidebar / toolbar / anywhere outside\n // iframe + outside `.bjs-ovl`). Without this, the block\n // drag anchor stays mounted in parent doc after the cursor\n // has left — next canvas hover would create a duplicate.\n el.unmountOverlays('hover');\n });\n _this.hoveringElements = [];\n // Also cancel any pending mouseout 50 ms timeout — the parent-doc\n // wipe above is the authoritative \"mouse is no longer on any\n // canvas element\" signal; any scheduled cleanup from an earlier\n // iframe-block mouseout is redundant + would race against the\n // next mouseover if the user comes back.\n if (_this._hideTimeout) {\n clearTimeout(_this._hideTimeout);\n _this._hideTimeout = null;\n }\n });\n }\n }, {\n key: \"addElement\",\n value: function addElement(element) {\n // Idempotent. Pre-fix this push was unguarded — every cascade\n // re-render of a Block called addElement() on each child again,\n // accumulating duplicates in `this.elements` and re-triggering\n // hover-listener teardown on every mouseover (the forEach at\n // line ~251 iterates the array). With the new surgical\n // structural mutations (BlockElement / PageElement /\n // CellElement removeElement + addBlock*) duplicate pushes\n // should no longer happen, but the guard freezes the invariant.\n // `handleElementEvents` already had its own `eventHandled` guard\n // so the DOM-listener leak was self-limited; the array bloat\n // wasn't.\n if (this.elements.indexOf(element) !== -1) return;\n this.elements.push(element);\n this.handleElementEvents(element);\n }\n }, {\n key: \"handleElementEvents\",\n value: function handleElementEvents(element) {\n var _this2 = this;\n if (!element.eventHandled) {\n element.domNode.addEventListener('mouseover', function (e) {\n e.preventDefault();\n _this2.mouseover(element);\n });\n element.domNode.addEventListener('mouseout', function (e) {\n e.preventDefault();\n _this2.mouseout(element, e);\n });\n\n // Droppable elements\n if (element.isDroppable()) {\n // dragover event\n element.domNode.addEventListener('dragover', function (e) {\n e.preventDefault();\n _this2.dragOver(element, e);\n });\n\n // dragleave event\n element.domNode.addEventListener('dragleave', function () {\n _this2.dragLeave(element);\n });\n\n // Drop draggable element\n element.domNode.addEventListener('drop', function (e) {\n e.preventDefault();\n _this2.drop(element, e);\n });\n }\n\n // Select element\n element.domNode.addEventListener('click', function (e) {\n e.preventDefault();\n var topElement = _this2.getTopHoveringElement();\n\n // only click on top element\n if (topElement != element) {\n return;\n }\n\n //\n _this2.builder.selectElement(topElement);\n });\n element.eventHandled = true;\n }\n }\n }, {\n key: \"mouseover\",\n value: function mouseover(element) {\n var _this3 = this;\n // Phase 1.1 (§4.I7 placement): active-drag guard MUST go FIRST, before\n // the isHoverable short-circuit. During any pointer-driven drag, freeze\n // hover recompute entirely — otherwise element.domNode mouseover events\n // fire under the captured pointer and churn state beneath the drag.\n // See docs/core/OVERLAY.md §10 + docs/archived/OVERLAY_PLAN.md §4.I7.\n if (_PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasActive()) return;\n\n // Container-only elements (Grid, Cell) are not hoverable from the canvas.\n // They can still be selected via breadcrumb or builder.selectElement().\n if (!element.isHoverable()) {\n return;\n }\n\n // Cancel any pending mouseout hide (prevents flicker when drag anchor overlaps iframe)\n if (this._hideTimeout) {\n clearTimeout(this._hideTimeout);\n this._hideTimeout = null;\n }\n this.addHoveringElement(element);\n\n // MOUSEOUT ALL\n this.elements.forEach(function (el) {\n // remove hover highlight\n el.removeHoverHightlight();\n\n // remove container hover highlight\n if (el.container) {\n // Remove hover highlight to its container\n el.container.removeContainerHightlight();\n }\n\n // hide drag anchor\n if (el.getDragAnchor) {\n el.hideDragAnchor();\n }\n\n // Phase 1.1: tear down any 'hover'-trigger overlays. Idempotent\n // if no overlays are live (default getOverlays() returns []).\n // See docs/core/OVERLAY.md §3 mount/unmount contract.\n el.unmountOverlays('hover');\n });\n\n // Only add a hover highlight to the last nested element.\n this.hoveringElements.forEach(function (el) {\n if (el == _this3.getTopHoveringElement()) {\n el.addHoverHightlight();\n\n // PLAN_EFFECT W2.1b — when the hovered element is the\n // currently-selected one, skip the container padding-\n // region highlight too. Its 4-box dashed/striped pattern\n // duplicates the selection identity + user feedback\n // 2026-04-19 \"container highlight leak on selection\"\n // wants it gone in this case.\n if (el.container && _this3.builder.getSelectedElement() !== el) {\n el.container.addContainerHightlight(el);\n } else if (el.container) {\n el.container.removeContainerHightlight();\n }\n } else {\n el.removeHoverHightlight();\n }\n });\n\n // Phase 1.6 — mount the 'hover'-trigger overlay on the NEAREST\n // ancestor in the hover chain that declares a `'hover'`-trigger\n // overlay. `hoveringElements` is ordered deepest→root\n // (getTopHoveringElement() returns [0]), so walking forward from 0\n // gives the closest-to-cursor element.\n //\n // Why \"nearest\" not \"top-only\" or \"all ancestors\":\n // - top-only (Phase 1.1 original) breaks the block drag-anchor UX —\n // hovering a button inside a block would never mount the block's\n // anchor.\n // - all-ancestors (legacy `showDragAnchor()` semantic) stacks\n // multiple block anchors when blocks are nested (e.g. BlockA →\n // Grid → Cell → BlockB). The user sees two hand icons at once —\n // visually noisy + ambiguous for the drag target.\n // - nearest (this) — exactly one anchor per hover, on the closest\n // block to the cursor. Matches Webflow / Notion. Future 'hover'\n // overlays get the same single-mount contract.\n //\n // Critical: filter by `getTrigger() === 'hover'`, not just\n // `getOverlays().length > 0`. Elements with only `'select'`-trigger\n // overlays (e.g. ImageElement's 6 actions/corners/crop overlays)\n // MUST NOT short-circuit the walk — otherwise a block wrapping an\n // image would never mount its hover overlay because the Image\n // stops the walk at index 0.\n //\n // Idempotent via mountOverlays guard (D9); zero overhead for elements\n // that don't opt in (default getOverlays() returns []).\n // See docs/core/OVERLAY.md §3 + §7.4 + §5 Phase 1.6 D47.\n for (var i = 0; i < this.hoveringElements.length; i++) {\n var ee = this.hoveringElements[i];\n if (typeof ee.getOverlays !== 'function') continue;\n var hoverOverlays = ee.getOverlays().some(function (o) {\n return typeof o.getTrigger === 'function' && o.getTrigger() === 'hover';\n });\n if (hoverOverlays) {\n ee.mountOverlays('hover');\n break;\n }\n }\n }\n }, {\n key: \"mouseout\",\n value: function mouseout(element, e) {\n var _this4 = this;\n // Phase 1.1 (§4.I7 placement): active-drag guard. During a captured\n // pointer drag, skip mouseout cleanup entirely — the drag is authoritative\n // and the deferred 50ms hide below would race with pointerup.\n // The 50ms debounce stays (§4.I1 — idle-hover fix, independent concern).\n // See docs/core/OVERLAY.md §10.\n if (_PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasActive()) return;\n this.removeHoveringElement(element);\n\n // ─────────────────────────────────────────────────────────────────\n // CRITICAL: 50ms delay — NEVER remove this\n // ─────────────────────────────────────────────────────────────────\n // Drag anchor (hand icon) is fixed-positioned in the MAIN document\n // and overlaps the iframe boundary. When the cursor crosses from\n // the block (inside iframe) onto the drag anchor (outside iframe),\n // both Chrome and Safari fire a rapid mouseout→mouseover loop:\n //\n // iframe-block.mouseout → hideDragAnchor → anchor disappears\n // ↓ cursor now over empty gap, re-enters iframe\n // iframe-block.mouseover → showDragAnchor → anchor reappears\n // ↓ cursor now over anchor again\n // iframe-block.mouseout → ... (LOOP = flicker + ungrab-able)\n //\n // Safari makes it worse: with 0ms debounce it never even renders\n // the hand icon because the mouseout fires between paints.\n //\n // The 50ms deferred hide gives the re-entering mouseover enough\n // time to cancel the pending hide, stabilising the anchor while\n // the cursor is parked over it. See commit 4b8f46ec for the\n // original Chrome fix — this block restores its 50ms delay that\n // was silently dropped in a later refactor.\n // ─────────────────────────────────────────────────────────────────\n if (this._hideTimeout) {\n clearTimeout(this._hideTimeout);\n }\n this._hideTimeout = setTimeout(function () {\n _this4._hideTimeout = null;\n\n // Skip if element was re-added to hovering list (mouseover fired before this timeout)\n if (_this4.hoveringElements.includes(element)) {\n return;\n }\n\n // Remove hover highlight from the element that the mouse left\n element.removeHoverHightlight();\n\n // Remove container highlight\n if (element.container) {\n element.container.removeContainerHightlight();\n }\n\n // Hide drag anchor\n if (element.getDragAnchor) {\n element.hideDragAnchor();\n }\n\n // Phase 1.1: tear down 'hover'-trigger overlays. Default\n // getOverlays() returns [] → no-op for non-opt-in elements.\n element.unmountOverlays('hover');\n\n // Phase 1.6 — sweep 'hover' overlays off any element that's no\n // longer in the hovering chain. The per-element unmount above\n // only catches the LAST-out element's overlays (because the\n // debounce timeout is shared, so intermediate mouseouts get\n // their timers cancelled and never reach this body). Without\n // this sweep, an overlay mounted on an ancestor via the\n // nearest-mount rule in mouseover gets orphaned when the\n // cursor leaves its subtree via a descendant's mouseout.\n _this4.elements.forEach(function (el) {\n if (el !== element && !_this4.hoveringElements.includes(el)) {\n el.unmountOverlays('hover');\n }\n });\n\n // If there are still hovering elements, re-highlight the new top element\n if (_this4.hoveringElements.length > 0) {\n var topElement = _this4.getTopHoveringElement();\n if (topElement) {\n topElement.addHoverHightlight();\n if (topElement.container) {\n topElement.container.addContainerHightlight(topElement);\n }\n if (topElement.getDragAnchor) {\n topElement.showDragAnchor();\n }\n }\n }\n }, 50);\n }\n }, {\n key: \"addHoveringElement\",\n value: function addHoveringElement(element) {\n this.hoveringElements.push(element);\n }\n }, {\n key: \"removeHoveringElement\",\n value: function removeHoveringElement(element) {\n this.hoveringElements = this.hoveringElements.filter(function (e) {\n return e !== element;\n });\n }\n }, {\n key: \"getTopHoveringElement\",\n value: function getTopHoveringElement() {\n return this.hoveringElements[0];\n }\n }, {\n key: \"getTopHDraggableElement\",\n value: function getTopHDraggableElement() {\n return this.draggableItems[0];\n }\n }, {\n key: \"getDroppableElements\",\n value: function getDroppableElements() {\n return this.elements.filter(function (element) {\n return element.isDroppable();\n });\n }\n }, {\n key: \"addDragOveringElement\",\n value: function addDragOveringElement(element) {\n this.dragOveringElements.push(element);\n }\n }, {\n key: \"removeDragOveringElement\",\n value: function removeDragOveringElement(element) {\n this.dragOveringElements = this.dragOveringElements.filter(function (e) {\n return e !== element;\n });\n }\n }, {\n key: \"dragOver\",\n value: function dragOver(element, e) {\n var draggableItem = this.draggingItem;\n this.addDragOveringElement(element);\n\n // Get top drag overing element\n var topElement = this.getTopDragOveringElement(draggableItem);\n\n // return if no valid drop target or not the triggering element\n if (!topElement || element != topElement && !this._isDescendantOf(element, topElement)) {\n return;\n }\n\n // ─────────────────────────────────────────────────────────────────\n // DROP-TARGET BRANCHING — order matters, read carefully.\n // ─────────────────────────────────────────────────────────────────\n //\n // 1. canDropBefore / canDropAfter (BlockElement)\n // The user is hovering an existing block. Highlight ABOVE or\n // BELOW the block depending on cursor Y. This is the primary\n // placement affordance once the page/cell has any content.\n //\n // 2. canDropInside (PageElement / CellElement, EMPTY only)\n // Only reached when the user is NOT hovering a block. Lights\n // up the whole container. By contract this branch only fires\n // when the container is empty — see PageElement.canDropInside\n // and CellElement.canDropInside. Once a container has any\n // block, drop-inside is disabled and this branch becomes a\n // no-op for that container, forcing the user to hover an\n // actual block instead. That guarantees the highlight always\n // matches the real landing position (no \"whole page lights up\n // but block silently lands at the bottom\" bug).\n //\n // The else-if (NOT a separate if) is what makes blocks win over\n // their parent container when both are valid drop targets.\n // ─────────────────────────────────────────────────────────────────\n\n // check if the element can drop before or after\n if (topElement.canDropAfter() || topElement.canDropBefore()) {\n if (topElement.checkIfThePositionIsBefore(e.clientX, e.clientY)) {\n if (topElement.canDropBefore()) {\n // Cursor is in the top half of the hovered block\n topElement.addDropBeforeHighlight();\n }\n } else {\n if (topElement.canDropAfter()) {\n // Cursor is in the bottom half of the hovered block\n topElement.addDropAfterHighlight();\n }\n }\n\n //\n if (element.container) {\n // Add hover highlight to its container\n element.container.addContainerDropHightlight();\n if (element.container.container) {\n // Add hover highlight to its container\n element.container.container.addContainerDropHightlight();\n }\n }\n }\n\n // Check if the element can drop inside\n // (only true for EMPTY PageElement / CellElement — see comment above)\n else if (topElement.canDropInside()) {\n topElement.addDropInsideHighlight();\n\n //\n if (element.container) {\n // Add hover highlight to its container\n element.container.addContainerDropHightlight();\n if (element.container.container) {\n // Add hover highlight to its container\n element.container.container.addContainerDropHightlight();\n }\n }\n }\n }\n }, {\n key: \"drop\",\n value: function drop(element, e) {\n var _this5 = this;\n var draggableItem = this.draggingItem;\n if (!draggableItem) {\n console.warn('No draggable item to drop');\n return;\n }\n var topElement = this.getTopDragOveringElement(draggableItem);\n\n // release the dragging item\n this.draggingItem = null;\n if (!topElement) {\n return;\n }\n\n // ─── PLAN_UNDO_REDO — drag-drop reorder = ONE entry ────────────\n //\n // When an EXISTING block is dragged to a new position, the drop\n // flow fires TWO structural mutations:\n // 1. addBlockAfter/Before/Inside → structure:add commit\n // 2. draggableItem.remove() → structure:remove commit\n // (async — fires after 300 ms fadeOut)\n //\n // Without a transaction, history sees 2 entries (\"Add Block\" +\n // \"Delete Block\"). Semantically it's ONE user intent: move. So\n // we wrap both commits in a transaction labelled structure:move.\n // Both individual commits get silenced inside the tx; a single\n // \"Move <Type>\" entry is pushed at endTransaction.\n //\n // Widget drop from sidebar → removeAfterDrop() === false → no tx\n // (a single \"Add <Type>\" entry is the correct semantics).\n //\n // The endTransaction is scheduled after the fadeOut duration so\n // it always fires AFTER remove()'s commit attempt. 400 ms = 300\n // fadeOut + 100 buffer. autoCloseTxMs (5000) is a safety net if\n // the setTimeout is dropped.\n var isReorder = typeof draggableItem.removeAfterDrop === 'function' && draggableItem.removeAfterDrop();\n if (isReorder && this.builder.history) {\n this.builder.history.beginTransaction('history.structure_move', {\n change: 'structure:move',\n elementType: typeof draggableItem.getName === 'function' ? draggableItem.getName() : undefined,\n source: 'drag-drop'\n });\n }\n\n // remove dropover highlight\n topElement.removeDropHighlight();\n\n // return if current element is not the top one (or a descendant of it)\n if (topElement != element && !this._isDescendantOf(element, topElement)) {\n return;\n }\n\n // Mirrors the dragOver() branching — same precedence rules apply:\n // 1. drop above/below an existing block (canDropBefore/After)\n // 2. drop inside an EMPTY container (canDropInside)\n // If the user is hovering the page background of a non-empty page,\n // both branches are false here and the drop is a no-op (intentional).\n // check if the element can drop before or after\n if (topElement.canDropAfter() || topElement.canDropBefore()) {\n if (topElement.checkIfThePositionIsBefore(e.clientX, e.clientY)) {\n if (topElement.canDropBefore()) {\n // Cursor is in the top half of the hovered block\n this.addBlockBefore(topElement.container, topElement, draggableItem.renderBlock());\n }\n } else {\n if (topElement.canDropAfter()) {\n // Cursor is in the bottom half of the hovered block\n this.addBlockAfter(topElement.container, topElement, draggableItem.renderBlock());\n }\n }\n\n //\n if (topElement.container) {\n // Add hover highlight to its container\n topElement.container.removeContainerDropHightlight();\n if (topElement.container.container) {\n // Add hover highlight to its container\n topElement.container.container.removeContainerDropHightlight();\n }\n }\n\n // remove current element\n if (draggableItem.removeAfterDrop()) {\n // remove \n draggableItem.remove();\n }\n }\n\n // Check if the element can drop inside\n else if (topElement.canDropInside()) {\n this.addBlockInside(topElement, draggableItem.renderBlock());\n\n //\n if (topElement.container) {\n // Add hover highlight to its container\n topElement.container.removeContainerDropHightlight();\n if (topElement.container.container) {\n // Add hover highlight to its container\n topElement.container.container.removeContainerDropHightlight();\n }\n }\n\n // remove current element\n if (draggableItem.removeAfterDrop()) {\n // remove\n draggableItem.remove();\n }\n }\n\n // cleanup effects\n this.elements.forEach(function (el) {\n el.removeSelectedHighlight();\n el.removeDropHighlight();\n el.removeContainerHightlight();\n el.removeContainerDropHightlight();\n el.removeHoverHightlight();\n // hide drag anchor\n if (el.getDragAnchor) {\n el.hideDragAnchor();\n }\n });\n\n // PLAN_UNDO_REDO — close the move transaction AFTER remove()'s\n // fadeOut (300 ms) + its trailing commit. 400 ms gives 100 ms\n // buffer. endTransaction pushes ONE entry via the label we set\n // at begin ('history.structure_move'). If the drop was not a\n // reorder (widget from sidebar), no tx was opened → this is a\n // no-op.\n if (isReorder && this.builder.history) {\n setTimeout(function () {\n _this5.builder.history.endTransaction();\n }, 400);\n }\n }\n }, {\n key: \"addBlockAfter\",\n value: function addBlockAfter(container, referenceBlock, block) {\n // Host injection — block came from BaseWidget.renderBlock() →\n // BlockElement.parse() and has not yet been adopted. Adopt\n // BEFORE the container mounts it so its overlays + control\n // emissions can reach `this.host` from the very first render().\n if (this.builder && typeof this.builder._adopt === 'function') {\n this.builder._adopt(block);\n }\n\n // Surgical insert — container.addBlockAfter now does BOTH the\n // array splice AND the DOM mount + UIManager registration (see\n // PageElement / CellElement). The pre-fix `container.render()`\n // here triggered a page-wide cascade re-render that round-\n // tripped every sibling's text through the HTML5 fragment\n // parser — see BlockElement.removeElement notes for the\n // customer-visible data-loss bug that caused.\n container.addBlockAfter(block, referenceBlock);\n block.fadeIn();\n this._commitStructureAdd(block);\n }\n }, {\n key: \"addBlockBefore\",\n value: function addBlockBefore(container, referenceBlock, block) {\n if (this.builder && typeof this.builder._adopt === 'function') {\n this.builder._adopt(block);\n }\n container.addBlockBefore(block, referenceBlock);\n block.fadeIn();\n this._commitStructureAdd(block);\n }\n }, {\n key: \"addBlockInside\",\n value: function addBlockInside(topElement, block) {\n if (this.builder && typeof this.builder._adopt === 'function') {\n this.builder._adopt(block);\n }\n // Append block inside. `appendBlock` now both pushes to the\n // container's `blocks`/`elements` array AND mounts the DOM\n // (PageElement._mountBlockDom / CellElement._mountChildBlockDom).\n topElement.appendBlock(block);\n block.fadeIn();\n this._commitStructureAdd(block);\n }\n\n /** PLAN_UNDO_REDO — shared helper for the 3 addBlock* drop paths.\n * Use getName() for the display name (subclass override) — not the\n * raw class name — so the history dropdown shows \"Add Block\" not\n * \"Add BlockElement\". */\n }, {\n key: \"_commitStructureAdd\",\n value: function _commitStructureAdd(block) {\n if (!this.builder.history) return;\n var elementType = typeof (block === null || block === void 0 ? void 0 : block.getName) === 'function' ? block.getName() : undefined;\n this.builder.history.commit('history.structure_add', {\n change: 'structure:add',\n elementUid: block === null || block === void 0 ? void 0 : block.id,\n elementType: elementType,\n source: 'drag-drop'\n });\n\n // CD-3 (AIBuilder Wave 4) — emit element:added at the structure-mutation\n // chokepoint, NOT through HistoryManager (which dedupes identical-data\n // commits). A Layers tree subscriber (Wave 14) needs to see every add\n // even if undo/redo brings the JSON back to a byte-equal prior state.\n if (this.builder.events && (block === null || block === void 0 ? void 0 : block.id) != null) {\n var _window$Builder$EVENT, _window$Builder;\n this.builder.events.emit((_window$Builder$EVENT = (_window$Builder = window.Builder) === null || _window$Builder === void 0 || (_window$Builder = _window$Builder.EVENTS) === null || _window$Builder === void 0 ? void 0 : _window$Builder.ELEMENT_ADDED) !== null && _window$Builder$EVENT !== void 0 ? _window$Builder$EVENT : 'element:added', {\n elementUid: block.id,\n elementType: elementType\n });\n }\n }\n }, {\n key: \"dragLeave\",\n value: function dragLeave(element) {\n this.removeDragOveringElement(element);\n\n // just remove the drop highlight\n element.removeDropHighlight();\n\n //\n if (element.container) {\n // Add hover highlight to its container\n element.container.removeContainerDropHightlight();\n if (element.container.container) {\n // Add hover highlight to its container\n element.container.container.removeContainerDropHightlight();\n }\n }\n }\n }, {\n key: \"getTopDragOveringElement\",\n value: function getTopDragOveringElement(draggableItem) {\n var top = this.dragOveringElements[0];\n if (!top) return null;\n if (draggableItem && typeof draggableItem.canDropOn === 'function') {\n // First try the directly hovered elements\n var direct = this.dragOveringElements.find(function (e) {\n return draggableItem.canDropOn(e);\n });\n if (direct) return direct;\n\n // Walk up the container chain from the top element to find a valid drop target\n var current = top.container;\n while (current) {\n if (draggableItem.canDropOn(current)) {\n return current;\n }\n current = current.container;\n }\n return null;\n }\n return top;\n }\n }, {\n key: \"addDraggableItem\",\n value: function addDraggableItem(draggableItem) {\n var _this6 = this;\n this.draggableItems.push(draggableItem);\n\n // Phase 1.6 — elements with a Canvas Overlay-backed drag anchor\n // (BlockElement via BlockDragAnchorOverlay) wire their OWN dragstart\n // inside the overlay's onDragStart hook, which then hands off to\n // `uiManager.dragStart(block)`. Skip the legacy anchor-wiring path\n // entirely so the element's hover-triggered overlay is authoritative.\n //\n // Widgets (BaseWidget subclasses) do NOT implement usesOverlayDragAnchor,\n // so they stay on the legacy path below — their `domNode` itself is\n // the draggable source.\n //\n // See docs/core/OVERLAY.md §7.4 + docs/archived/OVERLAY_PLAN.md §3.7 + §4.I2 (pointer\n // events ⊥ HTML5 DnD — NativeDragHandleOverlay handles the ghost\n // workaround for Safari independently).\n if (typeof draggableItem.usesOverlayDragAnchor === 'function' && draggableItem.usesOverlayDragAnchor()) {\n return;\n }\n\n //\n // draggableItem.getDragAnchor().setAttribute('draggable', true);\n\n //\n draggableItem.addDragAnchor();\n\n // handle dragstart event\n draggableItem.getDragAnchor().addEventListener('dragstart', function (e) {\n if (_this6.draggingItem != null) {\n return;\n }\n\n // ─────────────────────────────────────────────────────────────\n // DRAG GHOST — Chrome vs Safari paths\n // ─────────────────────────────────────────────────────────────\n // Chrome/Firefox/Edge: default drag image capture works fine\n // → just set dataTransfer.setData + effectAllowed. DO NOT\n // touch setDragImage on Chrome — user confirmed it works.\n //\n // Safari: automatic drag image capture SILENTLY FAILS when\n // the draggable element is clipped by an ancestor's\n // `overflow: hidden` or `overflow-y: scroll`. Both apply\n // to `.widget-item`:\n // .widgets-box { overflow: hidden }\n // .widget-items { overflow-y: scroll }\n // .widget-item { overflow: hidden; position: static }\n // So Safari gets an empty ghost.\n //\n // Known workaround: clone the draggable element into\n // document.body (off-screen but rendered) and pass the\n // clone to setDragImage. Since the clone is a direct\n // child of body with no clipping ancestor, Safari can\n // snapshot it cleanly. Remove the clone on next tick —\n // Safari has already captured it.\n //\n // We gate the clone workaround on Safari-only user-agent\n // detection so we do not risk regressing Chrome's path.\n //\n // See docs/BUILDER.md → Design Lessons 11 + 12.\n // ─────────────────────────────────────────────────────────────\n if (e.dataTransfer) {\n try {\n e.dataTransfer.setData('text/plain', '');\n e.dataTransfer.effectAllowed = 'all';\n\n // Safari-only: clone workaround for scroll-container bug.\n var ua = typeof navigator !== 'undefined' && navigator.userAgent || '';\n var isSafari = /safari/i.test(ua) && !/chrome|chromium|crios|android/i.test(ua);\n if (isSafari && typeof e.dataTransfer.setDragImage === 'function') {\n var anchor = draggableItem.getDragAnchor();\n if (anchor) {\n var rect = anchor.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) {\n var clone = anchor.cloneNode(true);\n var computed = getComputedStyle(anchor);\n Object.assign(clone.style, {\n position: 'fixed',\n top: '0',\n // Render off-screen (negative left) but\n // NOT display:none — Safari needs a real\n // rendered element for the snapshot.\n left: '-10000px',\n width: rect.width + 'px',\n height: rect.height + 'px',\n margin: '0',\n padding: computed.padding,\n background: computed.backgroundColor || '#ffffff',\n color: computed.color,\n fontFamily: computed.fontFamily,\n fontSize: computed.fontSize,\n border: computed.border,\n borderRadius: computed.borderRadius,\n boxShadow: '0 8px 24px rgba(0,0,0,0.18)',\n pointerEvents: 'none',\n opacity: '0.95',\n zIndex: '-1'\n });\n document.body.appendChild(clone);\n e.dataTransfer.setDragImage(clone, rect.width / 2, rect.height / 2);\n // Remove on next microtask — Safari has\n // already captured the snapshot by then.\n setTimeout(function () {\n if (clone.parentNode) {\n clone.parentNode.removeChild(clone);\n }\n }, 0);\n }\n }\n }\n // Chrome path: do NOT call setDragImage — default\n // capture works and user explicitly confirmed it.\n } catch (_) {\n // Non-fatal — fall through to browser default\n }\n }\n _this6.dragStart(draggableItem);\n });\n }\n }, {\n key: \"removeDraggableItem\",\n value: function removeDraggableItem(object) {\n this.draggableItems = this.draggableItems.filter(function (e) {\n return e !== object;\n });\n }\n }, {\n key: \"getDraggableItemByIndex\",\n value: function getDraggableItemByIndex(index) {\n return this.draggableItems[index];\n }\n }, {\n key: \"dragStart\",\n value: function dragStart(draggableItem) {\n this.draggingItem = draggableItem;\n\n // clear drag over elements\n this.dragOveringElements = [];\n\n // remove hover effects\n this.elements.forEach(function (el) {\n el.removeHoverHightlight();\n el.removeDropHighlight();\n el.removeContainerHightlight();\n el.removeContainerDropHightlight();\n });\n\n // Legacy drag-source (widgets): hide the anchor 100 ms after dragstart.\n // Overlay drag-source (blocks via BlockDragAnchorOverlay): the overlay\n // self-destroys in its own onDragStart hook (identical 100 ms timer),\n // so `hideDragAnchor` is intentionally missing on the element — guard\n // here preserves the contract without try/catch pollution.\n setTimeout(function () {\n if (typeof draggableItem.hideDragAnchor === 'function') {\n draggableItem.hideDragAnchor();\n }\n }, 100);\n }\n }, {\n key: \"removeElement\",\n value: function removeElement(element) {\n this.elements = this.elements.filter(function (e) {\n return e !== element;\n });\n this.removeDragOveringElement(element);\n this.removeHoveringElement(element);\n this.removeDraggableItem(element);\n }\n }, {\n key: \"_isDescendantOf\",\n value: function _isDescendantOf(element, ancestor) {\n var current = element.container;\n while (current) {\n if (current === ancestor) return true;\n current = current.container;\n }\n return false;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (UIManager);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/UIManager.js?");
/***/ }),
/***/ "./src/includes/VideoElement.js":
/*!**************************************!*\
!*** ./src/includes/VideoElement.js ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _DimensionControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./DimensionControl.js */ \"./src/includes/DimensionControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n/**\n * Style keys the template consumes via `formatter.toStyleStringAll(...)`.\n * Kept in sync with `Video.template.html` so the cheap in-place style update\n * matches exactly what a full render would emit.\n */\nvar CSS_KEYS = ['width', 'height', 'border_top_style', 'border_top_width', 'border_top_color', 'border_right_style', 'border_right_width', 'border_right_color', 'border_bottom_style', 'border_bottom_width', 'border_bottom_color', 'border_left_style', 'border_left_width', 'border_left_color', 'border_radius'];\nvar VideoElement = /*#__PURE__*/function (_BaseElement) {\n function VideoElement(template, src) {\n var _this;\n _classCallCheck(this, VideoElement);\n _this = _callSuper(this, VideoElement);\n _this.template = template;\n _this.src = src;\n _this.domNode = null;\n\n // required keys for the element template\n _this.requiredTemplateKeys = ['src'];\n _this.formatter = new Formatter({\n width: null,\n height: null,\n align: 'center',\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_style: null,\n border_left_width: null,\n border_left_color: null,\n border_radius: 0\n });\n return _this;\n }\n _inherits(VideoElement, _BaseElement);\n return _createClass(VideoElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.video');\n }\n\n /**\n * Full render — rebuilds the iframe DOM from the template. Used only when\n * structure changes (empty-state ↔ video, initial mount). For format-only\n * changes call `applyFormatStyles()` instead — it keeps the existing\n * `<video>` element alive so canvas selection/hover overlays, loaded media,\n * and listeners don't churn.\n *\n * W0.2a: scaffold + return migrated to BaseElement.render() lifecycle.\n */\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n // formatter auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n src: this.src ? this.transferMediaAbsUrl(this.src) : ''\n });\n\n // Re-wire canvas listeners since `<video>` is a fresh element.\n this._wireCanvasVideoListeners();\n }\n\n /**\n * Cheap, structure-preserving update. Reads CSS keys from the formatter\n * and patches the existing `<video>` / placeholder `style` attribute +\n * the wrapper's `justify-content` for align. No innerHTML swap → no\n * listener re-registration, no selection-overlay flicker.\n *\n * Falls back to full `render()` only when the domNode hasn't been mounted\n * yet (first paint).\n */\n }, {\n key: \"applyFormatStyles\",\n value: function applyFormatStyles() {\n if (!this.domNode || !this.domNode.firstElementChild) {\n this.render();\n return;\n }\n\n // Outer flex wrapper — controls alignment.\n var wrapper = this.domNode.firstElementChild;\n var align = this.formatter.getFormat('align', 'center');\n wrapper.style.justifyContent = align;\n\n // Inner visible node: the real <video> when src is set, else the\n // `.bjs-video-placeholder` empty-state box. Both accept the same CSS\n // so they use the same style string.\n var target = this.domNode.querySelector('video, .bjs-video-placeholder');\n if (!target) return;\n\n // Rewrite only the formatter-driven portion of the style attribute,\n // preserving any static declarations the template put in front\n // (display, max-width, box-shadow, border color overlays, etc.).\n var dynamic = this.formatter.toStyleStringAll(CSS_KEYS);\n target.setAttribute('data-bjs-dyn-style', dynamic);\n this._rebuildStyle(target);\n }\n\n /**\n * The template's inline `style` has two halves:\n * (1) a static prefix authored in the .html template (layout + chrome)\n * (2) a dynamic suffix computed from the formatter\n * On first paint we capture (1) into `data-bjs-static-style` so later\n * `applyFormatStyles()` calls can rewrite (2) without touching (1).\n */\n }, {\n key: \"_rebuildStyle\",\n value: function _rebuildStyle(target) {\n var staticPart = target.getAttribute('data-bjs-static-style');\n if (staticPart === null) {\n // Capture once: everything currently in `style` that ISN'T a\n // formatter key. We approximate by stripping the dynamic half\n // (safe because we control the template ordering — dynamic is\n // appended after ` max-width: 100%; `).\n staticPart = target.getAttribute('style') || '';\n target.setAttribute('data-bjs-static-style', staticPart);\n }\n var dynamic = target.getAttribute('data-bjs-dyn-style') || '';\n target.setAttribute('style', \"\".concat(staticPart, \" \").concat(dynamic));\n }\n }, {\n key: \"_wireCanvasVideoListeners\",\n value: function _wireCanvasVideoListeners() {\n var _this2 = this;\n var videoEl = this.domNode && this.domNode.querySelector('video');\n if (!videoEl || !this.src) {\n this._setStatus('idle');\n return;\n }\n this._setStatus('loading');\n videoEl.addEventListener('loadedmetadata', function () {\n return _this2._setStatus('success');\n }, {\n once: true\n });\n videoEl.addEventListener('error', function () {\n var err = videoEl.error;\n _this2._setStatus('error', err && err.code);\n }, {\n once: true\n });\n }\n }, {\n key: \"_setStatus\",\n value: function _setStatus(kind, errorCode) {\n var node = this._statusNode;\n if (!node || !node.isConnected) return;\n if (kind === 'idle') {\n node.hidden = true;\n node.className = 'bjs-video-status';\n node.innerHTML = '';\n return;\n }\n var variant = 'info';\n var icon = 'hourglass_empty';\n var key = 'video.load_pending';\n if (kind === 'success') {\n variant = 'success';\n icon = 'check_circle';\n key = 'video.load_ok';\n } else if (kind === 'error') {\n variant = 'error';\n icon = 'error';\n switch (errorCode) {\n case 1:\n key = 'video.err_aborted';\n break;\n case 2:\n key = 'video.err_network';\n break;\n case 3:\n key = 'video.err_decode';\n break;\n case 4:\n key = 'video.err_src_unsupported';\n break;\n default:\n key = 'video.load_error';\n }\n }\n node.hidden = false;\n node.className = \"bjs-info-banner bjs-info-banner--\".concat(variant, \" bjs-video-status\");\n node.innerHTML = \"\\n <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">\".concat(icon, \"</span>\\n <span class=\\\"bjs-info-banner-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key), \"</span>\\n \");\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(VideoElement, \"getData\", this, 3)([])), {}, {\n src: this.src\n });\n }\n }, {\n key: \"buildDimensionControl\",\n value: function buildDimensionControl(label, key) {\n var _this3 = this;\n return new _DimensionControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](label, this.formatter.getFormat(key), {\n units: ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'],\n onChange: function onChange(serialized) {\n _this3.formatter.setFormat(key, serialized);\n // Structure-preserving: keep the same <video> element so\n // loading/selection state survives a width/height tweak.\n _this3.applyFormatStyles();\n }\n });\n }\n }, {\n key: \"buildUrlControl\",\n value: function buildUrlControl() {\n var _this4 = this;\n var node = document.createElement('div');\n node.innerHTML = \"\\n <div class=\\\"bjs-info-banner\\\" role=\\\"note\\\">\\n <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">info</span>\\n <span class=\\\"bjs-info-banner-text\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('video.url_banner'), \"</span>\\n </div>\\n <div class=\\\"bjs-control-stack\\\">\\n <label class=\\\"bjs-control-label\\\" for=\\\"video-url-input\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.video_url'), \"</label>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-link-input\\\">\\n <input type=\\\"url\\\"\\n id=\\\"video-url-input\\\"\\n name=\\\"video-url\\\"\\n class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('video.url_placeholder'), \"\\\"\\n value=\\\"\").concat((this.src || '').replace(/\"/g, '"'), \"\\\"\\n autocomplete=\\\"url\\\">\\n <button type=\\\"button\\\"\\n class=\\\"bjs-icon-btn\\\"\\n data-control=\\\"clear\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('video.clear'), \"\\\"\\n \").concat(this.src ? '' : 'hidden', \">\\n <span class=\\\"material-symbols-rounded\\\">close</span>\\n </button>\\n </div>\\n <span class=\\\"bjs-link-error\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n </div>\\n </div>\\n <div class=\\\"bjs-video-status\\\" role=\\\"status\\\" aria-live=\\\"polite\\\" hidden></div>\\n \");\n var input = node.querySelector('input');\n var clearBtn = node.querySelector('[data-control=\"clear\"]');\n var errorSpan = node.querySelector('.bjs-link-error');\n this._statusNode = node.querySelector('.bjs-video-status');\n var isSyntacticallyValid = function isSyntacticallyValid(v) {\n if (!v) return true;\n return /^(https?:\\/\\/|\\/|\\.{0,2}\\/|blob:|data:)/i.test(v.trim());\n };\n var debounceId = null;\n var commit = function commit() {\n var v = input.value.trim();\n var prevHadSrc = !!_this4.src;\n _this4.src = v;\n clearBtn.hidden = !v;\n if (!isSyntacticallyValid(v)) {\n input.classList.add('is-error');\n errorSpan.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('video.invalid_url');\n _this4._setStatus('idle');\n return;\n }\n input.classList.remove('is-error');\n errorSpan.textContent = '';\n\n // Src change = structure change (empty-state ↔ <video>, or swap\n // in a new video resource) → full render is the right path.\n // Dimension/border/align changes go through applyFormatStyles().\n var structureChanged = prevHadSrc !== !!v || prevHadSrc;\n if (structureChanged) {\n _this4.render();\n } else {\n _this4.applyFormatStyles();\n }\n };\n input.addEventListener('input', function () {\n if (debounceId) clearTimeout(debounceId);\n clearBtn.hidden = !input.value.trim();\n input.classList.remove('is-error');\n errorSpan.textContent = '';\n debounceId = setTimeout(commit, 350);\n });\n input.addEventListener('blur', function () {\n if (debounceId) {\n clearTimeout(debounceId);\n debounceId = null;\n }\n commit();\n });\n clearBtn.addEventListener('click', function () {\n input.value = '';\n commit();\n input.focus();\n });\n if (this.src) this._wireCanvasVideoListeners();\n return {\n domNode: node\n };\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this5 = this;\n return [this.buildUrlControl(), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.width'), 'width'), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.height'), 'height'), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('align'), {\n setValue: function setValue(value) {\n _this5.formatter.setFormat('align', value);\n _this5.applyFormatStyles();\n }\n }, ['left', 'center', 'right']), new BorderControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style', ''),\n border_top_width: this.formatter.getFormat('border_top_width', ''),\n border_top_color: this.formatter.getFormat('border_top_color', ''),\n border_bottom_style: this.formatter.getFormat('border_bottom_style', ''),\n border_bottom_width: this.formatter.getFormat('border_bottom_width', ''),\n border_bottom_color: this.formatter.getFormat('border_bottom_color', ''),\n border_left_style: this.formatter.getFormat('border_left_style', ''),\n border_left_width: this.formatter.getFormat('border_left_width', ''),\n border_left_color: this.formatter.getFormat('border_left_color', ''),\n border_right_style: this.formatter.getFormat('border_right_style', ''),\n border_right_width: this.formatter.getFormat('border_right_width', ''),\n border_right_color: this.formatter.getFormat('border_right_color', '')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this5.formatter.setFormat('border_top_style', border_top_style);\n _this5.formatter.setFormat('border_top_width', border_top_width);\n _this5.formatter.setFormat('border_top_color', border_top_color);\n _this5.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this5.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this5.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this5.formatter.setFormat('border_left_style', border_left_style);\n _this5.formatter.setFormat('border_left_width', border_left_width);\n _this5.formatter.setFormat('border_left_color', border_left_color);\n _this5.formatter.setFormat('border_right_style', border_right_style);\n _this5.formatter.setFormat('border_right_width', border_right_width);\n _this5.formatter.setFormat('border_right_color', border_right_color);\n _this5.applyFormatStyles();\n }\n }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius', 0), {\n setRadius: function setRadius(v) {\n _this5.formatter.setFormat('border_radius', v);\n _this5.applyFormatStyles();\n }\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.src), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (VideoElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/VideoElement.js?");
/***/ }),
/***/ "./src/includes/VideoWidget.js":
/*!*************************************!*\
!*** ./src/includes/VideoWidget.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _VideoElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./VideoElement.js */ \"./src/includes/VideoElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar VideoWidget = /*#__PURE__*/function (_BaseWidget) {\n function VideoWidget() {\n var _this;\n _classCallCheck(this, VideoWidget);\n _this = _callSuper(this, VideoWidget); // Call the parent class constructor\n\n // Add a VideoElement to the widget.\n // No default URL: the upstream demo link (media.w3.org/2010/.../trailer.mp4)\n // is dead, and showing a broken video on first drop is worse than an empty\n // state. The empty-state template renders an illustration + \"paste a URL\"\n // hint, which is also the better onboarding.\n var video = new _VideoElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Video', '');\n\n // Append the new element to the block\n _this.block.appendElements([video]);\n return _this;\n }\n _inherits(VideoWidget, _BaseWidget);\n return _createClass(VideoWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.video');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'videocam';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (VideoWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/VideoWidget.js?");
/***/ }),
/***/ "./src/includes/WelcomeWidget.js":
/*!***************************************!*\
!*** ./src/includes/WelcomeWidget.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar WelcomeWidget = /*#__PURE__*/function (_BaseWidget) {\n function WelcomeWidget() {\n var _this;\n _classCallCheck(this, WelcomeWidget);\n _this = _callSuper(this, WelcomeWidget); // Call the parent class constructor\n\n // Add elements to the widget\n var h1 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h1', 'Welcome!');\n var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'This is a welcome message!');\n p.formatter.setFormat('text_align', 'center');\n\n // Append the new elements to the block\n _this.block.appendElements([h1, p]);\n return _this;\n }\n _inherits(WelcomeWidget, _BaseWidget);\n return _createClass(WelcomeWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.welcome');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'history_edu';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (WelcomeWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/WelcomeWidget.js?");
/***/ }),
/***/ "./src/includes/WidgetsBox.js":
/*!************************************!*\
!*** ./src/includes/WidgetsBox.js ***!
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar WidgetsBox = /*#__PURE__*/function () {\n // host-injection: Builder passes itself so widget drag-registration\n // can route through the per-instance UIManager instead of a bare-\n // builder global. Multi-instance safe.\n function WidgetsBox(container) {\n var host = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n _classCallCheck(this, WidgetsBox);\n this.container = container;\n this.host = host;\n this.widgetGroups = {};\n this.groupHeaders = {};\n this.widgetItemsContainer;\n }\n\n /**\n * Attach a custom banner to a group, rendered between the group title\n * and the widget grid. Useful for showing context (e.g. info card).\n *\n * @param {string} group Group name (must match the one used in addWidget).\n * @param {string|HTMLElement|Function} content\n * - string: raw HTML\n * - HTMLElement: appended as-is\n * - function: called at render time, must return string or HTMLElement\n */\n return _createClass(WidgetsBox, [{\n key: \"setGroupHeader\",\n value: function setGroupHeader(group, content) {\n this.groupHeaders[group] = content;\n }\n }, {\n key: \"addWidget\",\n value: function addWidget(widget) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n // group\n if (typeof options.group === 'undefined') {\n options.group = 'Basic';\n }\n\n // display type\n if (typeof options.type === 'undefined') {\n widget.type = 'icon';\n } else {\n widget.type = options.type;\n }\n if (typeof this.widgetGroups[options.group] === 'undefined') {\n this.widgetGroups[options.group] = [];\n }\n if (typeof options.index === 'number' && options.index >= 0 && options.index <= this.widgetGroups[options.group].length) {\n this.widgetGroups[options.group].splice(options.index, 0, widget);\n } else {\n this.widgetGroups[options.group].push(widget);\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this = this;\n if (!this.widgetItemsContainer) {\n var wrapper = document.createElement('div');\n wrapper.innerHTML = \"\\n <div class=\\\"widgets-box shadow-sm rounded-0 bg-white\\\">\\n <div class=\\\"widget-header w-100 p-3\\\">\\n <div class=\\\"alert alert-light fst-italic rounded-2 bg-light border-0 mb-0\\\">\\n \\u2728 \".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets_box.drag_hint'), \"\\n </div>\\n </div>\\n <div class=\\\"widget-items\\\"></div>\\n </div>\\n \");\n this.widgetItemsContainer = wrapper.querySelector('.widget-items');\n this.container.appendChild(wrapper);\n }\n\n //\n this.widgetItemsContainer.innerHTML = ''; // Clear previous content\n\n Object.entries(this.widgetGroups).forEach(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n key = _ref2[0],\n widgets = _ref2[1];\n var groupDom = document.createElement('div');\n groupDom.innerHTML = \"\\n <div class=\\\"widgets-group\\\">\\n <div class=\\\"widget-group-header w-100 px-3 d-flex justify-content-between align-items-center cursor-pointer\\\">\\n <h6 class=\\\"widget-group-title mb-0 text-nowrap\\\">\".concat(key, \"</h6>\\n <hr class=\\\"mx-3 w-100\\\">\\n <span class=\\\"material-symbols-rounded toggle-icon\\\" style=\\\"cursor:pointer;\\\">expand_more</span>\\n </div>\\n <div class=\\\"widget-items-container\\\"><div class=\\\"widget-group-items\\\"></div></div>\\n </div>\\n \");\n var header = groupDom.querySelector('.widget-group-header');\n var toggleIcon = groupDom.querySelector('.toggle-icon');\n var groupContent = groupDom.querySelector('.widget-group-items');\n var groupContainer = groupDom.querySelector('.widget-items-container');\n\n // Optional banner above the widget grid\n var headerContent = _this.groupHeaders[key];\n if (headerContent) {\n var banner = document.createElement('div');\n banner.className = 'widget-group-banner';\n var resolved = headerContent;\n if (typeof resolved === 'function') {\n resolved = resolved();\n }\n if (resolved instanceof HTMLElement) {\n banner.appendChild(resolved);\n } else if (typeof resolved === 'string') {\n banner.innerHTML = resolved;\n }\n groupContainer.insertBefore(banner, groupContent);\n }\n\n // Initially collapsed\n // groupContainer.style.display = 'none';\n\n // Toggle functionality\n header.addEventListener('click', function () {\n var isCollapsed = groupContainer.style.display === 'none';\n if (isCollapsed) {\n groupContainer.style.display = 'block';\n toggleIcon.textContent = 'expand_less';\n // Smooth scroll to this group\n groupDom.scrollIntoView({\n behavior: 'smooth',\n block: 'start'\n });\n } else {\n groupContainer.style.display = 'none';\n toggleIcon.textContent = 'expand_more';\n }\n });\n widgets.forEach(function (widget) {\n groupContent.appendChild(widget.render(widget.type));\n _this.host.uiManager.addDraggableItem(widget);\n });\n _this.widgetItemsContainer.appendChild(groupDom);\n });\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (WidgetsBox);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/WidgetsBox.js?");
/***/ }),
/***/ "./src/includes/YoutubeElement.js":
/*!****************************************!*\
!*** ./src/includes/YoutubeElement.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _DimensionControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./DimensionControl.js */ \"./src/includes/DimensionControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n/**\n * Keys that map to CSS on the <iframe> / placeholder. Kept in sync with\n * `Youtube.template.html`; the cheap in-place `applyFormatStyles()` path\n * rewrites only these. See PHASE_2_PLAN §2.8 rule E.\n */\nvar CSS_KEYS = ['width', 'height', 'border_top_style', 'border_top_width', 'border_top_color', 'border_right_style', 'border_right_width', 'border_right_color', 'border_bottom_style', 'border_bottom_width', 'border_bottom_color', 'border_left_style', 'border_left_width', 'border_left_color', 'border_radius'];\nvar YoutubeElement = /*#__PURE__*/function (_BaseElement) {\n function YoutubeElement(template, url) {\n var _this;\n _classCallCheck(this, YoutubeElement);\n _this = _callSuper(this, YoutubeElement);\n _this.template = template;\n _this.url = url;\n _this.domNode = null;\n _this.requiredTemplateKeys = ['url'];\n _this.formatter = new Formatter({\n width: null,\n height: null,\n align: 'center',\n border_top_style: null,\n border_top_width: null,\n border_top_color: null,\n border_right_style: null,\n border_right_width: null,\n border_right_color: null,\n border_bottom_style: null,\n border_bottom_width: null,\n border_bottom_color: null,\n border_left_style: null,\n border_left_width: null,\n border_left_color: null,\n border_radius: 0\n });\n return _this;\n }\n _inherits(YoutubeElement, _BaseElement);\n return _createClass(YoutubeElement, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.youtube');\n }\n\n /**\n * Extract the YouTube video ID from a URL. Supports:\n * - https://www.youtube.com/watch?v=ID\n * - https://youtu.be/ID\n * - https://www.youtube.com/embed/ID\n * - https://www.youtube.com/shorts/ID\n * Returns null when the URL is missing / malformed / not a YouTube URL.\n */\n }, {\n key: \"getYouTubeVideoId\",\n value: function getYouTubeVideoId() {\n if (!this.url) return null;\n try {\n var parsedUrl = new URL(this.url);\n if (parsedUrl.hostname === 'youtu.be') {\n return parsedUrl.pathname.slice(1) || null;\n }\n if (parsedUrl.hostname.includes('youtube.com')) {\n if (parsedUrl.pathname.startsWith('/embed/')) {\n return parsedUrl.pathname.slice('/embed/'.length) || null;\n }\n if (parsedUrl.pathname.startsWith('/shorts/')) {\n return parsedUrl.pathname.slice('/shorts/'.length) || null;\n }\n return parsedUrl.searchParams.get('v') || null;\n }\n return null;\n } catch (e) {\n return null;\n }\n }\n }, {\n key: \"_doRender\",\n value: function _doRender() {\n var _this$getYouTubeVideo;\n // formatter auto-merged (W0.2c)\n this.domNode.innerHTML = this.renderTemplate({\n youtubeID: (_this$getYouTubeVideo = this.getYouTubeVideoId()) !== null && _this$getYouTubeVideo !== void 0 ? _this$getYouTubeVideo : false\n });\n }\n\n /**\n * Cheap, structure-preserving update for format-only changes (dimension,\n * align, border, radius). Keeps the existing <iframe>/placeholder DOM\n * alive so selection/hover overlays don't churn. See PHASE_2_PLAN §2.8 E.\n */\n }, {\n key: \"applyFormatStyles\",\n value: function applyFormatStyles() {\n var _target$dataset, _target$dataset$bjsSt;\n if (!this.domNode || !this.domNode.firstElementChild) {\n this.render();\n return;\n }\n // Outer flex wrapper — alignment\n var wrapper = this.domNode.firstElementChild;\n wrapper.style.justifyContent = this.formatter.getFormat('align', 'center');\n\n // Inner styled element: <iframe> when embed works, else placeholder\n var target = this.domNode.querySelector('iframe, .bjs-video-placeholder');\n if (!target) return;\n var staticPrefix = (_target$dataset$bjsSt = (_target$dataset = target.dataset).bjsStaticStyle) !== null && _target$dataset$bjsSt !== void 0 ? _target$dataset$bjsSt : _target$dataset.bjsStaticStyle = target.getAttribute('style') || '';\n target.setAttribute('style', \"\".concat(staticPrefix, \" \").concat(this.formatter.toStyleStringAll(CSS_KEYS)));\n }\n }, {\n key: \"getData\",\n value: function getData() {\n return _objectSpread(_objectSpread({}, _superPropGet(YoutubeElement, \"getData\", this, 3)([])), {}, {\n url: this.url\n });\n }\n }, {\n key: \"buildDimensionControl\",\n value: function buildDimensionControl(label, key) {\n var _this2 = this;\n return new _DimensionControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](label, this.formatter.getFormat(key), {\n units: ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'],\n onChange: function onChange(serialized) {\n _this2.formatter.setFormat(key, serialized);\n _this2.applyFormatStyles();\n }\n });\n }\n\n /**\n * URL control — `.bjs-text-input` + clear button + 350ms debounce +\n * synchronous YouTube-ID extraction. No async probe needed (YouTube\n * embed's error events don't cross the iframe boundary reliably —\n * see PHASE_2_PLAN §2.8 D). Status comes from the URL's parse result:\n * - Empty URL → idle (empty-state rendered on canvas).\n * - URL parses + ID extracted → `.bjs-info-banner--success` with the ID.\n * - URL set but ID extraction fails → `.bjs-info-banner--error` with\n * \"This doesn't look like a YouTube URL — use youtube.com/watch?v=… or youtu.be/…\".\n */\n }, {\n key: \"buildUrlControl\",\n value: function buildUrlControl() {\n var _this3 = this;\n var node = document.createElement('div');\n node.innerHTML = \"\\n <div class=\\\"bjs-info-banner\\\" role=\\\"note\\\">\\n <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">info</span>\\n <span class=\\\"bjs-info-banner-text\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('youtube.url_banner'), \"</span>\\n </div>\\n <div class=\\\"bjs-control-stack\\\">\\n <label class=\\\"bjs-control-label\\\" for=\\\"youtube-url-input\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.youtube_url'), \"</label>\\n <div class=\\\"bjs-control-input\\\">\\n <div class=\\\"bjs-link-input\\\">\\n <input type=\\\"url\\\"\\n id=\\\"youtube-url-input\\\"\\n name=\\\"youtube-url\\\"\\n class=\\\"bjs-text-input\\\"\\n placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('youtube.url_placeholder'), \"\\\"\\n value=\\\"\").concat((this.url || '').replace(/\"/g, '"'), \"\\\"\\n autocomplete=\\\"url\\\">\\n <button type=\\\"button\\\"\\n class=\\\"bjs-icon-btn\\\"\\n data-control=\\\"clear\\\"\\n aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('youtube.clear'), \"\\\"\\n \").concat(this.url ? '' : 'hidden', \">\\n <span class=\\\"material-symbols-rounded\\\">close</span>\\n </button>\\n </div>\\n <span class=\\\"bjs-link-error\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n </div>\\n </div>\\n <div class=\\\"bjs-video-status\\\" role=\\\"status\\\" aria-live=\\\"polite\\\" hidden></div>\\n \");\n var input = node.querySelector('input');\n var clearBtn = node.querySelector('[data-control=\"clear\"]');\n var errorSpan = node.querySelector('.bjs-link-error');\n this._statusNode = node.querySelector('.bjs-video-status');\n var isSyntacticallyValid = function isSyntacticallyValid(v) {\n if (!v) return true;\n return /^(https?:\\/\\/|\\/|\\.{0,2}\\/)/i.test(v.trim());\n };\n var debounceId = null;\n var commit = function commit() {\n var v = input.value.trim();\n var prevUrl = _this3.url;\n _this3.url = v;\n clearBtn.hidden = !v;\n if (v && !isSyntacticallyValid(v)) {\n input.classList.add('is-error');\n errorSpan.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('youtube.invalid_url');\n _this3._setStatus('idle');\n return;\n }\n input.classList.remove('is-error');\n errorSpan.textContent = '';\n\n // Re-render whenever the URL flips between empty/non-empty OR the\n // extracted video ID changes (src swap). Otherwise structure is\n // the same — applyFormatStyles would suffice but URL change IS a\n // structure change for YT, so always render().\n var structureChanged = !!prevUrl !== !!v || _this3._lastVideoId !== _this3.getYouTubeVideoId();\n if (structureChanged) _this3.render();\n\n // Status\n if (!v) {\n _this3._setStatus('idle');\n } else if (_this3.getYouTubeVideoId()) {\n _this3._setStatus('success');\n _this3._lastVideoId = _this3.getYouTubeVideoId();\n } else {\n _this3._setStatus('error');\n }\n };\n input.addEventListener('input', function () {\n if (debounceId) clearTimeout(debounceId);\n clearBtn.hidden = !input.value.trim();\n input.classList.remove('is-error');\n errorSpan.textContent = '';\n debounceId = setTimeout(commit, 350);\n });\n input.addEventListener('blur', function () {\n if (debounceId) {\n clearTimeout(debounceId);\n debounceId = null;\n }\n commit();\n });\n clearBtn.addEventListener('click', function () {\n input.value = '';\n commit();\n input.focus();\n });\n\n // Initial status — deferred to `afterRender()` because the status\n // node isn't in the DOM yet at this point (Builder appends the\n // control's domNode AFTER getControls() returns, then calls\n // afterRender — so `_setStatus` would early-out on !isConnected).\n var initialStatus = this.url ? this.getYouTubeVideoId() ? 'success' : 'error' : 'idle';\n return {\n domNode: node,\n afterRender: function afterRender() {\n _this3._setStatus(initialStatus);\n }\n };\n }\n }, {\n key: \"_setStatus\",\n value: function _setStatus(kind) {\n var node = this._statusNode;\n if (!node || !node.isConnected) return;\n if (kind === 'idle') {\n node.hidden = true;\n node.className = 'bjs-video-status';\n node.innerHTML = '';\n return;\n }\n var variant, icon, textKey;\n if (kind === 'success') {\n variant = 'success';\n icon = 'check_circle';\n textKey = 'youtube.extract_ok';\n } else {\n variant = 'error';\n icon = 'error';\n textKey = 'youtube.extract_failed';\n }\n var text = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(textKey);\n node.hidden = false;\n node.className = \"bjs-info-banner bjs-info-banner--\".concat(variant, \" bjs-video-status\");\n node.innerHTML = \"\\n <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">\".concat(icon, \"</span>\\n <span class=\\\"bjs-info-banner-text\\\">\").concat(text, \"</span>\\n \");\n }\n }, {\n key: \"getControls\",\n value: function getControls() {\n var _this4 = this;\n return [this.buildUrlControl(), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.width'), 'width'), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.height'), 'height'), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('align'), {\n setValue: function setValue(value) {\n _this4.formatter.setFormat('align', value);\n _this4.applyFormatStyles();\n }\n }, ['left', 'center', 'right']), new BorderControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n border_top_style: this.formatter.getFormat('border_top_style', ''),\n border_top_width: this.formatter.getFormat('border_top_width', ''),\n border_top_color: this.formatter.getFormat('border_top_color', ''),\n border_bottom_style: this.formatter.getFormat('border_bottom_style', ''),\n border_bottom_width: this.formatter.getFormat('border_bottom_width', ''),\n border_bottom_color: this.formatter.getFormat('border_bottom_color', ''),\n border_left_style: this.formatter.getFormat('border_left_style', ''),\n border_left_width: this.formatter.getFormat('border_left_width', ''),\n border_left_color: this.formatter.getFormat('border_left_color', ''),\n border_right_style: this.formatter.getFormat('border_right_style', ''),\n border_right_width: this.formatter.getFormat('border_right_width', ''),\n border_right_color: this.formatter.getFormat('border_right_color', '')\n }, {\n setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n _this4.formatter.setFormat('border_top_style', border_top_style);\n _this4.formatter.setFormat('border_top_width', border_top_width);\n _this4.formatter.setFormat('border_top_color', border_top_color);\n _this4.formatter.setFormat('border_bottom_style', border_bottom_style);\n _this4.formatter.setFormat('border_bottom_width', border_bottom_width);\n _this4.formatter.setFormat('border_bottom_color', border_bottom_color);\n _this4.formatter.setFormat('border_left_style', border_left_style);\n _this4.formatter.setFormat('border_left_width', border_left_width);\n _this4.formatter.setFormat('border_left_color', border_left_color);\n _this4.formatter.setFormat('border_right_style', border_right_style);\n _this4.formatter.setFormat('border_right_width', border_right_width);\n _this4.formatter.setFormat('border_right_color', border_right_color);\n _this4.applyFormatStyles();\n }\n }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius', 0), {\n setRadius: function setRadius(v) {\n _this4.formatter.setFormat('border_radius', v);\n _this4.applyFormatStyles();\n }\n })];\n }\n }], [{\n key: \"parse\",\n value: function parse(data) {\n return this.parseFormats(new this(data.template, data.url), data);\n }\n }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (YoutubeElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/YoutubeElement.js?");
/***/ }),
/***/ "./src/includes/YoutubeWidget.js":
/*!***************************************!*\
!*** ./src/includes/YoutubeWidget.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar YoutubeWidget = /*#__PURE__*/function (_BaseWidget) {\n function YoutubeWidget() {\n var _this;\n _classCallCheck(this, YoutubeWidget);\n _this = _callSuper(this, YoutubeWidget); // Call the parent class constructor\n\n // Add a RSSElement to the widget\n var rssElement = new YoutubeElement('Youtube', null);\n\n // Append the new element to the block\n _this.block.appendElements([rssElement]);\n return _this;\n }\n _inherits(YoutubeWidget, _BaseWidget);\n return _createClass(YoutubeWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.youtube');\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'youtube_activity';\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (YoutubeWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/YoutubeWidget.js?");
/***/ }),
/***/ "./src/includes/ads/AdCTAWidget.js":
/*!*****************************************!*\
!*** ./src/includes/ads/AdCTAWidget.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _ButtonElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ButtonElement.js */ \"./src/includes/ButtonElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Call-to-Action widget — a button that maps to platform CTA dictionaries.\n *\n * Unlike a freeform button, ad CTAs are constrained to a fixed set of platform\n * enums. The UI exposes all options as plain text, but the exporter maps them\n * to the matching platform enum (e.g. \"Learn More\" → SHOP_NOW_WITHOUT_PRICE\n * depending on target). The host server keeps the canonical CTA dict.\n *\n * Allowed CTAs (shared across platforms):\n * learn_more, shop_now, sign_up, contact_us, download, get_quote, book_now, apply_now\n */\nvar AdCTAWidget = /*#__PURE__*/function (_BaseWidget) {\n function AdCTAWidget() {\n var _this;\n _classCallCheck(this, AdCTAWidget);\n _this = _callSuper(this, AdCTAWidget);\n _this.elements = [];\n var cta = new _ButtonElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Button', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_cta_default') || 'Learn More', '#');\n\n // Ad CTA button styling: teal fill, bold, comfortable padding\n cta.formatter.parseFormats({\n align: 'left',\n font_family: 'inherit',\n font_weight: '600',\n font_size: '15px',\n text_color: '#FFFFFF',\n link_color: '#FFFFFF',\n text_align: 'center',\n line_height: '1.2',\n background_color: '#0891B2',\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n padding_top: 12,\n padding_right: 24,\n padding_bottom: 12,\n padding_left: 24,\n border_top_style: 'solid',\n border_top_width: '0',\n border_top_color: '#0891B2',\n border_right_style: 'solid',\n border_right_width: '0',\n border_right_color: '#0891B2',\n border_bottom_style: 'solid',\n border_bottom_width: '0',\n border_bottom_color: '#0891B2',\n border_left_width: '0',\n border_left_style: 'solid',\n border_left_color: '#0891B2',\n border_radius: '6px'\n });\n _this.block.appendElements([cta]);\n return _this;\n }\n _inherits(AdCTAWidget, _BaseWidget);\n return _createClass(AdCTAWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_cta') || 'Call to Action';\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'ads_click';\n }\n }], [{\n key: \"adRole\",\n get: function get() {\n return 'cta';\n }\n }, {\n key: \"constraints\",\n get: function get() {\n return {\n allowedValues: ['learn_more', 'shop_now', 'sign_up', 'contact_us', 'download', 'get_quote', 'book_now', 'apply_now'],\n defaultValue: 'learn_more',\n exportField: 'call_to_action'\n };\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdCTAWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdCTAWidget.js?");
/***/ }),
/***/ "./src/includes/ads/AdCarouselCardWidget.js":
/*!**************************************************!*\
!*** ./src/includes/ads/AdCarouselCardWidget.js ***!
\**************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ImageElement.js */ \"./src/includes/ImageElement.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _ButtonElement_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../ButtonElement.js */ \"./src/includes/ButtonElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n/**\n * Ad Carousel Card widget — a composite card with image + headline +\n * description + CTA, repeatable 2-10 times for Meta / TikTok carousel ads.\n *\n * Exporter extracts each BlockElement containing this structure as one\n * element of the carousel_cards[] array.\n */\nvar AdCarouselCardWidget = /*#__PURE__*/function (_BaseWidget) {\n function AdCarouselCardWidget() {\n var _this;\n _classCallCheck(this, AdCarouselCardWidget);\n _this = _callSuper(this, AdCarouselCardWidget);\n _this.elements = [];\n\n // Image (top)\n var image = new _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Image');\n image.formatter.parseFormats({\n width: '100%',\n align: 'center',\n border_radius: '8px',\n padding_top: 0,\n padding_bottom: 0,\n padding_left: 0,\n padding_right: 0\n });\n\n // Headline (middle)\n var headline = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h3', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_carousel_headline_default') || 'Card headline');\n headline.formatter.parseFormats({\n font_weight: '700',\n font_size: '16px',\n text_color: '#111827',\n text_align: 'left',\n line_height: '1.25',\n padding_top: 10,\n padding_bottom: 4,\n padding_left: 12,\n padding_right: 12\n });\n\n // Description (below headline)\n var desc = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_carousel_desc_default') || 'Short sub-text');\n desc.formatter.parseFormats({\n font_size: '13px',\n text_color: '#6B7280',\n line_height: '1.4',\n padding_top: 0,\n padding_bottom: 10,\n padding_left: 12,\n padding_right: 12\n });\n\n // CTA (bottom)\n var cta = new _ButtonElement_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"]('Button', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_cta_default') || 'Learn More', '#');\n cta.formatter.parseFormats({\n align: 'left',\n font_weight: '600',\n font_size: '14px',\n text_color: '#0891B2',\n link_color: '#0891B2',\n text_align: 'center',\n line_height: '1.2',\n background_color: '#FFFFFF',\n padding_top: 10,\n padding_right: 18,\n padding_bottom: 10,\n padding_left: 18,\n border_top_style: 'solid',\n border_top_width: '1px',\n border_top_color: '#0891B2',\n border_right_style: 'solid',\n border_right_width: '1px',\n border_right_color: '#0891B2',\n border_bottom_style: 'solid',\n border_bottom_width: '1px',\n border_bottom_color: '#0891B2',\n border_left_width: '1px',\n border_left_style: 'solid',\n border_left_color: '#0891B2',\n border_radius: '6px'\n });\n\n // Block styling: card-like with border + radius\n _this.block.formatter.parseFormats({\n background_color: '#FFFFFF',\n padding_top: 0,\n padding_bottom: 16,\n padding_left: 0,\n padding_right: 0,\n border_top_style: 'solid',\n border_top_width: '1px',\n border_top_color: '#E5E7EB',\n border_right_style: 'solid',\n border_right_width: '1px',\n border_right_color: '#E5E7EB',\n border_bottom_style: 'solid',\n border_bottom_width: '1px',\n border_bottom_color: '#E5E7EB',\n border_left_width: '1px',\n border_left_style: 'solid',\n border_left_color: '#E5E7EB',\n border_radius: '10px'\n });\n _this.block.appendElements([image, headline, desc, cta]);\n return _this;\n }\n _inherits(AdCarouselCardWidget, _BaseWidget);\n return _createClass(AdCarouselCardWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_carousel_card') || 'Carousel Card';\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'view_carousel';\n }\n }], [{\n key: \"adRole\",\n get: function get() {\n return 'carousel_card';\n }\n }, {\n key: \"constraints\",\n get: function get() {\n return {\n imageAspectRatio: '1:1',\n headlineMaxLength: 40,\n descriptionMaxLength: 20,\n minCards: 2,\n maxCards: 10,\n exportField: 'carousel_cards'\n };\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdCarouselCardWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdCarouselCardWidget.js?");
/***/ }),
/***/ "./src/includes/ads/AdDescriptionWidget.js":
/*!*************************************************!*\
!*** ./src/includes/ads/AdDescriptionWidget.js ***!
\*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../PElement.js */ \"./src/includes/PElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Description widget — a short sub-line below the headline.\n *\n * On Meta this maps to the \"description\" field (newsfeed card byline).\n * On Google Responsive Display it's descriptions[1+]. It's shorter and\n * more direct than primary text.\n *\n * Platform constraints:\n * - Meta: max 30 chars (link description)\n * - Google: max 90 chars (as description asset)\n * - TikTok: N/A (merged with primary text)\n * - LinkedIn: max 70 chars (headline variant)\n */\nvar AdDescriptionWidget = /*#__PURE__*/function (_BaseWidget) {\n function AdDescriptionWidget() {\n var _this;\n _classCallCheck(this, AdDescriptionWidget);\n _this = _callSuper(this, AdDescriptionWidget);\n _this.elements = [];\n var desc = new _PElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('P', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_description_default') || 'One-line sub-text');\n desc.formatter.parseFormats({\n font_size: '13px',\n text_color: '#6B7280',\n line_height: '1.4',\n padding_top: 0,\n padding_bottom: 8,\n padding_left: 16,\n padding_right: 16\n });\n _this.block.appendElements([desc]);\n return _this;\n }\n _inherits(AdDescriptionWidget, _BaseWidget);\n return _createClass(AdDescriptionWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_description') || 'Description';\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'short_text';\n }\n }], [{\n key: \"adRole\",\n get: function get() {\n return 'description';\n }\n }, {\n key: \"constraints\",\n get: function get() {\n return {\n maxLength: 30,\n platforms: {\n meta: {\n maxLength: 30\n },\n google: {\n maxLength: 90\n },\n linkedin: {\n maxLength: 70\n }\n },\n exportField: 'description'\n };\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdDescriptionWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdDescriptionWidget.js?");
/***/ }),
/***/ "./src/includes/ads/AdHeadlineWidget.js":
/*!**********************************************!*\
!*** ./src/includes/ads/AdHeadlineWidget.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../HeadingElement.js */ \"./src/includes/HeadingElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Headline widget — short, bold, attention-grabbing text.\n *\n * Uses a standard HeadingElement under the hood so the exporter can find\n * \"first HeadingElement in the page\" and map it to the headline field\n * of platform API payloads (Meta body.name, Google Ads headlines[0], etc).\n *\n * Platform constraints (informational — enforced by the PHP exporter + UI):\n * - Meta: max 40 chars, 1 line\n * - Google: max 30 chars per headline (Responsive Display allows 5)\n * - TikTok: max 40 chars\n * - LinkedIn: max 70 chars\n */\nvar AdHeadlineWidget = /*#__PURE__*/function (_BaseWidget) {\n function AdHeadlineWidget() {\n var _this;\n _classCallCheck(this, AdHeadlineWidget);\n _this = _callSuper(this, AdHeadlineWidget);\n _this.elements = [];\n\n // h2 matches typical Meta feed card headline sizing\n var headline = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Heading', 'h2', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_headline_default') || 'Your attention-grabbing headline');\n\n // Default style: bold, dark, centered — reads like an ad headline\n headline.formatter.parseFormats({\n font_weight: '700',\n font_size: '22px',\n text_color: '#111827',\n text_align: 'left',\n line_height: '1.2',\n padding_top: 8,\n padding_bottom: 8,\n padding_left: 16,\n padding_right: 16\n });\n _this.block.appendElements([headline]);\n return _this;\n }\n _inherits(AdHeadlineWidget, _BaseWidget);\n return _createClass(AdHeadlineWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_headline') || 'Ad Headline';\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'title';\n }\n }], [{\n key: \"adRole\",\n get: function get() {\n return 'headline';\n }\n }, {\n key: \"constraints\",\n get: function get() {\n return {\n maxLength: 40,\n singleLine: true,\n platforms: {\n meta: {\n maxLength: 40\n },\n google: {\n maxLength: 30\n },\n tiktok: {\n maxLength: 40\n },\n linkedin: {\n maxLength: 70\n }\n },\n exportField: 'headline'\n };\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdHeadlineWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdHeadlineWidget.js?");
/***/ }),
/***/ "./src/includes/ads/AdImageSlotWidget.js":
/*!***********************************************!*\
!*** ./src/includes/ads/AdImageSlotWidget.js ***!
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ImageElement.js */ \"./src/includes/ImageElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Image Slot widget — the main creative image.\n *\n * Platform aspect ratios (what the user should upload):\n * - Meta Feed: 1:1 (1080x1080) or 1.91:1 (1200x628)\n * - Meta Story: 9:16 (1080x1920)\n * - Google Display: various (300x250, 728x90, 160x600, 1200x628)\n * - TikTok Video: 9:16 (cover image, same ratio)\n * - LinkedIn Feed: 1.91:1 (1200x627)\n *\n * Exporter picks first ImageElement in the page → image_url / image_hash.\n */\nvar AdImageSlotWidget = /*#__PURE__*/function (_BaseWidget) {\n function AdImageSlotWidget() {\n var _this;\n _classCallCheck(this, AdImageSlotWidget);\n _this = _callSuper(this, AdImageSlotWidget);\n _this.elements = [];\n var image = new _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Image');\n image.formatter.parseFormats({\n width: '100%',\n align: 'center',\n border_radius: '0',\n padding_top: 0,\n padding_bottom: 0,\n padding_left: 0,\n padding_right: 0\n });\n _this.block.appendElements([image]);\n return _this;\n }\n _inherits(AdImageSlotWidget, _BaseWidget);\n return _createClass(AdImageSlotWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_image') || 'Ad Image';\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'image';\n }\n }], [{\n key: \"adRole\",\n get: function get() {\n return 'image';\n }\n }, {\n key: \"constraints\",\n get: function get() {\n return {\n aspectRatios: {\n meta_feed: '1:1',\n meta_story: '9:16',\n google_display: '1.91:1',\n tiktok: '9:16',\n linkedin: '1.91:1'\n },\n minWidth: 600,\n recommendedWidth: 1200,\n exportField: 'image_url'\n };\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdImageSlotWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdImageSlotWidget.js?");
/***/ }),
/***/ "./src/includes/ads/AdLogoSlotWidget.js":
/*!**********************************************!*\
!*** ./src/includes/ads/AdLogoSlotWidget.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ImageElement.js */ \"./src/includes/ImageElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Logo Slot widget — the brand logo shown alongside the creative.\n *\n * On Meta this maps to the page profile image (already set at page level),\n * but some placements support a dedicated brand asset (e.g. Carousel cards).\n * On Google Responsive Display this maps to logoImages[].\n *\n * Exporter picks first ImageElement with adRole=logo, or the SECOND\n * ImageElement in a page (after the main image slot).\n */\nvar AdLogoSlotWidget = /*#__PURE__*/function (_BaseWidget) {\n function AdLogoSlotWidget() {\n var _this;\n _classCallCheck(this, AdLogoSlotWidget);\n _this = _callSuper(this, AdLogoSlotWidget);\n _this.elements = [];\n var logo = new _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Image');\n logo.formatter.parseFormats({\n width: '80px',\n max_width: '80px',\n align: 'left',\n border_radius: '50%',\n padding_top: 8,\n padding_bottom: 8,\n padding_left: 16,\n padding_right: 0\n });\n _this.block.appendElements([logo]);\n return _this;\n }\n _inherits(AdLogoSlotWidget, _BaseWidget);\n return _createClass(AdLogoSlotWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_logo') || 'Brand Logo';\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'verified';\n }\n }], [{\n key: \"adRole\",\n get: function get() {\n return 'logo';\n }\n }, {\n key: \"constraints\",\n get: function get() {\n return {\n aspectRatio: '1:1',\n minWidth: 128,\n recommendedWidth: 512,\n exportField: 'brand_logo_url'\n };\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdLogoSlotWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdLogoSlotWidget.js?");
/***/ }),
/***/ "./src/includes/ads/AdPrimaryTextWidget.js":
/*!*************************************************!*\
!*** ./src/includes/ads/AdPrimaryTextWidget.js ***!
\*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../PElement.js */ \"./src/includes/PElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Primary Text widget — the main body copy above/below the creative.\n *\n * On Meta this is the \"primary_text\" that shows above the image. On Google\n * Responsive Display this maps to descriptions[0]. The exporter extracts\n * \"first PElement with adRole=primary_text (via widget-class)\" or falls back\n * to \"first PElement in the page\".\n *\n * Platform constraints:\n * - Meta: max 125 chars (recommended)\n * - Google: max 90 chars per description\n * - TikTok: max 100 chars\n * - LinkedIn: max 600 chars (but recommends < 150)\n */\nvar AdPrimaryTextWidget = /*#__PURE__*/function (_BaseWidget) {\n function AdPrimaryTextWidget() {\n var _this;\n _classCallCheck(this, AdPrimaryTextWidget);\n _this = _callSuper(this, AdPrimaryTextWidget);\n _this.elements = [];\n var text = new _PElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('P', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_primary_text_default') || 'Your body copy here. Keep it short, clear, and actionable — under 125 characters works best on most platforms.');\n text.formatter.parseFormats({\n font_size: '15px',\n text_color: '#374151',\n line_height: '1.5',\n padding_top: 4,\n padding_bottom: 12,\n padding_left: 16,\n padding_right: 16\n });\n _this.block.appendElements([text]);\n return _this;\n }\n _inherits(AdPrimaryTextWidget, _BaseWidget);\n return _createClass(AdPrimaryTextWidget, [{\n key: \"getName\",\n value: function getName() {\n return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_primary_text') || 'Primary Text';\n }\n }, {\n key: \"getIcon\",\n value: function getIcon() {\n return 'notes';\n }\n }], [{\n key: \"adRole\",\n get: function get() {\n return 'primary_text';\n }\n }, {\n key: \"constraints\",\n get: function get() {\n return {\n maxLength: 125,\n platforms: {\n meta: {\n maxLength: 125\n },\n google: {\n maxLength: 90\n },\n tiktok: {\n maxLength: 100\n },\n linkedin: {\n maxLength: 600,\n recommended: 150\n }\n },\n exportField: 'primary_text'\n };\n }\n }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdPrimaryTextWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdPrimaryTextWidget.js?");
/***/ }),
/***/ "./src/includes/buttonPresets.js":
/*!***************************************!*\
!*** ./src/includes/buttonPresets.js ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CATEGORIES: () => (/* binding */ CATEGORIES),\n/* harmony export */ HOVER_EFFECT_KEYS: () => (/* binding */ HOVER_EFFECT_KEYS),\n/* harmony export */ PRESETS: () => (/* binding */ PRESETS),\n/* harmony export */ SHADOW_KEYS: () => (/* binding */ SHADOW_KEYS),\n/* harmony export */ SHADOW_SCALE: () => (/* binding */ SHADOW_SCALE),\n/* harmony export */ SIZE_KEYS: () => (/* binding */ SIZE_KEYS),\n/* harmony export */ SIZE_SCALE: () => (/* binding */ SIZE_SCALE),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ findPreset: () => (/* binding */ findPreset),\n/* harmony export */ presetsByCategory: () => (/* binding */ presetsByCategory)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/*\n * buttonPresets.js — curated library of ~210 button style presets for\n * ButtonElement. Each preset is a Formatter snapshot + metadata; the\n * user picks one and the element's applyPreset() writes the snapshot\n * into its formatter in a single pass.\n *\n * Architecture\n * ────────────\n *\n * PALETTE — reusable base color tokens (~16 color families ×\n * {solid / strong / soft / tone / toneText}). Every\n * generator function reads from here so a one-line\n * palette tweak updates dozens of presets at once.\n *\n * SIZE_SCALE — xs · sm · md · lg · xl (5 entries). Each entry is a\n * partial formatter snapshot patching only\n * font_size + padding_{top,right,bottom,left}. Size\n * is an orthogonal axis to preset identity; switching\n * preset does NOT change size, switching size does\n * NOT change color/border/radius/shadow identity.\n *\n * SHADOW_SCALE — 6 named box-shadow values (none / sm / md / lg /\n * xl / inner). Page-mode only — email exporters\n * strip box-shadow.\n *\n * HOVER_EFFECTS — 6 data-bjs-hover-fx values (none / lift / glow /\n * scale / sweep / push). Actual animation CSS lives\n * in src/builder.css alongside the other overlay\n * chrome. Page-mode only — no `:hover` in email.\n *\n * PRESETS — array of preset objects. Order within the array\n * drives display order within each category tab.\n *\n * CATEGORIES — display metadata (label, order, mode). Drives the\n * picker's tab row + sidebar category filter.\n *\n * Preset shape\n * ────────────\n *\n * {\n * id: 'solid-indigo', // stable serialization key\n * category: 'solid', // matches CATEGORIES key\n * label: 'Indigo', // i18n key if starts with 'i18n:'\n * flags: {\n * emailSafe: true, // false → show ⚠ warn badge in email mode\n * requiresVML: false, // true → auto-wrap <table>+VML on export\n * pageOnly: false, // true → label \"Page only\" in email mode\n * },\n * formats: { // partial formatter snapshot\n * background_color: '#2563eb',\n * text_color: '#ffffff',\n * // …every CSS_KEY the preset owns…\n * },\n * icon: null, // null OR a material-symbols name\n * iconPosition: 'none', // 'left' | 'right' | 'only' | 'none'\n * }\n *\n * Non-obvious rules\n * ────────────────\n *\n * 1. Generators (makeSolid / makeOutline / makeTonal) mix a per-color\n * object into a shared DEFAULT_MD skeleton so every preset covers\n * the full CSS_KEYS set. Partial snapshots would leak the previous\n * preset's values into the new one on apply.\n *\n * 2. `border_radius` baseline is 6px (matches current ButtonElement\n * default). Radius is a separate axis — presets don't touch it\n * unless the preset's IDENTITY demands it (pill-* ships 999px,\n * brutalist-* ships 0px).\n *\n * 3. Gradient presets write `background_image` (not background_color);\n * background_color becomes the FALLBACK color emitted first so\n * Outlook-strip-gradient degrades to flat color, not transparent.\n *\n * 4. Glass / glow presets USE box_shadow + backdrop-filter. backdrop-\n * filter is NOT in the formatter's CSS_KEYS → it gets attached via\n * the element's extraInlineStyles() passthrough (new method).\n *\n * 5. Icon presets carry a non-null `icon` + non-'none' iconPosition.\n * Non-icon presets carry null + 'none'. Applying a preset RESETS\n * both fields to the preset's values (icon choice follows the\n * preset identity — switching to a non-icon preset removes the\n * icon).\n */\n\n// ─── SIZE SCALE ────────────────────────────────────────────────────────────\n\nvar SIZE_SCALE = {\n xs: {\n font_size: '11px',\n padding_top: 4,\n padding_right: 8,\n padding_bottom: 4,\n padding_left: 8\n },\n sm: {\n font_size: '13px',\n padding_top: 6,\n padding_right: 12,\n padding_bottom: 6,\n padding_left: 12\n },\n md: {\n font_size: '14px',\n padding_top: 10,\n padding_right: 20,\n padding_bottom: 10,\n padding_left: 20\n },\n lg: {\n font_size: '16px',\n padding_top: 12,\n padding_right: 28,\n padding_bottom: 12,\n padding_left: 28\n },\n xl: {\n font_size: '18px',\n padding_top: 16,\n padding_right: 36,\n padding_bottom: 16,\n padding_left: 36\n }\n};\nvar SIZE_KEYS = ['xs', 'sm', 'md', 'lg', 'xl'];\n\n// ─── SHADOW SCALE (page-mode only — email strips box-shadow) ───────────────\n\nvar SHADOW_SCALE = {\n none: '',\n sm: '0 1px 2px rgba(0,0,0,0.08)',\n md: '0 4px 8px -2px rgba(0,0,0,0.16)',\n lg: '0 10px 18px -6px rgba(0,0,0,0.22)',\n xl: '0 18px 32px -10px rgba(0,0,0,0.28)',\n inner: 'inset 0 2px 4px rgba(0,0,0,0.25)'\n};\nvar SHADOW_KEYS = ['none', 'sm', 'md', 'lg', 'xl', 'inner'];\n\n// ─── HOVER EFFECTS (page-mode only — no :hover reliability in email) ──────\n// Values match data-bjs-hover-fx attribute. CSS rules live in\n// src/builder.css under `[data-bjs-hover-fx=\"<key>\"]:hover { … }`.\n\nvar HOVER_EFFECT_KEYS = ['none', 'lift', 'glow', 'scale', 'sweep', 'push'];\n\n// ─── PALETTE (shared color tokens) ─────────────────────────────────────────\n\nvar PAL = {\n indigo: {\n solid: '#2563eb',\n strong: '#1d4ed8',\n soft: '#93c5fd',\n onSolid: '#ffffff',\n tone: '#dbeafe',\n toneText: '#1d4ed8'\n },\n indigoDeep: {\n solid: '#3730a3',\n strong: '#1e1b4b',\n soft: '#a5b4fc',\n onSolid: '#ffffff',\n tone: '#e0e7ff',\n toneText: '#3730a3'\n },\n slate: {\n solid: '#64748b',\n strong: '#334155',\n soft: '#cbd5e1',\n onSolid: '#ffffff',\n tone: '#f1f5f9',\n toneText: '#334155'\n },\n ink: {\n solid: '#111827',\n strong: '#030712',\n soft: '#6b7280',\n onSolid: '#ffffff',\n tone: '#f3f4f6',\n toneText: '#111827'\n },\n charcoal: {\n solid: '#1f2937',\n strong: '#030712',\n soft: '#9ca3af',\n onSolid: '#f3f4f6',\n tone: '#e5e7eb',\n toneText: '#111827'\n },\n paper: {\n solid: '#f9fafb',\n strong: '#f3f4f6',\n soft: '#ffffff',\n onSolid: '#111827',\n tone: '#ffffff',\n toneText: '#111827',\n border: '#d1d5db'\n },\n emerald: {\n solid: '#16a34a',\n strong: '#14532d',\n soft: '#86efac',\n onSolid: '#ffffff',\n tone: '#dcfce7',\n toneText: '#15803d'\n },\n amber: {\n solid: '#f59e0b',\n strong: '#b45309',\n soft: '#fcd34d',\n onSolid: '#1f2937',\n tone: '#fef3c7',\n toneText: '#b45309'\n },\n crimson: {\n solid: '#dc2626',\n strong: '#7f1d1d',\n soft: '#fca5a5',\n onSolid: '#ffffff',\n tone: '#fee2e2',\n toneText: '#b91c1c'\n },\n cyan: {\n solid: '#06b6d4',\n strong: '#0e7490',\n soft: '#67e8f9',\n onSolid: '#ffffff',\n tone: '#cffafe',\n toneText: '#0e7490'\n },\n violet: {\n solid: '#7c3aed',\n strong: '#4c1d95',\n soft: '#c4b5fd',\n onSolid: '#ffffff',\n tone: '#ede9fe',\n toneText: '#6d28d9'\n },\n rose: {\n solid: '#e11d48',\n strong: '#881337',\n soft: '#fda4af',\n onSolid: '#ffffff',\n tone: '#ffe4e6',\n toneText: '#be123c'\n },\n orange: {\n solid: '#ea580c',\n strong: '#9a3412',\n soft: '#fdba74',\n onSolid: '#ffffff',\n tone: '#ffedd5',\n toneText: '#c2410c'\n },\n teal: {\n solid: '#0d9488',\n strong: '#134e4a',\n soft: '#99f6e4',\n onSolid: '#ffffff',\n tone: '#ccfbf1',\n toneText: '#115e59'\n },\n lime: {\n solid: '#65a30d',\n strong: '#365314',\n soft: '#bef264',\n onSolid: '#1f2937',\n tone: '#ecfccb',\n toneText: '#3f6212'\n },\n pink: {\n solid: '#db2777',\n strong: '#831843',\n soft: '#f9a8d4',\n onSolid: '#ffffff',\n tone: '#fce7f3',\n toneText: '#9d174d'\n },\n sky: {\n solid: '#0284c7',\n strong: '#075985',\n soft: '#7dd3fc',\n onSolid: '#ffffff',\n tone: '#e0f2fe',\n toneText: '#0369a1'\n },\n mint: {\n solid: '#5eead4',\n strong: '#14b8a6',\n soft: '#99f6e4',\n onSolid: '#134e4a',\n tone: '#f0fdfa',\n toneText: '#134e4a'\n },\n plum: {\n solid: '#9333ea',\n strong: '#581c87',\n soft: '#d8b4fe',\n onSolid: '#ffffff',\n tone: '#f3e8ff',\n toneText: '#7e22ce'\n },\n sand: {\n solid: '#d6cfbe',\n strong: '#a8a29e',\n soft: '#f5f5f4',\n onSolid: '#1c1917',\n tone: '#f5f5f4',\n toneText: '#44403c'\n },\n sage: {\n solid: '#84cc16',\n strong: '#3f6212',\n soft: '#d9f99d',\n onSolid: '#1c1917',\n tone: '#f7fee7',\n toneText: '#4d7c0f'\n },\n graphite: {\n solid: '#374151',\n strong: '#0f172a',\n soft: '#9ca3af',\n onSolid: '#ffffff',\n tone: '#e5e7eb',\n toneText: '#1f2937'\n }\n};\n\n// ─── DEFAULT SKELETON ─────────────────────────────────────────────────────\n// Every generator mixes into this so every preset emits a FULL snapshot.\n// Without this, applying preset B after preset A would leak A's values.\n\nvar DEFAULT_MD = {\n font_family: 'inherit',\n font_weight: '500',\n font_size: '14px',\n text_color: '#ffffff',\n link_color: '#ffffff',\n text_align: 'center',\n line_height: '1.5',\n letter_spacing: null,\n text_direction: 'ltr',\n paragraph_spacing: null,\n background_color: '#2563eb',\n background_image: null,\n background_position: 'center',\n background_size: '100%',\n background_repeat: 'no-repeat',\n padding_top: 10,\n padding_right: 20,\n padding_bottom: 10,\n padding_left: 20,\n border_top_style: 'solid',\n border_top_width: '1px',\n border_top_color: '#2563eb',\n border_right_style: 'solid',\n border_right_width: '1px',\n border_right_color: '#2563eb',\n border_bottom_style: 'solid',\n border_bottom_width: '1px',\n border_bottom_color: '#2563eb',\n border_left_style: 'solid',\n border_left_width: '1px',\n border_left_color: '#2563eb',\n border_radius: '6px',\n box_shadow: '',\n width: null,\n max_width: null,\n min_width: null\n};\n\n// Apply a single color uniformly to all 4 border sides.\nfunction borderColor(color) {\n return {\n border_top_color: color,\n border_right_color: color,\n border_bottom_color: color,\n border_left_color: color\n };\n}\nfunction borderWidth(width) {\n return {\n border_top_width: width,\n border_right_width: width,\n border_bottom_width: width,\n border_left_width: width\n };\n}\nfunction borderStyle(style) {\n return {\n border_top_style: style,\n border_right_style: style,\n border_bottom_style: style,\n border_left_style: style\n };\n}\nvar SAFE = {\n emailSafe: true,\n requiresVML: false,\n pageOnly: false\n};\nvar WARN = {\n emailSafe: false,\n requiresVML: true,\n pageOnly: false\n};\nvar PAGE = {\n emailSafe: false,\n requiresVML: false,\n pageOnly: true\n};\n\n// ─── SOLID (~30) ──────────────────────────────────────────────────────────\n\nfunction makeSolid(id, label, color) {\n var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n var bg = opts.bg || color.solid;\n var fg = opts.fg || color.onSolid;\n var bd = opts.border || bg;\n return {\n id: \"solid-\".concat(id),\n category: 'solid',\n label: label,\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: bg,\n text_color: fg,\n link_color: fg\n }, borderColor(bd))),\n icon: null,\n iconPosition: 'none'\n };\n}\n\n// For soft variant we need dark text on soft bg — color.toneText or custom.\nfunction makeSolidSoft(id, label, color) {\n return {\n id: \"solid-\".concat(id, \"-soft\"),\n category: 'solid',\n label: \"\".concat(label, \" \\xB7 soft\"),\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: color.soft,\n text_color: color.toneText,\n link_color: color.toneText\n }, borderColor(color.soft))),\n icon: null,\n iconPosition: 'none'\n };\n}\n\n// ─── OUTLINE (~22) ────────────────────────────────────────────────────────\n\nfunction makeOutline(id, label, color) {\n var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n var bd = opts.border || color.solid;\n var fg = opts.text || color.solid;\n return {\n id: \"outline-\".concat(id),\n category: 'outline',\n label: label,\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: fg,\n link_color: fg\n }, borderColor(bd)), borderWidth('1px')), borderStyle('solid'))),\n icon: null,\n iconPosition: 'none'\n };\n}\n\n// ─── TONAL (~22) ──────────────────────────────────────────────────────────\n\nfunction makeTonal(id, label, color) {\n return {\n id: \"tonal-\".concat(id),\n category: 'tonal',\n label: label,\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: color.tone,\n text_color: color.toneText,\n link_color: color.toneText\n }, borderColor(color.tone))),\n icon: null,\n iconPosition: 'none'\n };\n}\n\n// ─── GHOST (~14) ──────────────────────────────────────────────────────────\n\nfunction makeGhost(id, label, color) {\n var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n var fg = opts.text || color.solid;\n var extra = opts.extra || {};\n return {\n id: \"ghost-\".concat(id),\n category: 'ghost',\n label: label,\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: fg,\n link_color: fg\n }, borderColor('transparent')), extra)),\n icon: null,\n iconPosition: 'none'\n };\n}\n\n// ─── GRADIENT (~32) ───────────────────────────────────────────────────────\n\nfunction makeGradient(id, label, gradient, fallback) {\n var text = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '#ffffff';\n var opts = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};\n return {\n id: \"gradient-\".concat(id),\n category: 'gradient',\n label: label,\n flags: opts.flags || WARN,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: fallback,\n background_image: gradient,\n text_color: text,\n link_color: text\n }, borderColor(fallback)), opts.formats || {})),\n icon: null,\n iconPosition: 'none'\n };\n}\n\n// ─── ELEVATED (~18, page-only) ───────────────────────────────────────────\nfunction makeElevated(id, label, base, shadow) {\n var opts = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};\n var fg = opts.fg || base.onSolid;\n return {\n id: \"elevated-\".concat(id),\n category: 'elevated',\n label: label,\n flags: PAGE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: base.solid,\n text_color: fg,\n link_color: fg\n }, borderColor(base.solid)), {}, {\n box_shadow: shadow\n }, opts.formats || {})),\n icon: null,\n iconPosition: 'none'\n };\n}\n\n// ─── GLASS & GLOW (~16, page-only) ───────────────────────────────────────\nfunction makeGlow(id, label, base, glow) {\n var opts = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};\n return {\n id: \"glass-\".concat(id),\n category: 'glass',\n label: label,\n flags: PAGE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: base.solid,\n text_color: base.onSolid,\n link_color: base.onSolid\n }, borderColor(base.solid)), borderWidth('0px')), {}, {\n box_shadow: glow\n }, opts.formats || {})),\n icon: null,\n iconPosition: 'none'\n };\n}\n\n// ─── BRUTALIST (~14) ─────────────────────────────────────────────────────\nfunction makeBrutalist(id, label, bg, fg) {\n var shadowColor = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '#111827';\n var opts = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};\n return {\n id: \"brutalist-\".concat(id),\n category: 'brutalist',\n label: label,\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread(_objectSpread({\n background_color: bg,\n text_color: fg,\n link_color: fg,\n font_weight: '700'\n }, borderColor(shadowColor)), borderWidth('2px')), borderStyle('solid')), {}, {\n border_radius: '0px',\n box_shadow: \"4px 4px 0 \".concat(shadowColor)\n }, opts.formats || {})),\n icon: null,\n iconPosition: 'none'\n };\n}\n\n// ─── SOLID (~30) ──────────────────────────────────────────────────────────\n\nvar SOLID = [makeSolid('indigo', 'Indigo', PAL.indigo), makeSolid('indigo-strong', 'Indigo · strong', PAL.indigo, {\n bg: PAL.indigo.strong,\n border: PAL.indigo.strong\n}), makeSolidSoft('indigo', 'Indigo', PAL.indigo), makeSolid('indigo-deep', 'Indigo · deep', PAL.indigoDeep), makeSolid('slate', 'Slate', PAL.slate), makeSolid('ink', 'Ink · black', PAL.ink), makeSolid('paper', 'Paper · white', PAL.paper, {\n bg: PAL.paper.solid,\n fg: '#111827',\n border: PAL.paper.border\n}), makeSolid('charcoal', 'Charcoal', PAL.charcoal), makeSolid('emerald', 'Emerald', PAL.emerald), makeSolid('emerald-strong', 'Emerald · strong', PAL.emerald, {\n bg: PAL.emerald.strong,\n border: PAL.emerald.strong\n}), makeSolidSoft('emerald', 'Emerald', PAL.emerald), makeSolid('amber', 'Amber', PAL.amber), makeSolid('amber-strong', 'Amber · strong', PAL.amber, {\n bg: PAL.amber.strong,\n fg: '#fff',\n border: PAL.amber.strong\n}), makeSolidSoft('amber', 'Amber', PAL.amber), makeSolid('crimson', 'Crimson', PAL.crimson), makeSolid('crimson-strong', 'Crimson · deep', PAL.crimson, {\n bg: PAL.crimson.strong,\n border: PAL.crimson.strong\n}), makeSolid('cyan', 'Cyan', PAL.cyan), makeSolid('cyan-strong', 'Cyan · deep', PAL.cyan, {\n bg: PAL.cyan.strong,\n border: PAL.cyan.strong\n}), makeSolid('violet', 'Violet', PAL.violet), makeSolid('violet-strong', 'Violet · deep', PAL.violet, {\n bg: PAL.violet.strong,\n border: PAL.violet.strong\n}), makeSolid('rose', 'Rose', PAL.rose), makeSolid('rose-strong', 'Rose · deep', PAL.rose, {\n bg: PAL.rose.strong,\n border: PAL.rose.strong\n}), makeSolid('orange', 'Orange', PAL.orange), makeSolid('teal', 'Teal', PAL.teal), makeSolid('lime', 'Lime', PAL.lime), makeSolid('pink', 'Pink', PAL.pink), makeSolid('sky', 'Sky', PAL.sky), makeSolid('mint', 'Mint', PAL.mint), makeSolid('plum', 'Plum', PAL.plum), makeSolid('graphite', 'Graphite', PAL.graphite)];\n\n// ─── OUTLINE (~22) ────────────────────────────────────────────────────────\n\nvar OUTLINE = [makeOutline('indigo', 'Indigo', PAL.indigo), makeOutline('ink', 'Ink', PAL.ink), makeOutline('paper', 'Paper', PAL.paper, {\n border: '#ffffff',\n text: '#ffffff'\n}),\n// for dark backgrounds\nmakeOutline('slate', 'Slate', PAL.slate), makeOutline('emerald', 'Emerald', PAL.emerald), makeOutline('amber', 'Amber', PAL.amber, {\n text: PAL.amber.strong\n}), makeOutline('crimson', 'Crimson', PAL.crimson), makeOutline('cyan', 'Cyan', PAL.cyan, {\n text: PAL.cyan.strong\n}), makeOutline('violet', 'Violet', PAL.violet), makeOutline('rose', 'Rose', PAL.rose), makeOutline('orange', 'Orange', PAL.orange, {\n text: PAL.orange.strong\n}), makeOutline('teal', 'Teal', PAL.teal), makeOutline('lime', 'Lime', PAL.lime, {\n text: PAL.lime.strong\n}), makeOutline('pink', 'Pink', PAL.pink), makeOutline('sky', 'Sky', PAL.sky),\n// Thick-2px variants\n{\n id: 'outline-indigo-thick',\n category: 'outline',\n label: 'Indigo · thick',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.indigo.solid,\n link_color: PAL.indigo.solid\n }, borderColor(PAL.indigo.solid)), borderWidth('2px')), borderStyle('solid'))),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'outline-ink-thick',\n category: 'outline',\n label: 'Ink · thick',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.ink.solid,\n link_color: PAL.ink.solid\n }, borderColor(PAL.ink.solid)), borderWidth('2px')), borderStyle('solid'))),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'outline-double-ink',\n category: 'outline',\n label: 'Double-line · ink',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.ink.solid,\n link_color: PAL.ink.solid\n }, borderColor(PAL.ink.solid)), borderWidth('3px')), borderStyle('double'))),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'outline-double-indigo',\n category: 'outline',\n label: 'Double-line · indigo',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.indigo.solid,\n link_color: PAL.indigo.solid\n }, borderColor(PAL.indigo.solid)), borderWidth('3px')), borderStyle('double'))),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'outline-dashed-ink',\n category: 'outline',\n label: 'Dashed · ink',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.ink.solid,\n link_color: PAL.ink.solid\n }, borderColor(PAL.ink.solid)), borderWidth('2px')), borderStyle('dashed'))),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'outline-dotted-slate',\n category: 'outline',\n label: 'Dotted · slate',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.slate.solid,\n link_color: PAL.slate.solid\n }, borderColor(PAL.slate.solid)), borderWidth('2px')), borderStyle('dotted'))),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'outline-pill-indigo',\n category: 'outline',\n label: 'Pill · indigo',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.indigo.solid,\n link_color: PAL.indigo.solid\n }, borderColor(PAL.indigo.solid)), {}, {\n border_radius: '999px'\n })),\n icon: null,\n iconPosition: 'none'\n}];\n\n// ─── TONAL (~22) ──────────────────────────────────────────────────────────\n\nvar TONAL = [makeTonal('indigo', 'Indigo', PAL.indigo), makeTonal('ink', 'Ink', PAL.ink), makeTonal('slate', 'Slate', PAL.slate), makeTonal('emerald', 'Emerald', PAL.emerald), makeTonal('amber', 'Amber', PAL.amber), makeTonal('crimson', 'Crimson', PAL.crimson), makeTonal('cyan', 'Cyan', PAL.cyan), makeTonal('violet', 'Violet', PAL.violet), makeTonal('rose', 'Rose', PAL.rose), makeTonal('orange', 'Orange', PAL.orange), makeTonal('teal', 'Teal', PAL.teal), makeTonal('lime', 'Lime', PAL.lime), makeTonal('pink', 'Pink', PAL.pink), makeTonal('sky', 'Sky', PAL.sky), makeTonal('mint', 'Mint', PAL.mint), makeTonal('plum', 'Plum', PAL.plum), makeTonal('sage', 'Sage', PAL.sage), makeTonal('sand', 'Sand', PAL.sand), makeTonal('graphite', 'Graphite', PAL.graphite),\n// Pill variants\n{\n id: 'tonal-pill-indigo',\n category: 'tonal',\n label: 'Pill · indigo',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: PAL.indigo.tone,\n text_color: PAL.indigo.toneText,\n link_color: PAL.indigo.toneText\n }, borderColor(PAL.indigo.tone)), {}, {\n border_radius: '999px'\n })),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'tonal-pill-rose',\n category: 'tonal',\n label: 'Pill · rose',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: PAL.rose.tone,\n text_color: PAL.rose.toneText,\n link_color: PAL.rose.toneText\n }, borderColor(PAL.rose.tone)), {}, {\n border_radius: '999px'\n })),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'tonal-chip-slate',\n category: 'tonal',\n label: 'Chip · slate',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: PAL.slate.tone,\n text_color: PAL.slate.toneText,\n link_color: PAL.slate.toneText\n }, borderColor(PAL.slate.tone)), {}, {\n border_radius: '999px',\n font_size: '12px',\n padding_top: 6,\n padding_bottom: 6,\n padding_left: 14,\n padding_right: 14\n })),\n icon: null,\n iconPosition: 'none'\n}];\n\n// ─── GHOST (~14) ──────────────────────────────────────────────────────────\n\nvar GHOST = [makeGhost('indigo', 'Indigo', PAL.indigo), makeGhost('ink', 'Ink', PAL.ink), makeGhost('slate', 'Muted', PAL.slate, {\n text: PAL.slate.strong\n}), makeGhost('emerald', 'Emerald', PAL.emerald), makeGhost('crimson', 'Crimson', PAL.crimson), makeGhost('violet', 'Violet', PAL.violet), makeGhost('rose', 'Rose', PAL.rose),\n// Link variants\n{\n id: 'ghost-link-indigo',\n category: 'ghost',\n label: 'Link · indigo',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.indigo.solid,\n link_color: PAL.indigo.solid\n }, borderColor('transparent')), {}, {\n padding_top: 6,\n padding_right: 4,\n padding_bottom: 6,\n padding_left: 4,\n font_weight: '500'\n })),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'ghost-link-underlined',\n category: 'ghost',\n label: 'Link · underlined',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.indigo.solid,\n link_color: PAL.indigo.solid\n }, borderColor('transparent')), {}, {\n padding_top: 6,\n padding_right: 4,\n padding_bottom: 6,\n padding_left: 4\n // text_decoration not in formatter; relies on .bp-link CSS via data-fx\n })),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'ghost-uppercase-tracking',\n category: 'ghost',\n label: 'All-caps · tracking',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.ink.solid,\n link_color: PAL.ink.solid\n }, borderColor('transparent')), {}, {\n padding_top: 6,\n padding_right: 4,\n padding_bottom: 6,\n padding_left: 4,\n font_weight: '600',\n letter_spacing: 2,\n font_size: '12px'\n })),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'ghost-arrow-subtle',\n category: 'ghost',\n label: 'Arrow · subtle',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: PAL.ink.solid,\n link_color: PAL.ink.solid\n }, borderColor('transparent')), {}, {\n padding_top: 8,\n padding_right: 8,\n padding_bottom: 8,\n padding_left: 8\n })),\n icon: 'arrow_forward',\n iconPosition: 'right'\n}, makeGhost('small-muted', 'Muted · small', PAL.slate, {\n text: PAL.slate.toneText,\n extra: {\n font_size: '12px',\n padding_top: 4,\n padding_right: 8,\n padding_bottom: 4,\n padding_left: 8\n }\n}), makeGhost('amber', 'Amber', PAL.amber, {\n text: PAL.amber.strong\n}), makeGhost('cyan', 'Cyan', PAL.cyan, {\n text: PAL.cyan.strong\n})];\n\n// ─── GRADIENT (~32) ───────────────────────────────────────────────────────\n\nvar GRADIENT = [makeGradient('sunset', 'Sunset', 'linear-gradient(135deg, #f97316, #ec4899)', '#f97316'), makeGradient('ocean', 'Ocean', 'linear-gradient(135deg, #06b6d4, #2563eb)', '#2563eb'), makeGradient('neon', 'Neon', 'linear-gradient(135deg, #ec4899, #8b5cf6)', '#8b5cf6'), makeGradient('forest', 'Forest', 'linear-gradient(135deg, #84cc16, #14b8a6)', '#14b8a6'), makeGradient('mono-dark', 'Mono · dark', 'linear-gradient(180deg, #334155, #0f172a)', '#0f172a'), makeGradient('mono-light', 'Mono · light', 'linear-gradient(180deg, #ffffff, #e5e7eb)', '#e5e7eb', '#111827', {\n formats: borderColor('#d1d5db')\n}), makeGradient('brand-sweep', 'Brand sweep', 'linear-gradient(135deg, #2563eb, #1e40af)', '#1e40af'), makeGradient('iridescent', 'Iridescent', 'linear-gradient(135deg, #f472b6, #a78bfa, #60a5fa, #34d399)', '#a78bfa'), makeGradient('aurora', 'Aurora', 'linear-gradient(135deg, #14b8a6, #0ea5e9, #a855f7)', '#0ea5e9'), makeGradient('midnight', 'Midnight', 'linear-gradient(135deg, #1e1b4b, #312e81, #581c87)', '#1e1b4b'), makeGradient('peach', 'Peach', 'linear-gradient(135deg, #fed7aa, #fbcfe8)', '#fbcfe8', '#9d174d'), makeGradient('ember', 'Ember', 'linear-gradient(135deg, #f97316, #dc2626)', '#dc2626'), makeGradient('violet-dawn', 'Violet dawn', 'linear-gradient(135deg, #8b5cf6, #ec4899, #f59e0b)', '#8b5cf6'), makeGradient('rose-gold', 'Rose gold', 'linear-gradient(135deg, #f59e0b, #f43f5e)', '#f43f5e'), makeGradient('arctic', 'Arctic', 'linear-gradient(135deg, #e0f2fe, #bae6fd, #7dd3fc)', '#7dd3fc', '#075985'), makeGradient('sahara', 'Sahara', 'linear-gradient(135deg, #fde047, #fb923c)', '#fb923c', '#7c2d12'), makeGradient('jade', 'Jade', 'linear-gradient(135deg, #10b981, #14b8a6)', '#14b8a6'), makeGradient('nebula', 'Nebula', 'linear-gradient(135deg, #4338ca, #db2777, #c026d3)', '#4338ca'), makeGradient('twilight', 'Twilight', 'linear-gradient(135deg, #334155, #581c87)', '#581c87'), makeGradient('spring', 'Spring', 'linear-gradient(135deg, #bef264, #4ade80)', '#4ade80', '#365314'), makeGradient('candy', 'Candy', 'linear-gradient(135deg, #f9a8d4, #c4b5fd)', '#c4b5fd', '#6d28d9'), makeGradient('noir', 'Noir', 'linear-gradient(135deg, #1f2937, #0f172a)', '#0f172a'), makeGradient('marigold', 'Marigold', 'linear-gradient(135deg, #f59e0b, #eab308)', '#eab308', '#713f12'), makeGradient('lavender', 'Lavender', 'linear-gradient(135deg, #c084fc, #a78bfa)', '#a78bfa'), makeGradient('mist', 'Mist', 'linear-gradient(135deg, #e5e7eb, #cbd5e1)', '#cbd5e1', '#334155'), makeGradient('vapor', 'Vapor', 'linear-gradient(135deg, #67e8f9, #c4b5fd, #f9a8d4)', '#c4b5fd'), makeGradient('retro', 'Retro', 'linear-gradient(135deg, #fbbf24, #ef4444, #8b5cf6)', '#ef4444'), makeGradient('crimson-flame', 'Crimson flame', 'linear-gradient(135deg, #ef4444, #dc2626, #7f1d1d)', '#7f1d1d'), makeGradient('oceanic', 'Oceanic', 'linear-gradient(135deg, #0284c7, #1e3a8a)', '#1e3a8a'), makeGradient('electric', 'Electric', 'linear-gradient(135deg, #22d3ee, #60a5fa)', '#60a5fa'), makeGradient('blossom', 'Blossom', 'linear-gradient(135deg, #ec4899, #a855f7)', '#a855f7'), makeGradient('rainbow', 'Rainbow', 'linear-gradient(90deg, #ef4444, #f59e0b, #10b981, #3b82f6, #8b5cf6)', '#8b5cf6'), makeGradient('solar', 'Solar', 'linear-gradient(135deg, #facc15, #f97316, #dc2626)', '#f97316', '#7f1d1d')];\n\n// ─── ELEVATED (~18, page-only) ───────────────────────────────────────────\n\nvar ELEVATED = [makeElevated('indigo-3d', 'Indigo · 3D', PAL.indigo, '0 4px 0 #1e40af, 0 6px 12px rgba(37,99,235,0.35)'), makeElevated('ink-3d', 'Ink · 3D', PAL.ink, '0 4px 0 #030712, 0 6px 12px rgba(17,24,39,0.45)'), makeElevated('violet-3d', 'Violet · 3D', PAL.violet, '0 4px 0 #4c1d95, 0 6px 12px rgba(124,58,237,0.35)'), makeElevated('emerald-3d', 'Emerald · 3D', PAL.emerald, '0 4px 0 #14532d, 0 6px 12px rgba(22,163,74,0.35)'), makeElevated('crimson-3d', 'Crimson · 3D', PAL.crimson, '0 4px 0 #7f1d1d, 0 6px 12px rgba(220,38,38,0.35)'), makeElevated('indigo-drop-sm', 'Indigo · drop sm', PAL.indigo, SHADOW_SCALE.sm), makeElevated('indigo-drop-md', 'Indigo · drop md', PAL.indigo, SHADOW_SCALE.md), makeElevated('indigo-drop-lg', 'Indigo · drop lg', PAL.indigo, SHADOW_SCALE.lg), makeElevated('indigo-drop-xl', 'Indigo · drop xl', PAL.indigo, SHADOW_SCALE.xl), makeElevated('ink-drop-lg', 'Ink · heavy drop', PAL.ink, SHADOW_SCALE.lg), makeElevated('amber-float', 'Amber · float', PAL.amber, '0 18px 32px -10px rgba(245,158,11,0.48)'), makeElevated('paper-soft', 'Paper · pillow', PAL.paper, '0 2px 8px rgba(0,0,0,0.08), 0 8px 20px rgba(0,0,0,0.06)', {\n fg: '#111827',\n formats: borderColor('#e5e7eb')\n}), makeElevated('emerald-float', 'Emerald · float', PAL.emerald, '0 18px 32px -10px rgba(22,163,74,0.4)'), makeElevated('rose-float', 'Rose · float', PAL.rose, '0 18px 32px -10px rgba(225,29,72,0.45)'), makeElevated('double-shadow', 'Double shadow', PAL.indigo, '0 4px 10px rgba(37,99,235,0.3), 0 12px 32px rgba(37,99,235,0.25)'), makeElevated('pressed-inner', 'Pressed · inner', PAL.indigo, SHADOW_SCALE.inner), makeElevated('stacked-card', 'Stacked card', PAL.paper, '2px 2px 0 #e5e7eb, 4px 4px 0 #d1d5db, 6px 6px 0 #9ca3af', {\n fg: '#111827'\n}), makeElevated('pro-charcoal', 'Pro · charcoal', PAL.charcoal, SHADOW_SCALE.xl)];\n\n// ─── GLASS & GLOW (~16, page-only) ───────────────────────────────────────\n\nvar GLASS = [{\n id: 'glass-default',\n category: 'glass',\n label: 'Glass',\n flags: PAGE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'rgba(255,255,255,0.18)',\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor('rgba(255,255,255,0.4)')), borderWidth('1px'))),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'glass-frost',\n category: 'glass',\n label: 'Frost · heavy blur',\n flags: PAGE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'rgba(255,255,255,0.32)',\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor('rgba(255,255,255,0.6)')), borderWidth('1px'))),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'glass-tinted-violet',\n category: 'glass',\n label: 'Glass · tinted violet',\n flags: PAGE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'rgba(124,58,237,0.2)',\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor('rgba(196,181,253,0.4)')), borderWidth('1px'))),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'glass-tinted-cyan',\n category: 'glass',\n label: 'Glass · tinted cyan',\n flags: PAGE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'rgba(6,182,212,0.2)',\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor('rgba(103,232,249,0.4)')), borderWidth('1px'))),\n icon: null,\n iconPosition: 'none'\n}, makeGlow('glow-violet', 'Glow · violet', PAL.violet, '0 0 24px rgba(124,58,237,0.55)'), makeGlow('glow-cyan', 'Glow · cyan', PAL.cyan, '0 0 24px rgba(6,182,212,0.6)'), makeGlow('glow-rose', 'Glow · rose', PAL.rose, '0 0 24px rgba(225,29,72,0.6)'), makeGlow('glow-emerald', 'Glow · emerald', PAL.emerald, '0 0 24px rgba(22,163,74,0.6)'), makeGlow('glow-amber', 'Glow · amber', PAL.amber, '0 0 24px rgba(245,158,11,0.7)'), makeGlow('glow-pink', 'Glow · pink', PAL.pink, '0 0 24px rgba(219,39,119,0.6)'), makeGlow('glow-strong-violet', 'Glow · strong', PAL.violet, '0 0 0 4px rgba(124,58,237,0.2), 0 0 32px rgba(124,58,237,0.85)'), makeGlow('halo-warm', 'Halo · warm', PAL.amber, '0 0 0 4px rgba(245,158,11,0.2), 0 0 28px rgba(245,158,11,0.6)'), makeGlow('halo-cool', 'Halo · cool', PAL.cyan, '0 0 0 4px rgba(6,182,212,0.2), 0 0 28px rgba(6,182,212,0.6)'), makeGlow('pulse-violet', 'Pulse · violet', PAL.violet, '0 0 0 2px rgba(124,58,237,0.25), 0 0 16px rgba(124,58,237,0.45), 0 0 32px rgba(124,58,237,0.25)'), makeGlow('neon-edge', 'Neon edge', PAL.pink, '0 0 0 1px #ff79c6, 0 0 12px #ff79c6, 0 0 24px rgba(255,121,198,0.6)'), {\n id: 'glass-bordered-ink',\n category: 'glass',\n label: 'Glass · bordered ink',\n flags: PAGE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: 'rgba(17,24,39,0.35)',\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor('rgba(255,255,255,0.25)')), borderWidth('1px')), {}, {\n box_shadow: '0 8px 24px rgba(0,0,0,0.35)'\n })),\n icon: null,\n iconPosition: 'none'\n}];\n\n// ─── BRUTALIST (~14) ─────────────────────────────────────────────────────\n\nvar BRUTALIST = [makeBrutalist('yellow', 'Yellow · classic', '#fde047', '#111827'), makeBrutalist('pink-loud', 'Pink · loud', '#ec4899', '#ffffff'), makeBrutalist('mono', 'Mono · stark', '#ffffff', '#111827', '#111827', {\n formats: _objectSpread(_objectSpread({}, borderWidth('3px')), {}, {\n box_shadow: '6px 6px 0 #111827',\n font_weight: '700'\n })\n}), makeBrutalist('orange', 'Orange · loud', '#fb923c', '#ffffff'), makeBrutalist('cyan', 'Cyan · loud', '#22d3ee', '#0f172a'), makeBrutalist('lime', 'Lime · sharp', '#bef264', '#1c1917'), makeBrutalist('purple', 'Purple · loud', '#a855f7', '#ffffff'), {\n id: 'brutalist-editorial-underline',\n category: 'brutalist',\n label: 'Editorial · underline',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: 'transparent',\n text_color: '#111827',\n link_color: '#111827'\n }, borderColor('transparent')), {}, {\n border_radius: '0px',\n font_family: 'Georgia, \"Times New Roman\", serif',\n font_weight: '400',\n font_size: '16px',\n letter_spacing: null\n })),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'brutalist-serif-italic',\n category: 'brutalist',\n label: 'Serif · italic',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: '#ffffff',\n text_color: '#111827',\n link_color: '#111827'\n }, borderColor('#111827')), borderWidth('1px')), {}, {\n border_radius: '0px',\n font_family: 'Georgia, \"Times New Roman\", serif'\n })),\n icon: null,\n iconPosition: 'none'\n}, {\n id: 'brutalist-all-caps',\n category: 'brutalist',\n label: 'All-caps · bordered',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: '#ffffff',\n text_color: '#111827',\n link_color: '#111827'\n }, borderColor('#111827')), borderWidth('2px')), {}, {\n border_radius: '0px',\n letter_spacing: 2,\n font_weight: '700',\n font_size: '12px'\n })),\n icon: null,\n iconPosition: 'none'\n}, makeBrutalist('red', 'Red · sharp', '#ef4444', '#ffffff'), makeBrutalist('green', 'Green · sharp', '#22c55e', '#ffffff'), makeBrutalist('sky', 'Sky · loud', '#7dd3fc', '#0c4a6e'), {\n id: 'brutalist-tab-style',\n category: 'brutalist',\n label: 'Tab-style',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n background_color: '#111827',\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor('#111827')), borderWidth('0px')), {}, {\n border_radius: '0px',\n font_weight: '600',\n letter_spacing: 1\n })),\n icon: null,\n iconPosition: 'none'\n}];\n\n// ─── ICON-LED (~14) ──────────────────────────────────────────────────────\n\nvar ICON_LED = [{\n id: 'icon-left-download',\n category: 'icon',\n label: 'Download · left',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: PAL.indigo.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.indigo.solid))),\n icon: 'download',\n iconPosition: 'left'\n}, {\n id: 'icon-right-arrow',\n category: 'icon',\n label: 'Continue · arrow',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: PAL.indigo.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.indigo.solid))),\n icon: 'arrow_forward',\n iconPosition: 'right'\n}, {\n id: 'icon-right-launch',\n category: 'icon',\n label: 'Open · external',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: PAL.indigo.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.indigo.solid))),\n icon: 'open_in_new',\n iconPosition: 'right'\n}, {\n id: 'icon-left-cart',\n category: 'icon',\n label: 'Cart · add',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: PAL.emerald.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.emerald.solid))),\n icon: 'shopping_cart',\n iconPosition: 'left'\n}, {\n id: 'icon-left-mail',\n category: 'icon',\n label: 'Email · left',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: PAL.cyan.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.cyan.solid))),\n icon: 'mail',\n iconPosition: 'left'\n}, {\n id: 'icon-left-play',\n category: 'icon',\n label: 'Play video',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: PAL.rose.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.rose.solid))),\n icon: 'play_arrow',\n iconPosition: 'left'\n}, {\n id: 'icon-only-heart-c',\n category: 'icon',\n label: 'Heart · circle',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: PAL.rose.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.rose.solid)), {}, {\n border_radius: '999px',\n padding_top: 10,\n padding_right: 10,\n padding_bottom: 10,\n padding_left: 10\n })),\n icon: 'favorite',\n iconPosition: 'only'\n}, {\n id: 'icon-only-share-s',\n category: 'icon',\n label: 'Share · square',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: PAL.slate.tone,\n text_color: PAL.slate.strong,\n link_color: PAL.slate.strong\n }, borderColor(PAL.slate.tone)), {}, {\n border_radius: '6px',\n padding_top: 10,\n padding_right: 10,\n padding_bottom: 10,\n padding_left: 10\n })),\n icon: 'share',\n iconPosition: 'only'\n}, {\n id: 'icon-only-fab-add',\n category: 'icon',\n label: 'FAB · add',\n flags: PAGE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: PAL.indigo.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.indigo.solid)), {}, {\n border_radius: '999px',\n padding_top: 18,\n padding_right: 18,\n padding_bottom: 18,\n padding_left: 18,\n box_shadow: '0 8px 24px rgba(37,99,235,0.4)'\n })),\n icon: 'add',\n iconPosition: 'only'\n}, {\n id: 'icon-only-mini-edit',\n category: 'icon',\n label: 'Mini edit',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: PAL.indigo.tone,\n text_color: PAL.indigo.toneText,\n link_color: PAL.indigo.toneText\n }, borderColor(PAL.indigo.tone)), {}, {\n border_radius: '6px',\n padding_top: 6,\n padding_right: 6,\n padding_bottom: 6,\n padding_left: 6,\n font_size: '12px'\n })),\n icon: 'edit',\n iconPosition: 'only'\n}, {\n id: 'icon-left-back',\n category: 'icon',\n label: 'Back · arrow',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: 'transparent',\n text_color: PAL.ink.solid,\n link_color: PAL.ink.solid\n }, borderColor('transparent'))),\n icon: 'arrow_back',\n iconPosition: 'left'\n}, {\n id: 'icon-left-check',\n category: 'icon',\n label: 'Confirm · check',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: PAL.emerald.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.emerald.solid))),\n icon: 'check',\n iconPosition: 'left'\n}, {\n id: 'icon-left-phone',\n category: 'icon',\n label: 'Call · phone',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n background_color: PAL.ink.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.ink.solid)), {}, {\n border_radius: '999px'\n })),\n icon: 'call',\n iconPosition: 'left'\n}, {\n id: 'icon-right-send',\n category: 'icon',\n label: 'Send · message',\n flags: SAFE,\n formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n background_color: PAL.violet.solid,\n text_color: '#ffffff',\n link_color: '#ffffff'\n }, borderColor(PAL.violet.solid))),\n icon: 'send',\n iconPosition: 'right'\n}];\n\n// ─── REGISTRY ────────────────────────────────────────────────────────────\n\nvar PRESETS = [].concat(SOLID, OUTLINE, TONAL, GHOST, GRADIENT, ELEVATED, GLASS, BRUTALIST, ICON_LED);\nvar CATEGORIES = [{\n id: 'solid',\n label: 'Solid',\n order: 1\n}, {\n id: 'outline',\n label: 'Outline',\n order: 2\n}, {\n id: 'tonal',\n label: 'Tonal',\n order: 3\n}, {\n id: 'ghost',\n label: 'Ghost',\n order: 4\n}, {\n id: 'gradient',\n label: 'Gradient',\n order: 5\n}, {\n id: 'elevated',\n label: 'Elevated',\n order: 6\n}, {\n id: 'glass',\n label: 'Glass & Glow',\n order: 7\n}, {\n id: 'brutalist',\n label: 'Brutalist',\n order: 8\n}, {\n id: 'icon',\n label: 'Icon-Led',\n order: 9\n}];\n\n/**\n * Find a preset by id. Returns null if not found (caller must decide: skip,\n * fall back to 'solid-indigo', or throw). Saved templates may carry a\n * preset_id that was removed in a later revision — callers should treat\n * null as \"unknown preset, keep current formatter as-is\".\n */\nfunction findPreset(id) {\n if (!id) return null;\n return PRESETS.find(function (p) {\n return p.id === id;\n }) || null;\n}\nfunction presetsByCategory(catId) {\n return PRESETS.filter(function (p) {\n return p.category === catId;\n });\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n SIZE_SCALE: SIZE_SCALE,\n SIZE_KEYS: SIZE_KEYS,\n SHADOW_SCALE: SHADOW_SCALE,\n SHADOW_KEYS: SHADOW_KEYS,\n HOVER_EFFECT_KEYS: HOVER_EFFECT_KEYS,\n PRESETS: PRESETS,\n CATEGORIES: CATEGORIES,\n findPreset: findPreset,\n presetsByCategory: presetsByCategory\n});\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/buttonPresets.js?");
/***/ }),
/***/ "./src/includes/overlays/AIRewritePopoverOverlay.js":
/*!**********************************************************!*\
!*** ./src/includes/overlays/AIRewritePopoverOverlay.js ***!
\**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * AIRewritePopoverOverlay — W6.1 inline AI rewrite popover.\n *\n * TEXT_INLINE_PLAN W6.1 (2026-04-21). First consumer of the new AI Task\n * framework. Mounts on the toolbar's sparkle button, lets the user\n * transform the current selection via 8 action presets × tone × length ×\n * custom prompt × variant carousel.\n *\n * Calls POST {builder.ai.inlineRewriteUrl} with payload:\n * { text, action, tone?, length?, custom_instruction?, variant_count,\n * element: { type, role }, block: { purpose, siblings },\n * currentPage: builder.getData() }\n *\n * Response (uniform AITaskResult shape):\n * { status, primary, variants[], data: { action, variant_count }, engine, model }\n *\n * UX states (W6.1 acceptance):\n * - idle: action chip grid + tone + length + custom prompt + Rewrite CTA\n * - loading: inputs disabled, shimmer over result slot, sparkle pulses\n * - result: variant card(s) with arrow nav + Apply / Try again / Undo\n * - error: red banner + retry button (status preserved)\n * - rate-limited: friendly countdown\n * - disabled: \"AI not configured\" panel (when ai.enabled=false or url null)\n *\n * HARD RULES applied:\n * T1 (selection = source of truth): popover holds saved selection range,\n * restores before applying variant.\n * T2 (no rerender on apply): selection's containing element receives the\n * new HTML via `range.deleteContents()` + `range.insertNode()` then\n * element is asked for a stable inline-only re-snapshot.\n * T6 (failure visible): every error path renders an error bubble.\n * T8 (host page sacred): mounts inside .bjs-overlay-root (popover host).\n * T9 (inline scope): backend-side InlineHtmlSanitizer enforces; frontend\n * uses InlineSanitizer.normalize after insert.\n */\n\n\n\n\nvar QUICK_ACTIONS = [{\n key: 'improve',\n icon: 'auto_fix_normal',\n labelKey: 'ai_rewrite.action_improve'\n}, {\n key: 'shorten',\n icon: 'compress',\n labelKey: 'ai_rewrite.action_shorten'\n}, {\n key: 'expand',\n icon: 'expand',\n labelKey: 'ai_rewrite.action_expand'\n}, {\n key: 'simplify',\n icon: 'lightbulb',\n labelKey: 'ai_rewrite.action_simplify'\n}, {\n key: 'fix_grammar',\n icon: 'spellcheck',\n labelKey: 'ai_rewrite.action_fix_grammar'\n}, {\n key: 'cta_ify',\n icon: 'campaign',\n labelKey: 'ai_rewrite.action_cta_ify'\n}, {\n key: 'translate',\n icon: 'translate',\n labelKey: 'ai_rewrite.action_translate'\n}, {\n key: 'rewrite',\n icon: 'edit_note',\n labelKey: 'ai_rewrite.action_custom'\n}];\nvar TONES = ['formal', 'casual', 'playful', 'persuasive', 'friendly', 'urgent'];\nvar LENGTHS = ['shorter', 'same', 'longer'];\nvar AIRewritePopoverOverlay = /*#__PURE__*/function () {\n /**\n * @param {TextInlineToolbarOverlay} toolbar — owner, used to share selection save/restore.\n * @param {{ anchorBtn: HTMLElement, builder: object }} opts\n */\n function AIRewritePopoverOverlay(toolbar, opts) {\n _classCallCheck(this, AIRewritePopoverOverlay);\n if (!toolbar || !opts || !opts.anchorBtn || !opts.builder) {\n throw new Error('AIRewritePopoverOverlay: toolbar + opts.anchorBtn + opts.builder required');\n }\n this._toolbar = toolbar;\n this._builder = opts.builder;\n this._anchorBtn = opts.anchorBtn;\n this._ai = opts.builder && opts.builder.ai || {};\n this.domNode = null;\n this._positionHandle = null;\n this._onDocKey = null;\n this._onDocMouseDown = null;\n this._mounted = false;\n\n // Form state\n this._action = 'rewrite';\n this._tone = null;\n this._length = 'same';\n this._custom = '';\n this._variantCount = 1;\n\n // Result state\n this._variants = [];\n this._activeVariantIndex = 0;\n this._previousHtml = null; // for undo\n this._savedRange = null; // selection range at open time\n this._snapshotText = null; // original text for fallback\n this._isLoading = false;\n this._errorState = null;\n }\n return _createClass(AIRewritePopoverOverlay, [{\n key: \"open\",\n value: function open() {\n var _this = this;\n if (this._mounted) return;\n try {\n this._captureSelection();\n this._build();\n document.body.appendChild(this.domNode);\n this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n anchor: function anchor() {\n return _this._anchorBtn.getBoundingClientRect();\n },\n target: this.domNode,\n offset: 8,\n collisionPadding: 12,\n preferredSide: 'below',\n flip: true\n });\n this._registerDismissListeners();\n this._mounted = true;\n this._anchorBtn.setAttribute('aria-expanded', 'true');\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[bjs:ai-rewrite] open failed:', err);\n this.close();\n }\n }\n }, {\n key: \"close\",\n value: function close() {\n if (!this._mounted && !this.domNode) return;\n this._unregisterDismissListeners();\n if (this._positionHandle) {\n try {\n this._positionHandle.dispose();\n } catch (_) {}\n this._positionHandle = null;\n }\n if (this.domNode && this.domNode.parentNode) {\n try {\n this.domNode.parentNode.removeChild(this.domNode);\n } catch (_) {}\n }\n this.domNode = null;\n this._mounted = false;\n this._anchorBtn.removeAttribute('aria-expanded');\n }\n }, {\n key: \"isOpen\",\n value: function isOpen() {\n return this._mounted;\n }\n\n /* ── selection ────────────────────────────────────────────────── */\n }, {\n key: \"_captureSelection\",\n value: function _captureSelection() {\n var tracker = this._builder && this._builder.textSelectionTracker;\n var last = tracker && typeof tracker.getLast === 'function' ? tracker.getLast() : null;\n if (last && last.range) {\n this._savedRange = last.range.cloneRange();\n this._snapshotText = last.text || last.range.toString();\n return;\n }\n // Fallback — try active selection in iframe.\n try {\n var iframeDoc = this._builder.iframe && this._builder.iframe.contentDocument || document;\n var sel = iframeDoc.getSelection ? iframeDoc.getSelection() : null;\n if (sel && sel.rangeCount > 0) {\n this._savedRange = sel.getRangeAt(0).cloneRange();\n this._snapshotText = sel.toString();\n }\n } catch (_) {\n this._savedRange = null;\n this._snapshotText = null;\n }\n }\n\n /* ── build DOM ────────────────────────────────────────────────── */\n }, {\n key: \"_build\",\n value: function _build() {\n var p = document.createElement('div');\n p.className = 'bjs-ovl bjs-ovl-ai-rewrite';\n p.setAttribute('role', 'dialog');\n p.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.dialog_title'));\n p.setAttribute('data-interactive', '');\n var aiAvailable = !!(this._ai.enabled && this._ai.inlineRewriteUrl);\n if (!aiAvailable) {\n p.appendChild(this._renderDisabled());\n this.domNode = p;\n return;\n }\n p.appendChild(this._renderHeader());\n this._bodyEl = document.createElement('div');\n this._bodyEl.className = 'bjs-ovl-ai-body';\n p.appendChild(this._bodyEl);\n this._renderForm();\n this.domNode = p;\n }\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var _this2 = this;\n var h = document.createElement('div');\n h.className = 'bjs-ovl-ai-header';\n h.innerHTML = \"\\n <span class=\\\"bjs-ovl-ai-title\\\">\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.dialog_title')), \"</span>\\n <button type=\\\"button\\\" class=\\\"bjs-ovl-ai-close\\\" aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.close')), \"\\\">\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">close</span>\\n </button>\\n \");\n h.querySelector('.bjs-ovl-ai-close').addEventListener('click', function (e) {\n e.preventDefault();\n _this2.close();\n });\n return h;\n }\n }, {\n key: \"_renderDisabled\",\n value: function _renderDisabled() {\n var _this3 = this;\n var d = document.createElement('div');\n d.className = 'bjs-ovl-ai-disabled';\n d.innerHTML = \"\\n <div class=\\\"bjs-ovl-ai-disabled-icon\\\"><span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">block</span></div>\\n <div class=\\\"bjs-ovl-ai-disabled-title\\\">\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.disabled_title')), \"</div>\\n <div class=\\\"bjs-ovl-ai-disabled-msg\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.disabled_msg')), \"</div>\\n <button type=\\\"button\\\" class=\\\"bjs-ovl-ai-btn bjs-ovl-ai-btn-secondary\\\" data-action=\\\"close\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.close')), \"</button>\\n \");\n d.querySelector('[data-action=\"close\"]').addEventListener('click', function () {\n return _this3.close();\n });\n return d;\n }\n }, {\n key: \"_renderForm\",\n value: function _renderForm() {\n var _this4 = this;\n this._bodyEl.innerHTML = '';\n\n // Quick actions chip grid\n var actionsLabel = document.createElement('div');\n actionsLabel.className = 'bjs-ovl-ai-section-label';\n actionsLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.quick_actions');\n this._bodyEl.appendChild(actionsLabel);\n var actionsGrid = document.createElement('div');\n actionsGrid.className = 'bjs-ovl-ai-actions-grid';\n QUICK_ACTIONS.forEach(function (act) {\n var btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'bjs-ovl-ai-action-chip';\n btn.dataset.action = act.key;\n if (_this4._action === act.key) btn.classList.add('is-selected');\n btn.innerHTML = \"\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\".concat(act.icon, \"</span>\\n <span class=\\\"bjs-ovl-ai-action-label\\\">\").concat(_this4._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(act.labelKey)), \"</span>\\n \");\n btn.addEventListener('click', function () {\n _this4._action = act.key;\n _this4._bodyEl.querySelectorAll('.bjs-ovl-ai-action-chip').forEach(function (c) {\n return c.classList.remove('is-selected');\n });\n btn.classList.add('is-selected');\n _this4._updateRewriteEnabled();\n });\n actionsGrid.appendChild(btn);\n });\n this._bodyEl.appendChild(actionsGrid);\n\n // Tone chip row\n var toneLabel = document.createElement('div');\n toneLabel.className = 'bjs-ovl-ai-section-label';\n toneLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.tone');\n this._bodyEl.appendChild(toneLabel);\n var toneRow = document.createElement('div');\n toneRow.className = 'bjs-ovl-ai-tone-row';\n TONES.forEach(function (t) {\n var chip = document.createElement('button');\n chip.type = 'button';\n chip.className = 'bjs-ovl-ai-tone-chip';\n chip.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.tone_' + t);\n chip.dataset.tone = t;\n if (_this4._tone === t) chip.classList.add('is-selected');\n chip.addEventListener('click', function () {\n _this4._tone = _this4._tone === t ? null : t;\n toneRow.querySelectorAll('.bjs-ovl-ai-tone-chip').forEach(function (c) {\n return c.classList.remove('is-selected');\n });\n if (_this4._tone === t) chip.classList.add('is-selected');\n });\n toneRow.appendChild(chip);\n });\n this._bodyEl.appendChild(toneRow);\n\n // Length segmented\n var lengthLabel = document.createElement('div');\n lengthLabel.className = 'bjs-ovl-ai-section-label';\n lengthLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.length');\n this._bodyEl.appendChild(lengthLabel);\n var lengthSeg = document.createElement('div');\n lengthSeg.className = 'bjs-ovl-ai-length-seg';\n LENGTHS.forEach(function (len) {\n var seg = document.createElement('button');\n seg.type = 'button';\n seg.className = 'bjs-ovl-ai-length-seg-btn';\n seg.dataset.length = len;\n seg.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.length_' + len);\n if (_this4._length === len) seg.classList.add('is-selected');\n seg.addEventListener('click', function () {\n _this4._length = len;\n lengthSeg.querySelectorAll('.bjs-ovl-ai-length-seg-btn').forEach(function (c) {\n return c.classList.remove('is-selected');\n });\n seg.classList.add('is-selected');\n });\n lengthSeg.appendChild(seg);\n });\n this._bodyEl.appendChild(lengthSeg);\n\n // Custom prompt\n var customLabel = document.createElement('div');\n customLabel.className = 'bjs-ovl-ai-section-label';\n customLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.custom_prompt');\n this._bodyEl.appendChild(customLabel);\n var customWrap = document.createElement('div');\n customWrap.className = 'bjs-ovl-ai-custom-wrap';\n var customInput = document.createElement('textarea');\n customInput.className = 'bjs-ovl-ai-custom-input';\n customInput.rows = 2;\n customInput.maxLength = 300;\n customInput.placeholder = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.custom_placeholder');\n customInput.value = this._custom;\n customInput.addEventListener('input', function () {\n _this4._custom = customInput.value;\n _this4._updateRewriteEnabled();\n });\n customInput.addEventListener('keydown', function (e) {\n if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n e.preventDefault();\n _this4._runRewrite();\n }\n });\n customWrap.appendChild(customInput);\n this._bodyEl.appendChild(customWrap);\n\n // CTA\n var cta = document.createElement('div');\n cta.className = 'bjs-ovl-ai-cta';\n var cancelBtn = document.createElement('button');\n cancelBtn.type = 'button';\n cancelBtn.className = 'bjs-ovl-ai-btn bjs-ovl-ai-btn-secondary';\n cancelBtn.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.cancel');\n cancelBtn.addEventListener('click', function () {\n return _this4.close();\n });\n var rewriteBtn = document.createElement('button');\n rewriteBtn.type = 'button';\n rewriteBtn.className = 'bjs-ovl-ai-btn bjs-ovl-ai-btn-primary';\n rewriteBtn.dataset.role = 'rewrite';\n rewriteBtn.innerHTML = \"\\n <span>\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.rewrite')), \"</span>\\n <span class=\\\"bjs-ovl-ai-cta-shortcut\\\">\\u2318\\u21B5</span>\\n \");\n rewriteBtn.addEventListener('click', function () {\n return _this4._runRewrite();\n });\n this._rewriteBtn = rewriteBtn;\n cta.appendChild(cancelBtn);\n cta.appendChild(rewriteBtn);\n this._bodyEl.appendChild(cta);\n this._updateRewriteEnabled();\n }\n }, {\n key: \"_updateRewriteEnabled\",\n value: function _updateRewriteEnabled() {\n if (!this._rewriteBtn) return;\n // Always enabled once an action is selected (default 'rewrite' = true).\n var enabled = !this._isLoading && !!this._action;\n this._rewriteBtn.disabled = !enabled;\n this._rewriteBtn.classList.toggle('is-disabled', !enabled);\n }\n\n /* ── result rendering ─────────────────────────────────────────── */\n }, {\n key: \"_renderLoading\",\n value: function _renderLoading() {\n this._bodyEl.innerHTML = '';\n var wrap = document.createElement('div');\n wrap.className = 'bjs-ovl-ai-loading';\n // Skeleton shimmer lines — grey tones, staggered pulse; 3 bouncing\n // dots in the status row. No sparkle, no violet. Feels \"thumbing\"\n // (alive) while staying in the builderjs neutral palette.\n wrap.innerHTML = \"\\n <div class=\\\"bjs-ovl-ai-loading-lines\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"bjs-ovl-ai-loading-line\\\"></div>\\n <div class=\\\"bjs-ovl-ai-loading-line\\\"></div>\\n <div class=\\\"bjs-ovl-ai-loading-line\\\"></div>\\n </div>\\n <div class=\\\"bjs-ovl-ai-loading-text\\\">\\n <span class=\\\"bjs-ovl-ai-loading-dots\\\" aria-hidden=\\\"true\\\">\\n <span class=\\\"bjs-ovl-ai-loading-dot\\\"></span>\\n <span class=\\\"bjs-ovl-ai-loading-dot\\\"></span>\\n <span class=\\\"bjs-ovl-ai-loading-dot\\\"></span>\\n </span>\\n <span>\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.loading')), \"</span>\\n </div>\\n \");\n this._bodyEl.appendChild(wrap);\n }\n }, {\n key: \"_renderResult\",\n value: function _renderResult() {\n var _this5 = this;\n this._bodyEl.innerHTML = '';\n var wrap = document.createElement('div');\n wrap.className = 'bjs-ovl-ai-result';\n\n // Variant carousel header\n if (this._variants.length > 1) {\n var tabs = document.createElement('div');\n tabs.className = 'bjs-ovl-ai-variant-tabs';\n this._variants.forEach(function (_, i) {\n var tab = document.createElement('button');\n tab.type = 'button';\n tab.className = 'bjs-ovl-ai-variant-tab';\n tab.textContent = String(i + 1);\n if (i === _this5._activeVariantIndex) tab.classList.add('is-active');\n tab.addEventListener('click', function () {\n _this5._activeVariantIndex = i;\n _this5._renderResult();\n });\n tabs.appendChild(tab);\n });\n wrap.appendChild(tabs);\n }\n\n // Active variant card\n var card = document.createElement('div');\n card.className = 'bjs-ovl-ai-variant-card';\n card.innerHTML = this._variants[this._activeVariantIndex] || '';\n wrap.appendChild(card);\n\n // Action row\n var actions = document.createElement('div');\n actions.className = 'bjs-ovl-ai-result-actions';\n var tryAgain = document.createElement('button');\n tryAgain.type = 'button';\n tryAgain.className = 'bjs-ovl-ai-btn bjs-ovl-ai-btn-secondary';\n tryAgain.innerHTML = \"<span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">refresh</span> <span>\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.try_again')), \"</span>\");\n tryAgain.addEventListener('click', function () {\n return _this5._runRewrite();\n });\n var apply = document.createElement('button');\n apply.type = 'button';\n apply.className = 'bjs-ovl-ai-btn bjs-ovl-ai-btn-primary';\n apply.innerHTML = \"<span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">check</span> <span>\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.apply')), \"</span>\");\n apply.addEventListener('click', function () {\n return _this5._applyVariant(_this5._variants[_this5._activeVariantIndex]);\n });\n actions.appendChild(tryAgain);\n actions.appendChild(apply);\n wrap.appendChild(actions);\n this._bodyEl.appendChild(wrap);\n }\n }, {\n key: \"_renderError\",\n value: function _renderError(errorType, message, retryAfter) {\n var _this6 = this;\n this._bodyEl.innerHTML = '';\n var labels = {\n rate_limit: 'ai_rewrite.error_rate_limit',\n disabled: 'ai_rewrite.error_disabled',\n timeout: 'ai_rewrite.error_timeout',\n engine: 'ai_rewrite.error_engine',\n configuration: 'ai_rewrite.error_configuration',\n validation: 'ai_rewrite.error_validation',\n internal: 'ai_rewrite.error_internal',\n task_not_found: 'ai_rewrite.error_task_not_found'\n };\n var labelKey = labels[errorType] || 'ai_rewrite.error_unknown';\n var wrap = document.createElement('div');\n wrap.className = 'bjs-ovl-ai-error';\n var iconText = errorType === 'rate_limit' ? 'hourglass_empty' : 'error';\n var retryHint = errorType === 'rate_limit' && retryAfter ? \" (~\".concat(retryAfter, \"s)\") : '';\n wrap.innerHTML = \"\\n <div class=\\\"bjs-ovl-ai-error-icon\\\"><span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\".concat(iconText, \"</span></div>\\n <div class=\\\"bjs-ovl-ai-error-label\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey))).concat(this._escape(retryHint), \"</div>\\n <div class=\\\"bjs-ovl-ai-error-msg\\\">\").concat(this._escape(message || ''), \"</div>\\n <div class=\\\"bjs-ovl-ai-error-actions\\\">\\n <button type=\\\"button\\\" class=\\\"bjs-ovl-ai-btn bjs-ovl-ai-btn-secondary\\\" data-action=\\\"back\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.back')), \"</button>\\n <button type=\\\"button\\\" class=\\\"bjs-ovl-ai-btn bjs-ovl-ai-btn-primary\\\" data-action=\\\"retry\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.try_again')), \"</button>\\n </div>\\n \");\n wrap.querySelector('[data-action=\"back\"]').addEventListener('click', function () {\n return _this6._renderForm();\n });\n wrap.querySelector('[data-action=\"retry\"]').addEventListener('click', function () {\n return _this6._runRewrite();\n });\n this._bodyEl.appendChild(wrap);\n }\n\n /* ── network ──────────────────────────────────────────────────── */\n }, {\n key: \"_runRewrite\",\n value: (function () {\n var _runRewrite2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var url, text, payload, _headers, res, data;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n url = this._ai.inlineRewriteUrl;\n if (url) {\n _context.next = 4;\n break;\n }\n this._renderError('configuration', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.disabled_msg'));\n return _context.abrupt(\"return\");\n case 4:\n text = this._snapshotText || '';\n if (text.trim()) {\n _context.next = 8;\n break;\n }\n this._renderError('validation', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.error_empty_selection'));\n return _context.abrupt(\"return\");\n case 8:\n this._isLoading = true;\n this._renderLoading();\n payload = {\n text: text,\n action: this._action,\n tone: this._tone || undefined,\n length: this._length || undefined,\n custom_instruction: this._custom || undefined,\n variant_count: this._variantCount,\n element: this._collectElementContext(),\n block: this._collectBlockContext(),\n // Optional locale hint — backend/LLM can use to bias output\n // language when ambiguous. Auto-detected from BuilderJS I18n.\n user_locale: (typeof _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getLocale === 'function' ? _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getLocale() : null) || undefined\n }; // Include page only for actions that benefit (matches backend\n // BuilderPageContextProvider tier-3 trigger list).\n if (['improve', 'cta_ify', 'rewrite_on_brand'].includes(this._action)) {\n try {\n payload.currentPage = this._builder.getData();\n } catch (_) {}\n }\n _context.prev = 12;\n // F11.1 (2026-04-28) — hosted AI endpoints typically require\n // auth via web session OR API token. Send Authorization: Bearer\n // header when consumer supplied `ai.apiToken` (BuilderJS demo\n // cross-origin path) — preferred over `?api_token=` query for\n // header hygiene. Same-origin server-rendered callers ride the\n // session cookie and leave apiToken empty.\n _headers = {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'X-CSRF-TOKEN': this._ai.csrfToken || ''\n };\n if (this._ai.apiToken) _headers['Authorization'] = 'Bearer ' + this._ai.apiToken;\n _context.next = 17;\n return fetch(url, {\n method: 'POST',\n headers: _headers,\n body: JSON.stringify(payload)\n });\n case 17:\n res = _context.sent;\n _context.next = 20;\n return res.json()[\"catch\"](function () {\n return {};\n });\n case 20:\n data = _context.sent;\n this._isLoading = false;\n if (!(!res.ok || data.status === 'error')) {\n _context.next = 25;\n break;\n }\n this._renderError(data.error_type || 'unknown', data.message || \"HTTP \".concat(res.status), data.retry_after);\n return _context.abrupt(\"return\");\n case 25:\n this._variants = Array.isArray(data.variants) && data.variants.length > 0 ? data.variants : data.primary ? [data.primary] : [];\n if (!(this._variants.length === 0)) {\n _context.next = 29;\n break;\n }\n this._renderError('engine', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.error_no_variants'));\n return _context.abrupt(\"return\");\n case 29:\n this._activeVariantIndex = 0;\n this._renderResult();\n _context.next = 37;\n break;\n case 33:\n _context.prev = 33;\n _context.t0 = _context[\"catch\"](12);\n this._isLoading = false;\n this._renderError('internal', String(_context.t0 && _context.t0.message || _context.t0));\n case 37:\n case \"end\":\n return _context.stop();\n }\n }, _callee, this, [[12, 33]]);\n }));\n function _runRewrite() {\n return _runRewrite2.apply(this, arguments);\n }\n return _runRewrite;\n }() /* ── apply / undo ─────────────────────────────────────────────── */)\n }, {\n key: \"_applyVariant\",\n value: function _applyVariant(variantHtml) {\n if (!variantHtml || !this._savedRange) {\n this.close();\n return;\n }\n try {\n var range = this._savedRange;\n var container = range.commonAncestorContainer;\n var host = container && container.nodeType === 1 ? container : container && container.parentElement;\n\n // Snapshot for history.\n var elementHost = host && host.closest ? host.closest('[builder-element]') : null;\n var elementUid = elementHost ? elementHost.getAttribute('builder-element-uid') : null;\n var elementType = elementHost ? elementHost.getAttribute('builder-element-kind') || elementHost.tagName.toLowerCase() : null;\n var originalSnippet = this._snapshotText || '';\n\n // Replace selection contents with new HTML.\n range.deleteContents();\n var tmp = document.createElement('span');\n tmp.innerHTML = variantHtml;\n var frag = document.createDocumentFragment();\n while (tmp.firstChild) frag.appendChild(tmp.firstChild);\n range.insertNode(frag);\n\n // Normalize inline markup (T9).\n if (host && _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"] && typeof _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].normalize === 'function') {\n try {\n _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].normalize(host);\n } catch (_) {}\n }\n\n // Keep the element's internal state in sync — inline toolbar uses\n // a char-offset SHIM pattern; we update the owning element's text\n // cache so next render/parse reflects what the user sees.\n if (elementUid && this._builder && this._builder.findElement) {\n try {\n var el = this._builder.findElement(elementUid);\n if (el && typeof el.setText === 'function' && host) {\n el.setText(host.innerHTML);\n }\n } catch (_) {/* tolerate */}\n }\n\n // Commit a rich history entry so Undo/Redo restores pre-rewrite\n // state and the HistoryWidget shows a meaningful label + icon.\n // Uses new change type 'ai:inline_rewrite' — mapped to\n // `auto_fix_normal` icon in HistoryWidget.ICON_FOR_CHANGE.\n try {\n if (this._builder && this._builder.history && typeof this._builder.history.commit === 'function') {\n var actionKey = this._action || 'rewrite';\n var actionLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.ai_action_' + actionKey) || actionKey.replace(/_/g, ' ');\n this._builder.history.commit('history.ai_inline_rewrite', {\n source: 'ai',\n change: 'ai:inline_rewrite',\n elementUid: elementUid,\n elementType: elementType,\n action: actionKey,\n prompt: actionLabel,\n tone: this._tone || null,\n length: this._length || null,\n oldValue: this._truncate(originalSnippet, 80),\n newValue: this._truncate(this._stripTags(variantHtml), 80)\n });\n }\n } catch (err) {\n // eslint-disable-next-line no-console\n console.warn('[bjs:ai-rewrite] history commit failed:', err);\n }\n this._showAppliedToast();\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[bjs:ai-rewrite] apply failed:', err);\n }\n this.close();\n }\n }, {\n key: \"_truncate\",\n value: function _truncate(s, n) {\n var str = String(s == null ? '' : s);\n return str.length > n ? str.slice(0, n - 1) + '…' : str;\n }\n }, {\n key: \"_stripTags\",\n value: function _stripTags(s) {\n return String(s == null ? '' : s).replace(/<[^>]*>/g, '');\n }\n }, {\n key: \"_showAppliedToast\",\n value: function _showAppliedToast() {\n try {\n var toast = document.createElement('div');\n toast.className = 'bjs-ovl-ai-toast';\n toast.innerHTML = \"\\n <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">check</span>\\n <span>\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.applied_toast')), \"</span>\\n \");\n document.body.appendChild(toast);\n setTimeout(function () {\n toast.classList.add('is-fading');\n setTimeout(function () {\n try {\n toast.remove();\n } catch (_) {}\n }, 300);\n }, 3500);\n } catch (_) {}\n }\n\n /* ── context collection ───────────────────────────────────────── */\n }, {\n key: \"_collectElementContext\",\n value: function _collectElementContext() {\n try {\n var node = this._savedRange ? this._savedRange.commonAncestorContainer : null;\n var host = node && node.nodeType === 1 ? node : node && node.parentElement;\n var inlineHost = host && host.closest ? host.closest('[data-bjs-inline-text]') : null;\n var elementHost = host && host.closest ? host.closest('[builder-element]') : null;\n return {\n type: elementHost ? elementHost.getAttribute('builder-element-kind') || elementHost.tagName.toLowerCase() : null,\n role: inlineHost ? inlineHost.getAttribute('data-bjs-inline-text') || null : null\n };\n } catch (_) {\n return null;\n }\n }\n }, {\n key: \"_collectBlockContext\",\n value: function _collectBlockContext() {\n var _this7 = this;\n try {\n var node = this._savedRange ? this._savedRange.commonAncestorContainer : null;\n var host = node && node.nodeType === 1 ? node : node && node.parentElement;\n var block = host && host.closest ? host.closest('[builder-element=\"BlockElement\"]') : null;\n if (!block) return null;\n var siblings = [];\n block.querySelectorAll('[data-bjs-inline-text]').forEach(function (el) {\n var txt = (el.textContent || '').trim();\n if (txt && txt !== _this7._snapshotText) siblings.push(txt.slice(0, 80));\n });\n return {\n purpose: block.getAttribute('data-block-purpose') || null,\n siblings: siblings.slice(0, 4)\n };\n } catch (_) {\n return null;\n }\n }\n\n /* ── dismissal ────────────────────────────────────────────────── */\n }, {\n key: \"_registerDismissListeners\",\n value: function _registerDismissListeners() {\n var _this8 = this;\n this._onDocKey = function (e) {\n if (e.key === 'Escape') {\n e.preventDefault();\n _this8.close();\n }\n };\n this._onDocMouseDown = function (e) {\n if (!_this8.domNode) return;\n var inside = _this8.domNode.contains(e.target) || _this8._anchorBtn && _this8._anchorBtn.contains(e.target);\n if (!inside) _this8.close();\n };\n document.addEventListener('keydown', this._onDocKey, true);\n document.addEventListener('mousedown', this._onDocMouseDown, true);\n }\n }, {\n key: \"_unregisterDismissListeners\",\n value: function _unregisterDismissListeners() {\n if (this._onDocKey) document.removeEventListener('keydown', this._onDocKey, true);\n if (this._onDocMouseDown) document.removeEventListener('mousedown', this._onDocMouseDown, true);\n this._onDocKey = null;\n this._onDocMouseDown = null;\n }\n\n /* ── util ─────────────────────────────────────────────────────── */\n }, {\n key: \"_escape\",\n value: function _escape(s) {\n return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''');\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AIRewritePopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/AIRewritePopoverOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/AnchoredPopoverOverlay.js":
/*!*********************************************************!*\
!*** ./src/includes/overlays/AnchoredPopoverOverlay.js ***!
\*********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * AnchoredPopoverOverlay — 2026-04-19 (Image overlay refactor Phase E).\n *\n * Compact popover for `'edit'`-mode overlays that should NOT take over\n * the full viewport with a modal mask. Anchors next to a target rect\n * (typically the action-bar button that opened it) so the canvas stays\n * visible + the user keeps spatial context. Sibling primitive of\n * `InlineEditorOverlay` (modal form); pick whichever fits the UX:\n *\n * InlineEditorOverlay — full-viewport mask + centered card.\n * Best for deep editing (full crop UI with\n * preview, focus dot, sliders).\n * AnchoredPopoverOverlay — small popover next to anchor; canvas\n * stays interactive (click outside to close).\n * Best for quick edits without losing canvas.\n *\n * Both primitives can host the SAME body content (embedded controls)\n * because the surface chrome (mask vs popover, header vs no-header) is\n * the only thing that differs. Subclasses build the body once and pass\n * it to the surface variant of their choice.\n *\n * Lifecycle:\n * - render() — subclass builds DOM (the popover panel + body).\n * - position() — anchors next to opts.anchorTo (function returning\n * DOMRect in viewport coords) with smart flip logic.\n * - On open: registers Esc + outside-click → exitEditMode.\n * - beforeDestroy() — removes listeners + lets subclass dispose\n * embedded controls.\n *\n * Positioning algorithm:\n * 1. Compute anchor rect.\n * 2. Try preferred side (default 'right'); if not enough space, try\n * 'left'; if neither fits horizontally, try 'bottom'; final\n * fallback 'top'.\n * 3. Vertical alignment: align with anchor's vertical center, then\n * clamp into viewport with 12px margin.\n *\n * Constructor opts:\n * anchorTo — function() → DOMRect | DOMRect | HTMLElement\n * (required; if missing, falls back to element.domNode rect)\n * side — 'right' | 'left' | 'bottom' | 'top' (preferred; default 'right')\n * gap — pixels between anchor and popover (default 8)\n * width — popover width in px (default 320)\n * maxHeight — popover max-height in px (default 480)\n */\n\nvar VIEWPORT_MARGIN = 12;\nvar DEFAULT_GAP = 8;\nvar DEFAULT_WIDTH = 320;\nvar DEFAULT_MAX_HEIGHT = 480;\nvar AnchoredPopoverOverlay = /*#__PURE__*/function (_BaseOverlay) {\n function AnchoredPopoverOverlay() {\n _classCallCheck(this, AnchoredPopoverOverlay);\n return _callSuper(this, AnchoredPopoverOverlay, arguments);\n }\n _inherits(AnchoredPopoverOverlay, _BaseOverlay);\n return _createClass(AnchoredPopoverOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'edit';\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this = this;\n // Subclass MUST build this.domNode + assign body content. This\n // base render() just sets up the shared chrome class + listeners.\n if (!this.domNode) {\n this.domNode = document.createElement('div');\n }\n this.domNode.classList.add('bjs-ovl-anchored-popover');\n this.domNode.setAttribute('data-interactive', '');\n this.domNode.setAttribute('role', 'dialog');\n\n // Esc to close.\n this._onKey = function (e) {\n if (e.key === 'Escape') {\n e.stopPropagation();\n if (_this.element && typeof _this.element.exitEditMode === 'function') {\n _this.element.exitEditMode();\n }\n }\n };\n document.addEventListener('keydown', this._onKey, true);\n\n // Outside-click to close. Use capture phase + check via\n // composedPath/closest to handle clicks across iframe boundary.\n this._onOutsideClick = function (e) {\n if (!_this.domNode) return;\n var t = e.target;\n if (_this.domNode.contains(t)) return;\n // Allow clicks on the action bar button that opened the\n // popover — without this guard the button click that opens\n // the popover instantly closes it again.\n if (t && typeof t.closest === 'function' && t.closest('.bjs-ovl-pill')) return;\n if (_this.element && typeof _this.element.exitEditMode === 'function') {\n _this.element.exitEditMode();\n }\n };\n // Defer one tick so the click that OPENED the popover isn't\n // immediately picked up by this handler (would close instantly).\n setTimeout(function () {\n document.addEventListener('mousedown', _this._onOutsideClick, true);\n }, 0);\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n if (this._onKey) document.removeEventListener('keydown', this._onKey, true);\n if (this._onOutsideClick) document.removeEventListener('mousedown', this._onOutsideClick, true);\n this._onKey = null;\n this._onOutsideClick = null;\n }\n }, {\n key: \"position\",\n value: function position() {\n if (!this.domNode) return;\n\n // Set explicit width up-front so measurement is stable.\n var width = this.opts && this.opts.width || DEFAULT_WIDTH;\n var maxHeight = this.opts && this.opts.maxHeight || DEFAULT_MAX_HEIGHT;\n Object.assign(this.domNode.style, {\n position: 'fixed',\n width: width + 'px',\n maxHeight: maxHeight + 'px'\n });\n\n // Force a layout to read the actual rendered height (bound by content + maxHeight).\n var popoverHeight = this.domNode.offsetHeight || 0;\n var anchorRect = this._resolveAnchorRect();\n if (!anchorRect) {\n // Fallback — center on viewport.\n Object.assign(this.domNode.style, {\n top: Math.max(VIEWPORT_MARGIN, (window.innerHeight - popoverHeight) / 2) + 'px',\n left: Math.max(VIEWPORT_MARGIN, (window.innerWidth - width) / 2) + 'px'\n });\n return;\n }\n var gap = this.opts && typeof this.opts.gap === 'number' ? this.opts.gap : DEFAULT_GAP;\n var preferredSide = this.opts && this.opts.side || 'right';\n\n // Try sides in preference order.\n var ordered = this._sideOrder(preferredSide);\n var chosen = null;\n var _iterator = _createForOfIteratorHelper(ordered),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var side = _step.value;\n var placed = this._tryPlace(side, anchorRect, width, popoverHeight, gap);\n if (placed) {\n chosen = placed;\n break;\n }\n }\n // Fallback — best-effort right side, clamped to viewport.\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n if (!chosen) chosen = this._tryPlace('right', anchorRect, width, popoverHeight, gap, true);\n Object.assign(this.domNode.style, {\n top: chosen.top + 'px',\n left: chosen.left + 'px'\n });\n this.domNode.classList.toggle('bjs-ovl-anchored-popover--right', chosen.side === 'right');\n this.domNode.classList.toggle('bjs-ovl-anchored-popover--left', chosen.side === 'left');\n this.domNode.classList.toggle('bjs-ovl-anchored-popover--top', chosen.side === 'top');\n this.domNode.classList.toggle('bjs-ovl-anchored-popover--bottom', chosen.side === 'bottom');\n }\n }, {\n key: \"_sideOrder\",\n value: function _sideOrder(preferred) {\n var all = ['right', 'left', 'bottom', 'top'];\n return [preferred].concat(_toConsumableArray(all.filter(function (s) {\n return s !== preferred;\n })));\n }\n }, {\n key: \"_resolveAnchorRect\",\n value: function _resolveAnchorRect() {\n var anchor = this.opts && this.opts.anchorTo;\n if (!anchor) {\n // Default — element's own DOM rect (in iframe coordinates ⇒\n // translate to viewport coords via the iframe's frameElement).\n var dom = this.element && this.element.domNode;\n if (!dom) return null;\n var r = dom.getBoundingClientRect();\n var ifr = dom.ownerDocument.defaultView.frameElement;\n var ir = ifr ? ifr.getBoundingClientRect() : {\n top: 0,\n left: 0\n };\n return {\n top: ir.top + r.top,\n left: ir.left + r.left,\n right: ir.left + r.right,\n bottom: ir.top + r.bottom,\n width: r.width,\n height: r.height\n };\n }\n if (typeof anchor === 'function') return anchor();\n if (anchor instanceof Element) return anchor.getBoundingClientRect();\n return anchor; // assume DOMRect-like\n }\n }, {\n key: \"_tryPlace\",\n value: function _tryPlace(side, anchorRect, width, height, gap, allowOverflow) {\n var vw = window.innerWidth;\n var vh = window.innerHeight;\n var top, left;\n if (side === 'right') {\n left = anchorRect.right + gap;\n if (!allowOverflow && left + width > vw - VIEWPORT_MARGIN) return null;\n top = anchorRect.top + anchorRect.height / 2 - height / 2;\n } else if (side === 'left') {\n left = anchorRect.left - gap - width;\n if (!allowOverflow && left < VIEWPORT_MARGIN) return null;\n top = anchorRect.top + anchorRect.height / 2 - height / 2;\n } else if (side === 'bottom') {\n top = anchorRect.bottom + gap;\n if (!allowOverflow && top + height > vh - VIEWPORT_MARGIN) return null;\n left = anchorRect.left + anchorRect.width / 2 - width / 2;\n } else {\n // top\n top = anchorRect.top - gap - height;\n if (!allowOverflow && top < VIEWPORT_MARGIN) return null;\n left = anchorRect.left + anchorRect.width / 2 - width / 2;\n }\n // Clamp into viewport.\n top = Math.max(VIEWPORT_MARGIN, Math.min(top, vh - height - VIEWPORT_MARGIN));\n left = Math.max(VIEWPORT_MARGIN, Math.min(left, vw - width - VIEWPORT_MARGIN));\n return {\n side: side,\n top: top,\n left: left\n };\n }\n }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AnchoredPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/AnchoredPopoverOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/BlockDragAnchorOverlay.js":
/*!*********************************************************!*\
!*** ./src/includes/overlays/BlockDragAnchorOverlay.js ***!
\*********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _NativeDragHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./NativeDragHandleOverlay.js */ \"./src/includes/overlays/NativeDragHandleOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * BlockDragAnchorOverlay — Phase 1.6\n *\n * Overlay replacement for the hand-rolled `BlockElement.addDragAnchor()`\n * anchor (legacy at BlockElement.js:339-401). Gated on the builder flag\n * `builder.useOverlayDragAnchor` — when OFF, `BlockElement.getOverlays()`\n * returns [] and the legacy anchor pipeline stays in charge.\n *\n * Trigger: 'hover' — mounts on UIManager.mouseover → block.mountOverlays,\n * unmounts on UIManager.mouseout flush timeout (preserved 50 ms debounce,\n * SA invariant I1).\n *\n * Extends `NativeDragHandleOverlay` (Phase 1.2) — NOT `DraggableHandleOverlay`\n * (SA invariant I2: pointer events and HTML5 DnD are mutually exclusive).\n * Inherits the Safari drag-ghost 3-layer workaround (I3):\n * 1. `dataTransfer.setData('text/plain', '')`\n * 2. `dataTransfer.effectAllowed = 'all'`\n * 3. Safari-only off-screen clone at `left: -10000px` for setDragImage\n *\n * `onDragStart` hands off to `uiManager.dragStart(block)` (same function the\n * legacy anchor's dragstart handler invoked at UIManager.js:729) — does NOT\n * fork the DnD pipeline. Post-dragstart the overlay destroys itself on a\n * 100 ms timer to mirror legacy `UIManager.dragStart → hideDragAnchor` at\n * line 757 (anchor visually disappears during drag; reappears on next hover).\n *\n * Visual parity with legacy `.drag-anchor` via `.bjs-ovl-block-drag` CSS —\n * same 20×20 grab affordance, `front_hand` material icon inside a rounded\n * pill. Legacy DOM markup preserved so host-app CSS targeting `.drag-label`\n * keeps working even in overlay mode.\n *\n * See docs/core/OVERLAY.md §7.4 + docs/archived/OVERLAY_PLAN.md §3.7.\n */\n\nvar HIDE_AFTER_DRAGSTART_MS = 100;\nvar BlockDragAnchorOverlay = /*#__PURE__*/function (_NativeDragHandleOver) {\n function BlockDragAnchorOverlay() {\n _classCallCheck(this, BlockDragAnchorOverlay);\n return _callSuper(this, BlockDragAnchorOverlay, arguments);\n }\n _inherits(BlockDragAnchorOverlay, _NativeDragHandleOver);\n return _createClass(BlockDragAnchorOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'hover';\n }\n }, {\n key: \"_buildHandle\",\n value: function _buildHandle() {\n // Match legacy markup at BlockElement.js:347-349 so any CSS/tests\n // targeting `.drag-label` keep working. The inner <span> is the\n // draggable=\"true\" grabber (SA I2 — the element carrying the\n // draggable attr gets the dragstart event).\n this.domNode.classList.add('bjs-ovl-block-drag');\n this.domNode.innerHTML = \"\\n <div class=\\\"drag-label\\\"><span class=\\\"material-symbols-rounded fs-4 border bg-light p-1 rounded-circle\\\" draggable=\\\"true\\\">front_hand</span></div>\\n \";\n }\n }, {\n key: \"position\",\n value: function position() {\n var _this = this;\n // Match legacy positioning at BlockElement.js:356-384 — right-middle\n // of the block, poking out by 2 px (domWidth - 18 with anchor width 20).\n // matchingDomNode wires observers so this re-runs on every reflow.\n this.element.matchingDomNode(this.domNode, 5, function () {\n if (!_this.domNode) return;\n if (!_this.element.domNode) return;\n var ownerView = _this.element.domNode.ownerDocument && _this.element.domNode.ownerDocument.defaultView;\n var iframe = ownerView && ownerView.frameElement;\n if (!iframe) return;\n var domRect = _this.element.domNode.getBoundingClientRect();\n var iframeRect = iframe.getBoundingClientRect();\n var absoluteTop = iframeRect.top + domRect.top;\n var absoluteLeft = iframeRect.left + domRect.left;\n Object.assign(_this.domNode.style, {\n position: 'fixed',\n top: \"\".concat(absoluteTop + domRect.height / 2 - 10, \"px\"),\n left: \"\".concat(absoluteLeft + domRect.width - 18, \"px\"),\n width: '20px',\n height: '20px'\n });\n });\n }\n }, {\n key: \"onDragStart\",\n value: function onDragStart(/* e */\n ) {\n var _this2 = this;\n // Hand off to the existing UIManager.dragStart pipeline — does NOT\n // fork DnD. The `NativeDragHandleOverlay` parent has already applied\n // setData + effectAllowed + Safari 3-layer clone workaround before\n // this hook fires (see src/includes/overlays/NativeDragHandleOverlay.js).\n var host = this.host;\n if (host && host.uiManager && typeof host.uiManager.dragStart === 'function') {\n try {\n host.uiManager.dragStart(this.element);\n } catch (err) {\n /* eslint-disable-next-line no-console */\n console.error('[overlay] BlockDragAnchorOverlay onDragStart → uiManager.dragStart threw:', err);\n }\n }\n\n // Hide the anchor during drag (matches legacy\n // UIManager.dragStart → hideDragAnchor at UIManager.js:757 with the\n // identical 100 ms delay). Destroying the overlay here is safe —\n // the Safari drag ghost has already been captured by setDragImage\n // in the parent's dragstart handler (microtask-0 clone removal).\n // The overlay re-mounts on the next UIManager.mouseover → hover\n // trigger cycle after dragend.\n setTimeout(function () {\n try {\n _this2.destroy();\n } catch (_) {/* already destroyed */}\n }, HIDE_AFTER_DRAGSTART_MS);\n }\n }]);\n}(_NativeDragHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BlockDragAnchorOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/BlockDragAnchorOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ButtonActionsOverlay.js":
/*!*******************************************************!*\
!*** ./src/includes/overlays/ButtonActionsOverlay.js ***!
\*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./FloatingActionBarOverlay.js */ \"./src/includes/overlays/FloatingActionBarOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ButtonActionsOverlay — 3-pill floating toolbar (2026-04-19 refactor).\n *\n * Link: opens LinkPopoverOverlay anchored next to the Link pill\n * (mode 'link-popover'). Compact in-place URL editor.\n * Settings: opens ButtonSettingsPopoverOverlay anchored next to the\n * gear pill (mode 'settings-popover'). Full modifier stack —\n * size / radius / shadow / hover / icon / position / width —\n * in a single popover so the user can tune without leaving\n * the canvas.\n * Style: opens ButtonPresetPickerOverlay anchored next to the\n * palette pill (mode 'style-picker'). 9-tab preset picker\n * with ~210 styles. Click-to-apply (no modal mask).\n *\n * The older \"Edit text\" pill was dropped — the <a>'s `[inline-edit=\"text\"]`\n * span is contenteditable on focus already, so a dedicated pill was pure\n * redundancy. Click the text → caret appears → type.\n *\n * Icons render via the shared inline-SVG registry so pills work even when\n * the theme iframe doesn't load Material Symbols.\n *\n * `e.stopPropagation()` on each click prevents the element's select/deselect\n * flow from firing from a button click (Lesson 23 Rule 5 + 11 + 12).\n *\n * Visual parity with ImageActionsOverlay — same FloatingActionBarOverlay\n * primitive, same `.bjs-ovl-action-bar` + `.bjs-ovl-pill` markup.\n *\n * See docs/core/OVERLAY.md §7.5 + §7.7 + docs/BUTTON_UPGRADE_PLAN.md.\n */\n\n\nvar ButtonActionsOverlay = /*#__PURE__*/function (_FloatingActionBarOve) {\n function ButtonActionsOverlay(element) {\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, ButtonActionsOverlay);\n return _callSuper(this, ButtonActionsOverlay, [element, Object.assign({\n anchor: 'top-right'\n }, opts)]);\n }\n _inherits(ButtonActionsOverlay, _FloatingActionBarOve);\n return _createClass(ButtonActionsOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'select';\n }\n }, {\n key: \"getButtons\",\n value: function getButtons() {\n var _this = this;\n return [{\n icon: 'link',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.link', 'Link'),\n onClick: function onClick(e) {\n return _this._enter(e, 'link-popover');\n }\n }, {\n icon: 'settings',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.settings', 'Settings'),\n onClick: function onClick(e) {\n return _this._enter(e, 'settings-popover');\n }\n }, {\n icon: 'palette',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.style', 'Style'),\n onClick: function onClick(e) {\n return _this._enter(e, 'style-picker');\n }\n }];\n }\n\n /**\n * Generic pill-click handler. Each pill stashes its own click rect on\n * `element._lastActionAnchorRect` so the downstream AnchoredPopover\n * anchors to whichever pill was clicked, then flips the element into\n * the matching edit mode (getOverlays() filters on `getEditMode()` so\n * the right popover mounts).\n */\n }, {\n key: \"_enter\",\n value: function _enter(e, mode) {\n if (!this.element) return;\n if (typeof this.element.enterEditMode !== 'function') return;\n if (e && e.currentTarget && typeof e.currentTarget.getBoundingClientRect === 'function') {\n this.element._lastActionAnchorRect = e.currentTarget.getBoundingClientRect();\n } else {\n this.element._lastActionAnchorRect = null;\n }\n this.element.enterEditMode(mode);\n }\n }]);\n}(_FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ButtonActionsOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ButtonActionsOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ButtonPresetPickerOverlay.js":
/*!************************************************************!*\
!*** ./src/includes/overlays/ButtonPresetPickerOverlay.js ***!
\************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\n/* harmony import */ var _buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../buttonPresets.js */ \"./src/includes/buttonPresets.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ButtonPresetPickerOverlay — anchored popover for picking a button\n * style preset. Mounts in 'style-picker' edit mode (set by either the\n * sidebar StylePickerControl Change button OR the action-bar's 3rd\n * palette pill — both stash `element._lastActionAnchorRect`).\n *\n * Layout\n * ──────\n * ┌──────────────────────────────────────────┐\n * │ Pick a button style [×] │\n * ├──────────────────────────────────────────┤\n * │ Solid · Outline · Tonal · Ghost · … │ ← tabs (scrollable)\n * ├──────────────────────────────────────────┤\n * │ ┌──────┐ ┌──────┐ │\n * │ │ ▣ A │ │ ▣ B │ ← 2-col grid │\n * │ └──────┘ └──────┘ │\n * │ ┌──────┐ ┌──────┐ │\n * │ │ ▣ C │ │ ▣ D │ │\n * │ └──────┘ └──────┘ │\n * ├──────────────────────────────────────────┤\n * │ Esc to cancel · Click outside to close │\n * └──────────────────────────────────────────┘\n *\n * Click a preset card → element.applyPreset(presetId) → popover stays\n * open so the user can compare styles by clicking through the grid.\n * Esc / outside-click / × button closes.\n *\n * Snapshot + Cancel\n * ─────────────────\n * On mount we snapshot { preset_id, size_key } so the user can\n * experiment then bail out via Esc; close-via-Esc reverts. Close-via-\n * outside-click commits (treats the click as a deliberate exit).\n *\n * Same primitive as LinkPopoverOverlay / ImageEffectPopoverOverlay etc.\n * — extends AnchoredPopoverOverlay (smart-flip placement, viewport\n * margin clamp, shared `.bjs-ovl-anchored-popover` chrome).\n */\n\n\n\n\n\nvar POPOVER_WIDTH = 420;\nvar POPOVER_MAX_HEIGHT = 520;\nvar ButtonPresetPickerOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n function ButtonPresetPickerOverlay(element) {\n var _this;\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, ButtonPresetPickerOverlay);\n var anchorTo = function anchorTo() {\n return element._lastActionAnchorRect || null;\n };\n _this = _callSuper(this, ButtonPresetPickerOverlay, [element, Object.assign({\n anchorTo: anchorTo,\n side: 'right',\n width: POPOVER_WIDTH,\n maxHeight: POPOVER_MAX_HEIGHT\n }, opts)]);\n _this._activeCategory = null; // resolved on render()\n _this._snapshot = null;\n _this._committedOnExit = false;\n return _this;\n }\n _inherits(ButtonPresetPickerOverlay, _AnchoredPopoverOverl);\n return _createClass(ButtonPresetPickerOverlay, [{\n key: \"getEditMode\",\n value: function getEditMode() {\n return 'style-picker';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(ButtonPresetPickerOverlay, \"render\", this, 3)([]);\n this.domNode.classList.add('bjs-ovl-button-picker');\n this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-button-picker-title');\n\n // Snapshot for Cancel\n this._snapshot = {\n preset_id: this.element.preset_id || null,\n size_key: this.element.size_key || 'md',\n shadow_key: this.element.shadow_key || 'none',\n hover_effect: this.element.hover_effect || 'none',\n icon: this.element.icon || null,\n icon_position: this.element.icon_position || 'none',\n formats: this.element.formatter ? Object.assign({}, this.element.formatter.formats) : null\n };\n this._committedOnExit = false;\n\n // Default tab: category of current preset, else 'solid'\n var cur = (0,_buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__.findPreset)(this.element.preset_id);\n this._activeCategory = cur && cur.category || 'solid';\n this.domNode.appendChild(this._renderHeader());\n this.domNode.appendChild(this._renderTabs());\n this.domNode.appendChild(this._renderBody());\n this.domNode.appendChild(this._renderFooter());\n }\n\n /* ─── Subclass overrides for AnchoredPopoverOverlay lifecycle ─── */\n }, {\n key: \"afterMount\",\n value: function afterMount() {\n // Focus the active tab so keyboard users land on something useful\n if (!this.domNode) return;\n var activeTab = this.domNode.querySelector('.bjs-ovl-button-picker-tab.is-active');\n if (activeTab) {\n try {\n activeTab.focus();\n } catch (_) {/* no-op */}\n }\n }\n\n /* ─── Header / tabs / body / footer ─── */\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var _this2 = this;\n var header = document.createElement('div');\n header.className = 'bjs-ovl-button-picker-header';\n var title = document.createElement('h3');\n title.className = 'bjs-ovl-button-picker-title';\n title.id = 'bjs-ovl-button-picker-title';\n title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.title', 'Pick a button style');\n var close = document.createElement('button');\n close.type = 'button';\n close.className = 'bjs-ovl-button-picker-close';\n close.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.close', 'Close'));\n close.innerHTML = '<span class=\"bjs-ovl-button-picker-close-icon\" aria-hidden=\"true\">' + _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render('close', {\n size: 18,\n color: 'currentColor'\n }) + '</span>';\n close.addEventListener('click', function (e) {\n e.preventDefault();\n _this2._commitAndClose();\n });\n header.appendChild(title);\n header.appendChild(close);\n return header;\n }\n }, {\n key: \"_renderTabs\",\n value: function _renderTabs() {\n var _this3 = this;\n var wrap = document.createElement('div');\n wrap.className = 'bjs-ovl-button-picker-tabs';\n wrap.setAttribute('role', 'tablist');\n var sorted = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__.CATEGORIES.slice().sort(function (a, b) {\n return a.order - b.order;\n });\n sorted.forEach(function (cat) {\n var isActive = cat.id === _this3._activeCategory;\n var tab = document.createElement('button');\n tab.type = 'button';\n tab.className = 'bjs-ovl-button-picker-tab' + (isActive ? ' is-active' : '');\n tab.setAttribute('role', 'tab');\n tab.setAttribute('aria-selected', String(isActive));\n tab.dataset.cat = cat.id;\n tab.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.cat_' + cat.id, cat.label);\n tab.addEventListener('click', function (e) {\n e.preventDefault();\n _this3._switchCategory(cat.id);\n });\n wrap.appendChild(tab);\n });\n return wrap;\n }\n }, {\n key: \"_renderBody\",\n value: function _renderBody() {\n var body = document.createElement('div');\n body.className = 'bjs-ovl-button-picker-body';\n body.appendChild(this._renderGrid(this._activeCategory));\n return body;\n }\n }, {\n key: \"_renderGrid\",\n value: function _renderGrid(catId) {\n var _this4 = this;\n var grid = document.createElement('div');\n grid.className = 'bjs-ovl-button-picker-grid';\n grid.dataset.cat = catId;\n var presets = (0,_buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__.presetsByCategory)(catId);\n var currentId = this.element.preset_id;\n presets.forEach(function (p) {\n var cell = document.createElement('button');\n cell.type = 'button';\n cell.className = 'bjs-ovl-button-picker-cell' + (p.id === currentId ? ' is-current' : '');\n cell.dataset.presetId = p.id;\n cell.setAttribute('aria-label', p.label);\n\n // Inline-style mini button mirrors the preset exactly\n cell.appendChild(_this4._renderPresetThumb(p));\n\n // Label below thumb\n var label = document.createElement('span');\n label.className = 'bjs-ovl-button-picker-cell-label';\n label.textContent = p.label;\n cell.appendChild(label);\n\n // Page-only / VML warn badge\n if (p.flags) {\n if (p.flags.pageOnly) {\n var b = document.createElement('span');\n b.className = 'bjs-ovl-button-picker-cell-badge bjs-ovl-button-picker-cell-badge--page';\n b.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.page_only_short', 'Page');\n cell.appendChild(b);\n } else if (p.flags.requiresVML) {\n var _b = document.createElement('span');\n _b.className = 'bjs-ovl-button-picker-cell-badge bjs-ovl-button-picker-cell-badge--warn';\n _b.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.vml_short', 'VML');\n cell.appendChild(_b);\n }\n }\n\n // Tick on current\n if (p.id === currentId) {\n var tick = document.createElement('span');\n tick.className = 'bjs-ovl-button-picker-cell-tick';\n tick.setAttribute('aria-hidden', 'true');\n tick.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render('check_circle', {\n size: 18,\n color: 'currentColor'\n });\n cell.appendChild(tick);\n }\n cell.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this4._applyPreset(p.id);\n });\n grid.appendChild(cell);\n });\n if (presets.length === 0) {\n var empty = document.createElement('div');\n empty.className = 'bjs-ovl-button-picker-empty';\n empty.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.empty', 'No presets in this category yet.');\n grid.appendChild(empty);\n }\n return grid;\n }\n }, {\n key: \"_renderPresetThumb\",\n value: function _renderPresetThumb(preset) {\n var f = preset.formats || {};\n var text = this.element && this.element.text || _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.sample_text', 'Action');\n var node = document.createElement('a');\n node.className = 'bjs-ovl-button-picker-spec';\n var styleParts = [f.background_image ? \"background:\".concat(f.background_image) : \"background:\".concat(f.background_color || '#2563eb'), f.background_color ? \"background-color:\".concat(f.background_color) : '', \"color:\".concat(f.text_color || '#fff'), f.border_top_color ? \"border:\".concat(f.border_top_width || '1px', \" \").concat(f.border_top_style || 'solid', \" \").concat(f.border_top_color) : 'border:0', \"border-radius:\".concat(f.border_radius || '6px'), f.box_shadow ? \"box-shadow:\".concat(f.box_shadow) : '', f.font_family ? \"font-family:\".concat(f.font_family) : '', f.font_weight ? \"font-weight:\".concat(f.font_weight) : 'font-weight:500', 'font-size:13px', 'padding:6px 14px', 'text-decoration:none', 'display:inline-flex', 'align-items:center', 'line-height:1.4'].filter(Boolean).join(';');\n node.setAttribute('style', styleParts);\n\n // 2026-04-19 — icon spacing. Use explicit side margins instead of a\n // flex `gap` so left-icon-only / right-icon-only / icon-only\n // variants each get the right amount of breathing room. `gap`\n // applies to every child pair and is too tight at 6px once the\n // icon sits next to a word (especially when the first char is\n // narrow like `&` or `|`).\n var iconSpan = function iconSpan(px, cls) {\n var s = document.createElement('span');\n s.className = 'bjs-ovl-button-picker-cell-icon ' + cls;\n s.setAttribute('aria-hidden', 'true');\n s.style.display = 'inline-flex';\n s.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render(preset.icon, {\n size: px,\n color: 'currentColor'\n });\n if (cls === 'is-left') s.style.marginRight = '8px';\n if (cls === 'is-right') s.style.marginLeft = '8px';\n return s;\n };\n if (preset.icon && preset.iconPosition === 'left') {\n node.appendChild(iconSpan(15, 'is-left'));\n }\n if (preset.iconPosition !== 'only') {\n var t = document.createElement('span');\n // innerHTML (NOT textContent) so HTML entities like and\n // user-authored inline tags match the rendered <a> in the\n // canvas (where EJS <%- text %> is unescaped). Consistent\n // behavior prevents \"looks different in picker vs canvas\"\n // surprises — esp. when users insert a leading for\n // optical centering.\n t.innerHTML = text;\n node.appendChild(t);\n }\n if (preset.icon && preset.iconPosition === 'right') {\n node.appendChild(iconSpan(15, 'is-right'));\n }\n if (preset.icon && preset.iconPosition === 'only') {\n node.appendChild(iconSpan(17, 'is-only'));\n }\n return node;\n }\n }, {\n key: \"_renderFooter\",\n value: function _renderFooter() {\n var _this5 = this;\n var footer = document.createElement('div');\n footer.className = 'bjs-ovl-button-picker-footer';\n var hint = document.createElement('span');\n hint.className = 'bjs-ovl-button-picker-footer-hint';\n hint.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.footer_hint', 'Esc to cancel · Click outside to apply');\n footer.appendChild(hint);\n var reset = document.createElement('button');\n reset.type = 'button';\n reset.className = 'bjs-ovl-button-picker-reset';\n reset.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.reset', 'Reset');\n reset.addEventListener('click', function (e) {\n e.preventDefault();\n _this5._cancel();\n });\n footer.appendChild(reset);\n return footer;\n }\n\n /* ─── Actions ─── */\n }, {\n key: \"_switchCategory\",\n value: function _switchCategory(catId) {\n if (catId === this._activeCategory) return;\n this._activeCategory = catId;\n // Refresh tabs active state\n this.domNode.querySelectorAll('.bjs-ovl-button-picker-tab').forEach(function (t) {\n var isActive = t.dataset.cat === catId;\n t.classList.toggle('is-active', isActive);\n t.setAttribute('aria-selected', String(isActive));\n });\n // Replace grid\n var body = this.domNode.querySelector('.bjs-ovl-button-picker-body');\n if (body) {\n body.innerHTML = '';\n body.appendChild(this._renderGrid(catId));\n }\n }\n }, {\n key: \"_applyPreset\",\n value: function _applyPreset(presetId) {\n if (!this.element || typeof this.element.applyPreset !== 'function') return;\n this.element.applyPreset(presetId);\n // Update grid current marker\n this.domNode.querySelectorAll('.bjs-ovl-button-picker-cell').forEach(function (cell) {\n var tick = cell.querySelector('.bjs-ovl-button-picker-cell-tick');\n if (cell.dataset.presetId === presetId) {\n cell.classList.add('is-current');\n if (!tick) {\n var t = document.createElement('span');\n t.className = 'bjs-ovl-button-picker-cell-tick';\n t.setAttribute('aria-hidden', 'true');\n t.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render('check_circle', {\n size: 18,\n color: 'currentColor'\n });\n cell.appendChild(t);\n }\n } else {\n cell.classList.remove('is-current');\n if (tick) tick.remove();\n }\n });\n }\n }, {\n key: \"_commitAndClose\",\n value: function _commitAndClose() {\n // Close button = explicit commit (keep current state)\n this._committedOnExit = true;\n if (typeof this.element.exitEditMode === 'function') {\n this.element.exitEditMode();\n }\n }\n }, {\n key: \"_cancel\",\n value: function _cancel() {\n // Reset button OR Esc (handled by AnchoredPopoverOverlay) — restore snapshot\n if (!this.element || !this._snapshot) return;\n var s = this._snapshot;\n this.element.preset_id = s.preset_id;\n this.element.size_key = s.size_key;\n this.element.shadow_key = s.shadow_key;\n this.element.hover_effect = s.hover_effect;\n this.element.icon = s.icon;\n this.element.icon_position = s.icon_position;\n if (s.formats && this.element.formatter) {\n this.element.formatter.formats = Object.assign({}, s.formats);\n }\n if (typeof this.element.applyFormatStyles === 'function') {\n this.element.applyFormatStyles();\n }\n if (typeof this.element.applyButtonExtras === 'function') {\n this.element.applyButtonExtras();\n }\n if (typeof this.element.notifySyncListeners === 'function') {\n this.element.notifySyncListeners();\n }\n if (typeof this.element.exitEditMode === 'function') {\n this.element.exitEditMode();\n }\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n _superPropGet(ButtonPresetPickerOverlay, \"beforeDestroy\", this, 3)([]);\n this._snapshot = null;\n }\n }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ButtonPresetPickerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ButtonPresetPickerOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ButtonSettingsPopoverOverlay.js":
/*!***************************************************************!*\
!*** ./src/includes/overlays/ButtonSettingsPopoverOverlay.js ***!
\***************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\n/* harmony import */ var _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../SegmentedTextControl.js */ \"./src/includes/SegmentedTextControl.js\");\n/* harmony import */ var _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../IconPickerControl.js */ \"./src/includes/IconPickerControl.js\");\n/* harmony import */ var _buttonPresets_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../buttonPresets.js */ \"./src/includes/buttonPresets.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ButtonSettingsPopoverOverlay — anchored popover hosting the full\n * Button modifier stack (size · radius · shadow · hover · icon · position\n * · width) next to the canvas button. Opens via the gear \"Settings\" pill\n * in ButtonActionsOverlay. Sibling of ButtonPresetPickerOverlay — same\n * AnchoredPopover primitive, same `_lastActionAnchorRect` anchor, but\n * shows axis controls instead of the preset grid.\n *\n * Why this exists\n * ───────────────\n * Sidebar is excellent for deliberate tuning but requires the user to\n * leave the canvas to reach it, and the canvas button may be far from\n * the sidebar when the row is wide. This popover keeps the full axis\n * surface one click away from the selected button. Preset identity\n * stays with the Style picker — they're orthogonal.\n *\n * Sync contract (SA I13 — dual-view)\n * ──────────────────────────────────\n * Every embedded SegmentedTextControl and the IconPickerControl\n * subscribes to element.addSyncListener so mutations on ANY surface\n * (sidebar, preset picker, this popover) flow into each other's\n * visual state without tight coupling between the surfaces.\n *\n * [popover chip click]\n * → SegmentedTextControl._select → element.apply*()\n * → formatter mutation + applyButtonExtras\n * → notifySyncListeners()\n * → [sidebar chip syncValue] (no callback re-fire)\n * → [popover chip syncValue] (already set — no-op)\n *\n * Guard — syncValue on SegmentedTextControl is silent (no callback\n * fire) so the propagation can't loop. IconPickerControl manual patch\n * similarly silent.\n *\n * Snapshot + Cancel\n * ─────────────────\n * On mount we snapshot { size_key, shadow_key, hover_effect, icon,\n * icon_position, width_key, radius_key } + the formatter. Esc /\n * Reset restores snapshot + exits edit mode.\n *\n * Icons render via the shared inline-SVG registry — popover chrome\n * (close X) and optional icon preview use SVG, no Material Symbols\n * dependency inside the popover surface.\n */\n\n\n\n\n\n\n\nvar POPOVER_WIDTH = 380;\nvar POPOVER_MAX_HEIGHT = 560;\nvar ButtonSettingsPopoverOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n function ButtonSettingsPopoverOverlay(element) {\n var _this;\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, ButtonSettingsPopoverOverlay);\n var anchorTo = function anchorTo() {\n return element._lastActionAnchorRect || null;\n };\n _this = _callSuper(this, ButtonSettingsPopoverOverlay, [element, Object.assign({\n anchorTo: anchorTo,\n side: 'right',\n width: POPOVER_WIDTH,\n maxHeight: POPOVER_MAX_HEIGHT\n }, opts)]);\n _this._snapshot = null;\n _this._controls = []; // disposable refs\n return _this;\n }\n _inherits(ButtonSettingsPopoverOverlay, _AnchoredPopoverOverl);\n return _createClass(ButtonSettingsPopoverOverlay, [{\n key: \"getEditMode\",\n value: function getEditMode() {\n return 'settings-popover';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(ButtonSettingsPopoverOverlay, \"render\", this, 3)([]);\n this.domNode.classList.add('bjs-ovl-button-settings');\n this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-button-settings-title');\n this._snapshot = this._captureSnapshot();\n this.domNode.appendChild(this._renderHeader());\n this.domNode.appendChild(this._renderBody());\n this.domNode.appendChild(this._renderFooter());\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n _superPropGet(ButtonSettingsPopoverOverlay, \"beforeDestroy\", this, 3)([]);\n // Release each embedded control's sync subscription so re-opening\n // the popover doesn't leak listeners.\n (this._controls || []).forEach(function (c) {\n try {\n c && typeof c.destroy === 'function' && c.destroy();\n } catch (_) {/* no-op */}\n });\n this._controls = [];\n this._snapshot = null;\n }\n\n /* ─── Snapshot helpers ─── */\n }, {\n key: \"_captureSnapshot\",\n value: function _captureSnapshot() {\n return {\n size_key: this.element.size_key || 'md',\n shadow_key: this.element.shadow_key || 'none',\n hover_effect: this.element.hover_effect || 'none',\n icon: this.element.icon || null,\n icon_position: this.element.icon_position || 'none',\n width_key: this.element._currentWidthKey ? this.element._currentWidthKey() : 'auto',\n radius_key: this.element._currentRadiusKey ? this.element._currentRadiusKey() || 'md' : 'md',\n formats: this.element.formatter ? Object.assign({}, this.element.formatter.formats) : null\n };\n }\n }, {\n key: \"_restoreSnapshot\",\n value: function _restoreSnapshot() {\n var s = this._snapshot;\n if (!s || !this.element) return;\n this.element.size_key = s.size_key;\n this.element.shadow_key = s.shadow_key;\n this.element.hover_effect = s.hover_effect;\n this.element.icon = s.icon;\n this.element.icon_position = s.icon_position;\n if (s.formats && this.element.formatter) {\n this.element.formatter.formats = Object.assign({}, s.formats);\n }\n if (typeof this.element.applyFormatStyles === 'function') this.element.applyFormatStyles();\n if (typeof this.element.applyButtonExtras === 'function') this.element.applyButtonExtras();\n if (typeof this.element.notifySyncListeners === 'function') this.element.notifySyncListeners();\n }\n\n /* ─── Chrome ─── */\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var _this2 = this;\n var header = document.createElement('div');\n header.className = 'bjs-ovl-button-settings-header';\n var title = document.createElement('h3');\n title.className = 'bjs-ovl-button-settings-title';\n title.id = 'bjs-ovl-button-settings-title';\n title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.settings.title', 'Button settings');\n var close = document.createElement('button');\n close.type = 'button';\n close.className = 'bjs-ovl-button-settings-close';\n close.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.close', 'Close'));\n close.innerHTML = '<span aria-hidden=\"true\">' + _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render('close', {\n size: 18,\n color: 'currentColor'\n }) + '</span>';\n close.addEventListener('click', function (e) {\n e.preventDefault();\n // Close button = explicit commit (accept current state)\n if (typeof _this2.element.exitEditMode === 'function') _this2.element.exitEditMode();\n });\n header.appendChild(title);\n header.appendChild(close);\n return header;\n }\n }, {\n key: \"_renderFooter\",\n value: function _renderFooter() {\n var _this3 = this;\n var footer = document.createElement('div');\n footer.className = 'bjs-ovl-button-settings-footer';\n var hint = document.createElement('span');\n hint.className = 'bjs-ovl-button-settings-hint';\n hint.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.settings.hint', 'Esc to cancel · Click outside to apply');\n footer.appendChild(hint);\n var reset = document.createElement('button');\n reset.type = 'button';\n reset.className = 'bjs-ovl-button-settings-reset';\n reset.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.settings.reset', 'Reset');\n reset.addEventListener('click', function (e) {\n e.preventDefault();\n _this3._restoreSnapshot();\n if (typeof _this3.element.exitEditMode === 'function') _this3.element.exitEditMode();\n });\n footer.appendChild(reset);\n return footer;\n }\n\n /* ─── Body ─── */\n }, {\n key: \"_renderBody\",\n value: function _renderBody() {\n var _this4 = this;\n var body = document.createElement('div');\n body.className = 'bjs-ovl-button-settings-body';\n\n // ── Size + Radius ──\n body.appendChild(this._renderSectionLabel(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.shape', 'Shape & size'), _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.shape_desc', 'Baseline size and corner radius.')));\n body.appendChild(this._renderSegmented('size', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.size.label', 'Size'), this.element.size_key || 'md', function (v) {\n return _this4.element.applySize(v);\n }, _buttonPresets_js__WEBPACK_IMPORTED_MODULE_5__.SIZE_KEYS.map(function (k) {\n return {\n value: k,\n label: k.toUpperCase()\n };\n }), function () {\n return _this4.element.size_key || 'md';\n }));\n body.appendChild(this._renderSegmented('radius', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.label', 'Radius'), this.element._currentRadiusKey() || 'md', function (v) {\n return _this4.element.applyRadiusKey(v);\n }, [{\n value: 'sharp',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.sharp', 'Sharp')\n }, {\n value: 'sm',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.sm', 'SM')\n }, {\n value: 'md',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.md', 'MD')\n }, {\n value: 'lg',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.lg', 'LG')\n }, {\n value: 'pill',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.pill', 'Pill')\n }], function () {\n return _this4.element._currentRadiusKey() || 'md';\n }));\n\n // ── Effects ──\n body.appendChild(this._renderSectionLabel(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.effects', 'Effects'), _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.effects_desc', 'Depth and micro-interactions. Page mode only.')));\n body.appendChild(this._renderSegmented('shadow', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.shadow.label', 'Shadow'), this.element.shadow_key || 'none', function (v) {\n return _this4.element.applyShadow(v);\n }, _buttonPresets_js__WEBPACK_IMPORTED_MODULE_5__.SHADOW_KEYS.map(function (k) {\n return {\n value: k,\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.shadow.' + k, k === 'inner' ? 'Inner' : k.toUpperCase())\n };\n }), function () {\n return _this4.element.shadow_key || 'none';\n }));\n body.appendChild(this._renderSegmented('hover', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.hover.label', 'Hover effect'), this.element.hover_effect || 'none', function (v) {\n return _this4.element.applyHoverEffect(v);\n }, _buttonPresets_js__WEBPACK_IMPORTED_MODULE_5__.HOVER_EFFECT_KEYS.map(function (k) {\n return {\n value: k,\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.hover.' + k, k.charAt(0).toUpperCase() + k.slice(1))\n };\n }), function () {\n return _this4.element.hover_effect || 'none';\n }));\n\n // ── Icon ──\n body.appendChild(this._renderSectionLabel(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.icon', 'Icon'), _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.icon_desc', 'Optional pictogram beside, before, or instead of the label.')));\n body.appendChild(this._renderIconPicker());\n body.appendChild(this._renderSegmented('iconPos', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon_pos.label', 'Position'), this.element.icon_position || 'none', function (v) {\n return _this4.element.applyIconPosition(v);\n }, [{\n value: 'left',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon_pos.left', 'Left')\n }, {\n value: 'right',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon_pos.right', 'Right')\n }, {\n value: 'only',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon_pos.only', 'Only')\n }, {\n value: 'none',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon_pos.none', 'None')\n }], function () {\n return _this4.element.icon_position || 'none';\n }));\n\n // ── Layout ──\n body.appendChild(this._renderSectionLabel(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.layout', 'Layout'), _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.layout_desc', 'Width within the block row.')));\n body.appendChild(this._renderSegmented('width', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.width.label', 'Width'), this.element._currentWidthKey(), function (v) {\n return _this4.element.applyWidth(v);\n }, [{\n value: 'auto',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.width.auto', 'Auto')\n }, {\n value: 'half',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.width.half', '50%')\n }, {\n value: 'full',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.width.full', 'Full')\n }], function () {\n return _this4.element._currentWidthKey();\n }));\n return body;\n }\n }, {\n key: \"_renderSectionLabel\",\n value: function _renderSectionLabel(label, desc) {\n var wrap = document.createElement('div');\n wrap.className = 'bjs-ovl-button-settings-section';\n var h = document.createElement('div');\n h.className = 'bjs-ovl-button-settings-section-label';\n h.textContent = label;\n wrap.appendChild(h);\n if (desc) {\n var d = document.createElement('div');\n d.className = 'bjs-ovl-button-settings-section-desc';\n d.textContent = desc;\n wrap.appendChild(d);\n }\n return wrap;\n }\n }, {\n key: \"_renderSegmented\",\n value: function _renderSegmented(key, label, value, onChange, options, readValue) {\n var ctl = new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](label, value, onChange, options, {\n element: this.element,\n readValue: readValue\n });\n this._controls.push(ctl);\n return ctl.domNode;\n }\n }, {\n key: \"_renderIconPicker\",\n value: function _renderIconPicker() {\n var _this5 = this;\n var picker = new _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon.label', 'Icon'), this.element.icon || '', {\n setValue: function setValue(name) {\n return _this5.element.applyIcon(name || null, _this5.element.icon_position && _this5.element.icon_position !== 'none' ? _this5.element.icon_position : 'left');\n }\n });\n\n // Silent sync — mirror element.icon into the picker's visual state\n // without re-firing the callback. Mirrors ButtonElement._buildIconPicker\n // so both sidebar + popover pickers stay aligned.\n var dispose = this.element.addSyncListener('ButtonSettingsIconPicker:' + Math.random().toString(36).slice(2, 7), function () {\n var next = _this5.element.icon || '';\n if (picker.value !== next) {\n picker.value = next;\n picker.isCustomOpen = picker._detectCustom(next);\n if (typeof picker._refreshTrigger === 'function') picker._refreshTrigger();\n }\n });\n var prevDestroy = typeof picker.destroy === 'function' ? picker.destroy.bind(picker) : null;\n picker.destroy = function () {\n try {\n dispose && dispose();\n } catch (_) {/* no-op */}\n if (prevDestroy) {\n try {\n prevDestroy();\n } catch (_) {/* no-op */}\n }\n };\n this._controls.push(picker);\n return picker.domNode;\n }\n }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ButtonSettingsPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ButtonSettingsPopoverOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/DraggableHandleOverlay.js":
/*!*********************************************************!*\
!*** ./src/includes/overlays/DraggableHandleOverlay.js ***!
\*********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\n/* harmony import */ var _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../PointerCaptureRegistry.js */ \"./src/includes/PointerCaptureRegistry.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * DraggableHandleOverlay — pointer-driven drag handle primitive.\n *\n * Use for NEW gestures with NO HTML5 DnD involvement:\n * - Grid column separator drag\n * - Image crop handles\n * - Resize corners\n *\n * DO NOT use for HTML5 DnD participants (Block drag anchor). Pointer events\n * and HTML5 DnD are mutually exclusive on the same node — once `dragstart`\n * fires, browser suppresses pointermove/pointerup. See §5.1b of OVERLAY.md +\n * SA invariant I2. `render()` asserts the target is NOT draggable=\"true\".\n *\n * Subclasses override:\n * - onDragStart(e) — pointerdown fired, capture acquired\n * - onDrag(dx, dy, e)— pointermove with delta from start (px)\n * - onDragEnd(e) — pointerup/pointercancel\n *\n * Subclasses may also override render() for custom DOM — but MUST call\n * super.render() to wire pointer handlers + run the draggable=true assert.\n */\n\n\nvar DraggableHandleOverlay = /*#__PURE__*/function (_BaseOverlay) {\n function DraggableHandleOverlay() {\n _classCallCheck(this, DraggableHandleOverlay);\n return _callSuper(this, DraggableHandleOverlay, arguments);\n }\n _inherits(DraggableHandleOverlay, _BaseOverlay);\n return _createClass(DraggableHandleOverlay, [{\n key: \"render\",\n value: function render() {\n if (!this.domNode) {\n this.domNode = document.createElement('div');\n }\n this.domNode.classList.add('bjs-ovl-handle');\n // Functional handles MUST escape canvas-clip — they sit on / past\n // the element edge by design (resize edges, corners, grid column\n // dividers all protrude). Clipping them at canvas edge would chop\n // half the grab target off when the element sits flush with the\n // canvas viewport. See OVERLAY.md §24 Canvas-clip contract.\n this.domNode.classList.add('bjs-ovl-no-clip');\n this.domNode.setAttribute('data-interactive', '');\n\n // SA invariant I2 assert — pointer events + HTML5 DnD mutually exclusive.\n // Check this.domNode itself AND any ancestor already in DOM. (If appended\n // later under a draggable=true parent, the ancestor check runs at mount\n // time, but we also check the node itself here which covers most cases.)\n if (this.domNode.getAttribute('draggable') === 'true') {\n throw new Error('DraggableHandleOverlay: target node has draggable=\"true\". ' + 'Pointer events are suppressed after dragstart. Use NativeDragHandleOverlay instead.');\n }\n this._bindPointer();\n }\n }, {\n key: \"_bindPointer\",\n value: function _bindPointer() {\n var _this = this;\n if (this._pointerBound) return; // idempotent in subclasses that re-render\n this._pointerBound = true;\n this.domNode.addEventListener('pointerdown', function (e) {\n // Let middle-click / right-click pass through.\n if (e.button !== 0) return;\n e.preventDefault();\n e.stopPropagation();\n\n // Guard: if somehow we ended up inside a draggable=true ancestor,\n // HTML5 DnD would fire dragstart next — we'd lose pointermove.\n // Abort loudly before silent-failure territory.\n if (_this.domNode.closest('[draggable=\"true\"]')) {\n // eslint-disable-next-line no-console\n console.error('[overlay] DraggableHandleOverlay grabbed inside draggable=true ancestor — ' + 'pointer events will be suppressed by HTML5 DnD. Aborting drag. ' + 'Use NativeDragHandleOverlay for HTML5 DnD handles (SA invariant I2).');\n return;\n }\n _this._dragPointerId = e.pointerId;\n _this._dragStart = {\n x: e.clientX,\n y: e.clientY\n };\n _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].acquire(_this.domNode, e.pointerId);\n _this.domNode.classList.add('is-dragging');\n try {\n _this.onDragStart(e);\n } catch (err) {\n /* eslint-disable-next-line no-console */console.error('[overlay] onDragStart threw:', err);\n }\n var onMove = function onMove(ev) {\n if (ev.pointerId !== _this._dragPointerId) return;\n try {\n _this.onDrag(ev.clientX - _this._dragStart.x, ev.clientY - _this._dragStart.y, ev);\n } catch (err) {\n /* eslint-disable-next-line no-console */console.error('[overlay] onDrag threw:', err);\n }\n };\n var _cleanup = function cleanup(ev) {\n if (ev.pointerId !== _this._dragPointerId) return;\n _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].release(_this.domNode, ev.pointerId);\n _this.domNode.classList.remove('is-dragging');\n _this.domNode.removeEventListener('pointermove', onMove);\n _this.domNode.removeEventListener('pointerup', _cleanup);\n _this.domNode.removeEventListener('pointercancel', _cleanup);\n try {\n _this.onDragEnd(ev);\n } catch (err) {\n /* eslint-disable-next-line no-console */console.error('[overlay] onDragEnd threw:', err);\n }\n };\n _this.domNode.addEventListener('pointermove', onMove);\n _this.domNode.addEventListener('pointerup', _cleanup);\n _this.domNode.addEventListener('pointercancel', _cleanup);\n });\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n var _superPropGet2;\n // If destroyed mid-drag, PointerCaptureRegistry's lostpointercapture\n // listener (registered at acquire time) auto-cleans the registry when\n // this.domNode detaches. No manual release needed here. See §4.I5.\n (_superPropGet2 = _superPropGet(DraggableHandleOverlay, \"beforeDestroy\", this, 3)) === null || _superPropGet2 === void 0 || _superPropGet2([]);\n }\n\n // Subclass hooks:\n }, {\n key: \"onDragStart\",\n value: function onDragStart(/* e */) {}\n }, {\n key: \"onDrag\",\n value: function onDrag(/* dx, dy, e */) {}\n }, {\n key: \"onDragEnd\",\n value: function onDragEnd(/* e */) {}\n }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DraggableHandleOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/DraggableHandleOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/EdgeResizerOverlay.js":
/*!*****************************************************!*\
!*** ./src/includes/overlays/EdgeResizerOverlay.js ***!
\*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./DraggableHandleOverlay.js */ \"./src/includes/overlays/DraggableHandleOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * EdgeResizerOverlay — 6-px bar on one edge, drag to resize.\n *\n * Use for resize gestures along a named edge:\n * - Cell right-edge (Phase 1.5 Grid v2)\n * - (future) box bottom-edge, corner-less resize\n *\n * Subclass signature:\n * new EdgeResizerOverlay(element, { edge: 'left' | 'right' | 'top' | 'bottom' })\n *\n * Drag delta math is delegated to subclass `onDrag(dx, dy, e)`. This class\n * only owns positioning (bar sits on the named edge, 6px thick) and cursor.\n *\n * Subclasses typically compute percentage deltas against parent width/height\n * and call `element.formatter.setFormat('width', '50%') + applyFormatStyles()`.\n * NEVER renderElementControls in the drag loop (SA invariant I9).\n */\n\nvar EdgeResizerOverlay = /*#__PURE__*/function (_DraggableHandleOverl) {\n function EdgeResizerOverlay() {\n _classCallCheck(this, EdgeResizerOverlay);\n return _callSuper(this, EdgeResizerOverlay, arguments);\n }\n _inherits(EdgeResizerOverlay, _DraggableHandleOverl);\n return _createClass(EdgeResizerOverlay, [{\n key: \"render\",\n value: function render() {\n _superPropGet(EdgeResizerOverlay, \"render\", this, 3)([]); // wires pointer handlers + I2 assert\n this.domNode.classList.add('bjs-ovl-edge-resizer');\n var edge = this.opts.edge || 'right';\n this.domNode.classList.add(\"bjs-ovl-edge-\".concat(edge));\n\n // Cursor hint per axis.\n var isHorizontal = edge === 'left' || edge === 'right';\n this.domNode.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n\n // a11y — announce as separator with orientation. Arrow-key support is\n // the subclass's responsibility (they know the formatter key to nudge).\n this.domNode.setAttribute('role', 'separator');\n this.domNode.setAttribute('aria-orientation', isHorizontal ? 'vertical' : 'horizontal');\n this.domNode.setAttribute('tabindex', '0');\n }\n }, {\n key: \"position\",\n value: function position() {\n var _this = this;\n var edge = this.opts.edge || 'right';\n var THICK = 6;\n this.element.matchingDomNode(this.domNode, 0, function () {\n var domRect = _this.element.domNode.getBoundingClientRect();\n var iframe = _this.element.domNode.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe ? iframe.getBoundingClientRect() : {\n top: 0,\n left: 0\n };\n var absTop = iframeRect.top + domRect.top;\n var absLeft = iframeRect.left + domRect.left;\n var style = {\n position: 'fixed'\n };\n if (edge === 'left') Object.assign(style, {\n top: absTop + 'px',\n left: absLeft - THICK / 2 + 'px',\n width: THICK + 'px',\n height: domRect.height + 'px'\n });else if (edge === 'right') Object.assign(style, {\n top: absTop + 'px',\n left: absLeft + domRect.width - THICK / 2 + 'px',\n width: THICK + 'px',\n height: domRect.height + 'px'\n });else if (edge === 'top') Object.assign(style, {\n top: absTop - THICK / 2 + 'px',\n left: absLeft + 'px',\n width: domRect.width + 'px',\n height: THICK + 'px'\n });else Object.assign(style, {\n top: absTop + domRect.height - THICK / 2 + 'px',\n left: absLeft + 'px',\n width: domRect.width + 'px',\n height: THICK + 'px'\n });\n Object.assign(_this.domNode.style, style);\n });\n }\n }]);\n}(_DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (EdgeResizerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/EdgeResizerOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/FloatingActionBarOverlay.js":
/*!***********************************************************!*\
!*** ./src/includes/overlays/FloatingActionBarOverlay.js ***!
\***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * FloatingActionBarOverlay — pill row of icon buttons anchored to a corner.\n *\n * Use for selection-time contextual actions on an element:\n * - Image Upload / Replace / Crop / Link (Phase 1.4)\n * - (future) Button text / link editors\n *\n * Subclass signature:\n * new FloatingActionBarOverlay(element, { anchor: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' })\n *\n * Subclass MUST implement `getButtons()` returning:\n * [ { icon: 'upload', label: 'Upload', onClick: () => {...} }, ... ]\n *\n * Buttons render icons via the shared inline-SVG registry\n * (`pricingCardIcons.js`) when the name is known, so the action bar stays\n * visible even when the theme doesn't load Material Symbols font (common\n * inside email template iframes). Unknown names fall back to the Material\n * Symbols font span (still works in page mode / parent doc).\n *\n * `e.stopPropagation()` runs on each click so the underlying element's\n * select/deselect flow doesn't fire from a button click. (Required per\n * §12 OVERLAY.md troubleshooting.)\n */\n\n\nvar ANCHOR_INSET = 8; // px from element edge\nvar FloatingActionBarOverlay = /*#__PURE__*/function (_BaseOverlay) {\n function FloatingActionBarOverlay() {\n _classCallCheck(this, FloatingActionBarOverlay);\n return _callSuper(this, FloatingActionBarOverlay, arguments);\n }\n _inherits(FloatingActionBarOverlay, _BaseOverlay);\n return _createClass(FloatingActionBarOverlay, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-ovl-action-bar');\n this.domNode.setAttribute('data-interactive', '');\n this.domNode.setAttribute('role', 'toolbar');\n var buttons = this.getButtons() || [];\n buttons.forEach(function (btnSpec) {\n if (!btnSpec) return;\n var btn = document.createElement('button');\n btn.type = 'button';\n btn.classList.add('bjs-ovl-pill');\n if (btnSpec.label) {\n btn.setAttribute('data-tooltip', btnSpec.label);\n btn.setAttribute('aria-label', btnSpec.label);\n // Action bars anchor to top-right/top-left/bottom-right/bottom-left\n // of an element. Top-anchored bars → tooltip would clip above the\n // viewport, so flip placement to match anchor direction.\n var anchor = _this.opts.anchor || 'top-right';\n if (anchor.startsWith('top')) {\n btn.setAttribute('data-tooltip-placement', 'bottom');\n }\n }\n if (btnSpec.icon) {\n var ic = document.createElement('span');\n ic.classList.add('bjs-ovl-pill-icon');\n ic.setAttribute('aria-hidden', 'true');\n if (_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(btnSpec.icon)) {\n ic.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].render(btnSpec.icon, {\n size: 18,\n color: 'currentColor'\n });\n } else {\n // Fallback to Material Symbols font (parent doc loads it)\n ic.classList.add('material-symbols-rounded');\n ic.textContent = btnSpec.icon;\n }\n btn.appendChild(ic);\n }\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n if (typeof btnSpec.onClick === 'function') {\n try {\n btnSpec.onClick(e);\n } catch (err) {\n /* eslint-disable-next-line no-console */console.error('[overlay] action bar onClick threw:', err);\n }\n }\n });\n _this.domNode.appendChild(btn);\n });\n }\n }, {\n key: \"position\",\n value: function position() {\n var _this2 = this;\n var anchor = this.opts.anchor || 'top-right';\n this.element.matchingDomNode(this.domNode, 0, function () {\n var domRect = _this2.element.domNode.getBoundingClientRect();\n var iframe = _this2.element.domNode.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe ? iframe.getBoundingClientRect() : {\n top: 0,\n left: 0\n };\n var elemTop = iframeRect.top + domRect.top;\n var elemLeft = iframeRect.left + domRect.left;\n var elemRight = elemLeft + domRect.width;\n var elemBottom = elemTop + domRect.height;\n\n // We measure bar size AFTER first attach — fall back to approx.\n var barRect = _this2.domNode.getBoundingClientRect();\n var barW = barRect.width || 120;\n var barH = barRect.height || 40;\n var style = {\n position: 'fixed'\n };\n if (anchor === 'top-right') {\n style.top = elemTop + ANCHOR_INSET + 'px';\n style.left = elemRight - barW - ANCHOR_INSET + 'px';\n } else if (anchor === 'top-left') {\n style.top = elemTop + ANCHOR_INSET + 'px';\n style.left = elemLeft + ANCHOR_INSET + 'px';\n } else if (anchor === 'bottom-right') {\n style.top = elemBottom - barH - ANCHOR_INSET + 'px';\n style.left = elemRight - barW - ANCHOR_INSET + 'px';\n } else {\n // bottom-left\n style.top = elemBottom - barH - ANCHOR_INSET + 'px';\n style.left = elemLeft + ANCHOR_INSET + 'px';\n }\n Object.assign(_this2.domNode.style, style);\n });\n }\n\n /** Subclass override: return array of { icon, label, onClick } specs. */\n }, {\n key: \"getButtons\",\n value: function getButtons() {\n return [];\n }\n }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FloatingActionBarOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/FloatingActionBarOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/FontPopoverOverlay.js":
/*!*****************************************************!*\
!*** ./src/includes/overlays/FontPopoverOverlay.js ***!
\*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../TextSelectionTracker.js */ \"./src/includes/TextSelectionTracker.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * FontPopoverOverlay — W3.1 (TEXT_INLINE_PLAN, 2026-04-24).\n *\n * Anchored popover embedding Font Family (typeahead-style select via\n * `FontFamilyControl`), Font Weight (`FontWeightControl`), and Font Size\n * (`NumberControl` stepper ± px). Preview chip at the top shows \"The\n * quick brown fox\" rendered in the currently-selected family × weight ×\n * size so the user sees the outcome before clicking away.\n *\n * HARD RULE T3 (dual-view sync): the popover body instantiates the SAME\n * control classes the sidebar uses (`FontFamilyControl` / `FontWeight\n * Control` / `NumberControl`), each with the `{bus, elementUid,\n * formatterKey}` 4th-arg options so EVERY write (popover or sidebar)\n * emits `formatter:change` and BOTH surfaces mirror live via silent\n * `setValue(v, { silent: true })`. One write path (D13 v5), two\n * consumers, zero drift.\n *\n * Mount pattern mirrors `TextColorPopoverOverlay` /\n * `LinkOnSelectionPopoverOverlay`: lightweight non-`BaseOverlay` class,\n * owned by the singleton `TextInlineToolbarOverlay`, mounted in\n * `document.body`, anchored via `ToolbarPositioner.attach` to the\n * toolbar's Font button, disposed when the toolbar unmounts.\n *\n * Unit toggle (px / rem / em): NOT shipped in W3.1 initial. Storing a\n * unit on `font_size` requires a formatter schema migration (current\n * state is numeric px-only) and a serializer round-trip test. Deferred\n * — flagged for a W3.1b follow-up if user feedback asks.\n *\n * Selection preservation: the iframe selection is NOT restored on apply\n * because Font writes to element-level formatter (not range-level inline\n * tags). Clicking into the popover's inputs will naturally collapse the\n * canvas selection — that's fine; the popover writes through the\n * element's own write path (formatter → applyFormatStyles) which does\n * not depend on a live range.\n *\n * Scope-note surface (user feedback 2026-04-24). Every write here applies\n * to the WHOLE text element (shared write path with the sidebar). A user\n * who selected a partial range and opens this popover might expect the\n * change to land on just that range — so a muted info note under the\n * preview states the scope explicitly. Same constraint will apply to\n * W4.1 Advanced popover (line-height / letter-spacing / text-direction /\n * paragraph-spacing are all element-level CSS) — a matching note will\n * ship there. Color / Link / AI popovers are range-scoped (execCommand\n * + range mutation + replace) so they do NOT carry a scope note.\n */\n\n\n\n\n\n\n\nvar FontPopoverOverlay = /*#__PURE__*/function () {\n /**\n * @param {TextInlineToolbarOverlay} toolbar — owner.\n * @param {{ anchorBtn: HTMLElement }} opts\n */\n function FontPopoverOverlay(toolbar, opts) {\n _classCallCheck(this, FontPopoverOverlay);\n if (!toolbar || !opts || !opts.anchorBtn) {\n throw new Error('FontPopoverOverlay: toolbar + opts.anchorBtn required');\n }\n this._toolbar = toolbar;\n this._builder = toolbar._builder;\n this._anchorBtn = opts.anchorBtn;\n this.domNode = null;\n this._familyControl = null;\n this._weightControl = null;\n this._sizeControl = null;\n this._previewEl = null;\n this._positionHandle = null;\n this._onDocKey = null;\n this._onDocMouseDown = null;\n this._busOffPreview = null;\n this._mounted = false;\n // W5.2 — selection snapshot captured at open time, restored on\n // close so the user's highlight survives interacting with the\n // popover's inputs (which steal focus in the parent document).\n this._selectionSnap = null;\n }\n\n /* ── public lifecycle ─────────────────────────────────────────── */\n return _createClass(FontPopoverOverlay, [{\n key: \"open\",\n value: function open() {\n var _this = this;\n if (this._mounted) return;\n // W5.2 — snapshot the current selection BEFORE we mount. The popover's\n // inputs (selects, number stepper) will steal focus in the parent\n // document on click, which on some Chromium builds collapses the\n // iframe selection. We restore on close so the user's highlight\n // survives round-trip.\n this._selectionSnap = _TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_5__.SelectionGuard.save(this._builder);\n try {\n this._build();\n if (!this.domNode) return;\n document.body.appendChild(this.domNode);\n this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n anchor: function anchor() {\n return _this._anchorBtn.getBoundingClientRect();\n },\n target: this.domNode,\n offset: 8,\n collisionPadding: 12,\n preferredSide: 'below',\n flip: true\n });\n this._registerDismissListeners();\n this._subscribePreview();\n this._mounted = true;\n this._anchorBtn.setAttribute('aria-expanded', 'true');\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[bjs:font-popover] open failed:', err);\n this.close();\n }\n }\n }, {\n key: \"close\",\n value: function close() {\n if (!this._mounted && !this.domNode) return;\n this._unregisterDismissListeners();\n if (this._busOffPreview) {\n this._busOffPreview();\n this._busOffPreview = null;\n }\n if (this._positionHandle) {\n try {\n this._positionHandle.dispose();\n } catch (_) {}\n this._positionHandle = null;\n }\n // Destroy embedded controls so their bus subscriptions don't leak\n // past the popover's lifetime.\n [this._familyControl, this._weightControl, this._sizeControl].forEach(function (ctrl) {\n if (ctrl && typeof ctrl.destroy === 'function') {\n try {\n ctrl.destroy();\n } catch (_) {}\n }\n });\n this._familyControl = null;\n this._weightControl = null;\n this._sizeControl = null;\n this._previewEl = null;\n if (this.domNode && this.domNode.parentNode) {\n try {\n this.domNode.parentNode.removeChild(this.domNode);\n } catch (_) {}\n }\n this.domNode = null;\n this._mounted = false;\n try {\n this._anchorBtn.setAttribute('aria-expanded', 'false');\n } catch (_) {}\n // W5.2 — restore the pre-open selection so the highlight visually\n // returns and any downstream selection-aware code (toolbar state\n // reads, keyboard shortcut dispatcher) picks up where it left off.\n if (this._selectionSnap) {\n _TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_5__.SelectionGuard.restore(this._builder, this._selectionSnap);\n this._selectionSnap = null;\n }\n }\n }, {\n key: \"isOpen\",\n value: function isOpen() {\n return this._mounted;\n }\n\n /* ── build DOM ────────────────────────────────────────────────── */\n }, {\n key: \"_build\",\n value: function _build() {\n var _this2 = this;\n var element = this._resolveElement();\n if (!element) {\n // No target element — nothing to write to. Bail gracefully.\n return;\n }\n var p = document.createElement('div');\n p.className = 'bjs-ovl bjs-ovl-font-popover';\n p.setAttribute('role', 'dialog');\n p.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_popover.title'));\n p.setAttribute('data-interactive', '');\n\n // Header — title.\n p.appendChild(this._renderHeader());\n\n // Preview chip — \"The quick brown fox\" in current family × weight × size.\n this._previewEl = this._renderPreview(element);\n p.appendChild(this._previewEl);\n\n // Scope note — Font writes are element-level, not range-level.\n // Spelled out so a user with a partial range selected doesn't\n // assume the change will land on just that range.\n p.appendChild(this._renderScopeNote());\n\n // Body — 3 dual-mounted controls. Each writes through element.formatter\n // + emits `formatter:change`; sidebar instances silently mirror via\n // the same bus. HARD RULE T3 (dual-view) held automatically.\n var body = document.createElement('div');\n body.className = 'bjs-font-popover-body';\n var setFmt = function setFmt(key) {\n return function (value) {\n element.formatter.setFormat(key, value);\n if (typeof element.applyFormatStyles === 'function') {\n element.applyFormatStyles();\n } else if (typeof element.render === 'function') {\n element.render();\n }\n _this2._updatePreview();\n };\n };\n var busOpts = function busOpts(key) {\n return {\n bus: _this2._builder && _this2._builder.events,\n elementUid: element.id,\n formatterKey: key\n };\n };\n this._familyControl = new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), element.formatter.getFormat('font_family'), {\n setValue: setFmt('font_family')\n }, busOpts('font_family'));\n body.appendChild(this._familyControl.domNode);\n this._weightControl = new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), element.formatter.getFormat('font_weight'), {\n setValue: setFmt('font_weight')\n }, busOpts('font_weight'));\n body.appendChild(this._weightControl.domNode);\n this._sizeControl = new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), element.formatter.getFormat('font_size'), {\n setValue: setFmt('font_size')\n }, _objectSpread({\n defaultValue: 16,\n minValue: 8,\n maxValue: 72,\n suffix: 'px',\n allowZero: false\n }, busOpts('font_size')));\n body.appendChild(this._sizeControl.domNode);\n p.appendChild(body);\n this.domNode = p;\n }\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var header = document.createElement('div');\n header.className = 'bjs-font-popover-header';\n var iconWrap = document.createElement('span');\n iconWrap.className = 'bjs-font-popover-header-icon';\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded';\n icon.textContent = 'text_format';\n icon.setAttribute('aria-hidden', 'true');\n iconWrap.appendChild(icon);\n var title = document.createElement('h3');\n title.className = 'bjs-font-popover-title';\n title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_popover.title');\n header.appendChild(iconWrap);\n header.appendChild(title);\n return header;\n }\n }, {\n key: \"_renderPreview\",\n value: function _renderPreview(element) {\n var chip = document.createElement('div');\n chip.className = 'bjs-font-popover-preview';\n chip.setAttribute('aria-hidden', 'true'); // live region = not useful; visual only\n chip.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_popover.preview_text');\n this._applyPreviewStyle(chip, element);\n return chip;\n }\n }, {\n key: \"_renderScopeNote\",\n value: function _renderScopeNote() {\n var note = document.createElement('div');\n note.className = 'bjs-font-popover-scope-note';\n note.setAttribute('role', 'note');\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded bjs-font-popover-scope-note-icon';\n icon.setAttribute('aria-hidden', 'true');\n icon.textContent = 'info';\n var text = document.createElement('span');\n text.className = 'bjs-font-popover-scope-note-text';\n text.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_popover.scope_note');\n note.appendChild(icon);\n note.appendChild(text);\n return note;\n }\n }, {\n key: \"_applyPreviewStyle\",\n value: function _applyPreviewStyle(chip, element) {\n if (!chip) return;\n var fmt = element && element.formatter;\n if (!fmt) return;\n var family = fmt.getFormat('font_family');\n var weight = fmt.getFormat('font_weight');\n var size = fmt.getFormat('font_size');\n if (family) chip.style.fontFamily = family;else chip.style.removeProperty('font-family');\n if (weight) chip.style.fontWeight = String(weight);else chip.style.removeProperty('font-weight');\n if (size) chip.style.fontSize = typeof size === 'number' ? size + 'px' : String(size);else chip.style.removeProperty('font-size');\n }\n }, {\n key: \"_updatePreview\",\n value: function _updatePreview() {\n var element = this._resolveElement();\n if (!element || !this._previewEl) return;\n this._applyPreviewStyle(this._previewEl, element);\n }\n\n /**\n * Subscribe to `formatter:change` so the preview chip live-updates\n * when the sidebar writes (same element, same key) — dual-view in\n * reverse direction (sidebar → popover preview).\n */\n }, {\n key: \"_subscribePreview\",\n value: function _subscribePreview() {\n var _this3 = this;\n var bus = this._builder && this._builder.events;\n var element = this._resolveElement();\n if (!bus || !element || typeof bus.on !== 'function') return;\n this._busOffPreview = bus.on('formatter:change', function (payload) {\n if (!payload) return;\n if (payload.elementUid !== element.id) return;\n if (payload.key !== 'font_family' && payload.key !== 'font_weight' && payload.key !== 'font_size') return;\n // Defer one microtask so the applying control has flushed its\n // own setValue before we re-read the formatter.\n setTimeout(function () {\n return _this3._updatePreview();\n }, 0);\n });\n }\n\n /* ── element resolution ───────────────────────────────────────── */\n }, {\n key: \"_resolveElement\",\n value: function _resolveElement() {\n var payload = this._toolbar && this._toolbar._currentPayload;\n if (!payload) return null;\n var uid = payload.elementUid;\n var uiMgr = this._builder && this._builder.uiManager;\n if (!uiMgr || !Array.isArray(uiMgr.elements)) return null;\n return uiMgr.elements.find(function (el) {\n return el && el.id === uid;\n }) || null;\n }\n\n /* ── dismissal ────────────────────────────────────────────────── */\n }, {\n key: \"_registerDismissListeners\",\n value: function _registerDismissListeners() {\n var _this4 = this;\n this._onDocKey = function (e) {\n if (e.key === 'Escape') {\n e.stopPropagation();\n _this4.close();\n }\n };\n document.addEventListener('keydown', this._onDocKey, true);\n this._onDocMouseDown = function (e) {\n if (!_this4.domNode) return;\n var t = e.target;\n if (_this4.domNode.contains(t)) return;\n if (t && _this4._anchorBtn && _this4._anchorBtn.contains(t)) return;\n _this4.close();\n };\n setTimeout(function () {\n if (_this4._mounted) document.addEventListener('mousedown', _this4._onDocMouseDown, true);\n }, 0);\n }\n }, {\n key: \"_unregisterDismissListeners\",\n value: function _unregisterDismissListeners() {\n if (this._onDocKey) {\n document.removeEventListener('keydown', this._onDocKey, true);\n this._onDocKey = null;\n }\n if (this._onDocMouseDown) {\n document.removeEventListener('mousedown', this._onDocMouseDown, true);\n this._onDocMouseDown = null;\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FontPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/FontPopoverOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/GridColumnResizeOverlay.js":
/*!**********************************************************!*\
!*** ./src/includes/overlays/GridColumnResizeOverlay.js ***!
\**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./DraggableHandleOverlay.js */ \"./src/includes/overlays/DraggableHandleOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * GridColumnResizeOverlay — Phase 1.3\n *\n * Draggable 6px-wide vertical bar sitting between two neighboring cells\n * of a Grid. Dragging updates both cells' width formats, conserving sum\n * (if left grows, right shrinks). Each Grid contributes (cells.length - 1)\n * instances — one per inter-cell boundary.\n *\n * Positioning: straddles the cell edge (left - THICK/2, width = THICK).\n * Height = cell height (taken from leftCell, assumes rows have equal row-height).\n *\n * Width math:\n * - Start-of-drag snapshots leftCell % and rightCell %, read via parseFloat.\n * - dxPct = (e.clientX - startX) / gridWidth * 100\n * - newLeft = clamp(startLeft + dxPct, 5, total - 5)\n * - newRight = total - newLeft\n * - `'width'` format emitted as \"NN.NN%\". Non-% width formats (px / em /\n * auto / bare numeric) fall back gracefully — parseFloat('auto') = NaN\n * treated as \"can't resize this boundary\" and drag bails.\n *\n * Keyboard: arrow keys while focused shift 1% (or 5% with Shift).\n *\n * NO-FLICKER (SA invariant I9): updates use `formatter.setFormat + applyFormatStyles`\n * on each cell. NEVER calls `builder.renderElementControls`.\n *\n * See docs/core/OVERLAY.md §6 tutorial, §7.1 Grid example, docs/archived/OVERLAY_PLAN.md §3.4.\n */\n\n\n// Hit-zone width — wide enough to forgive aim, but visually subtle (the\n// always-visible CSS pill thumb sits at the center). 12px covers typical\n// mouse precision (3px × 4) AND straddles the cell_gap fully when gap ≤ 12.\nvar THICK = 12;\nvar MIN_PCT = 5;\nvar GridColumnResizeOverlay = /*#__PURE__*/function (_DraggableHandleOverl) {\n function GridColumnResizeOverlay() {\n _classCallCheck(this, GridColumnResizeOverlay);\n return _callSuper(this, GridColumnResizeOverlay, arguments);\n }\n _inherits(GridColumnResizeOverlay, _DraggableHandleOverl);\n return _createClass(GridColumnResizeOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'select';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(GridColumnResizeOverlay, \"render\", this, 3)([]); // pointer handlers + I2 assert\n this.domNode.classList.add('bjs-ovl-grid-separator');\n this.domNode.style.cursor = 'col-resize';\n this.domNode.setAttribute('role', 'separator');\n this.domNode.setAttribute('aria-orientation', 'vertical');\n this.domNode.setAttribute('tabindex', '0');\n this.domNode.setAttribute('aria-label', 'Resize column');\n this._bindKeyboard();\n }\n }, {\n key: \"_bindKeyboard\",\n value: function _bindKeyboard() {\n var _this = this;\n if (this._keyBound) return;\n this._keyBound = true;\n this.domNode.addEventListener('keydown', function (e) {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;\n e.preventDefault();\n var cells = _this._pair();\n if (!cells) return;\n var delta = (e.key === 'ArrowRight' ? 1 : -1) * (e.shiftKey ? 5 : 1);\n var startLeft = _this._readPct(cells.left);\n var startRight = _this._readPct(cells.right);\n if (isNaN(startLeft) || isNaN(startRight)) return;\n var total = startLeft + startRight;\n var newLeft = Math.max(MIN_PCT, Math.min(total - MIN_PCT, startLeft + delta));\n var newRight = total - newLeft;\n _this._applyPair(cells, newLeft, newRight);\n });\n }\n }, {\n key: \"position\",\n value: function position() {\n var _this2 = this;\n var cells = this._pair();\n if (!cells) {\n // Stale boundary (cells removed since mount) — hide rather than bail.\n if (this.domNode) this.domNode.style.display = 'none';\n return;\n }\n if (this.domNode) this.domNode.style.display = '';\n\n // Position centered on the GAP between the two cells (not on the\n // left cell's right edge). Critical for grids with cell_gap > 0:\n // the visible whitespace between cells is what users instinctively\n // aim at — a separator pinned to the left cell's right edge sits\n // BEFORE that whitespace and is unhittable. Center on the midpoint\n // of [leftCell.right, rightCell.left] and widen the bar to span at\n // least the visible gap (so cursor anywhere in the gap hits it).\n // matchingDomNode observers are wired to the LEFT cell — that's the\n // primary reflow trigger; right cell reflows propagate via its own\n // ResizeObserver chain.\n var leftCell = cells.left;\n var rightCell = cells.right;\n leftCell.matchingDomNode(this.domNode, 0, function () {\n var leftRect = leftCell.domNode.getBoundingClientRect();\n var rightRect = rightCell.domNode.getBoundingClientRect();\n var iframe = leftCell.domNode.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe ? iframe.getBoundingClientRect() : {\n top: 0,\n left: 0\n };\n var absTop = iframeRect.top + leftRect.top;\n var absLeft = iframeRect.left + leftRect.left;\n\n // Visible gap pixels (right cell may be in the next row if the\n // grid wrapped — tests for vertical separation and bails to\n // edge-of-left-cell positioning in that case).\n var gapPx = Math.max(0, rightRect.left - leftRect.right);\n var sameRow = Math.abs(rightRect.top - leftRect.top) < 4;\n var barWidth = sameRow ? Math.max(THICK, gapPx + THICK) : THICK;\n var gapCenter = sameRow ? (leftRect.right + rightRect.left) / 2 : leftRect.right;\n Object.assign(_this2.domNode.style, {\n position: 'fixed',\n top: absTop + 'px',\n left: iframeRect.left + gapCenter - barWidth / 2 + 'px',\n width: barWidth + 'px',\n height: leftRect.height + 'px'\n });\n });\n }\n\n // ─── Drag lifecycle ─────────────────────────────────────────────\n }, {\n key: \"onDragStart\",\n value: function onDragStart(/* e */\n ) {\n var cells = this._pair();\n if (!cells) return;\n this._dragCells = cells;\n this._dragGridWidth = this.element.domNode.getBoundingClientRect().width;\n this._dragStartLeft = this._readPct(cells.left);\n this._dragStartRight = this._readPct(cells.right);\n\n // Auto-promote non-percent boundaries to percent so the user can drag\n // ANY adjacent pair, not just the ones that happened to be authored\n // with `%` widths. Sample data ships cells with `auto`/`fill`/`px`/\n // grow-share — silently bailing here meant \"drag does nothing\" which\n // reads as a broken UI. We measure the cells' RENDERED widths against\n // the grid width, write back as `N%`, and proceed with normal % math.\n // Conserved sum = leftPct + rightPct (rest of the row keeps its\n // existing widths, including any other auto/fill cells).\n if (isNaN(this._dragStartLeft) || isNaN(this._dragStartRight)) {\n var _cells$left$formatter, _cells$right$formatte;\n var grid = this.element;\n var gridW = grid.domNode && grid.domNode.getBoundingClientRect().width || 0;\n if (gridW > 0 && cells.left.domNode && cells.right.domNode && typeof ((_cells$left$formatter = cells.left.formatter) === null || _cells$left$formatter === void 0 ? void 0 : _cells$left$formatter.setFormat) === 'function' && typeof ((_cells$right$formatte = cells.right.formatter) === null || _cells$right$formatte === void 0 ? void 0 : _cells$right$formatte.setFormat) === 'function') {\n var lW = cells.left.domNode.getBoundingClientRect().width;\n var rW = cells.right.domNode.getBoundingClientRect().width;\n // Subtract the cell-gap share so the % math doesn't double-\n // count gap pixels (Cell.template.html already deducts a\n // proportional share of cell_gap from the flex-basis).\n var gap = typeof grid.cell_gap === 'number' ? grid.cell_gap : 0;\n var count = Array.isArray(grid.cells) ? grid.cells.length : 1;\n var gapShare = count > 1 && gap > 0 ? gap * (count - 1) / count : 0;\n var lPct = (lW + gapShare) / gridW * 100;\n var rPct = (rW + gapShare) / gridW * 100;\n if (lPct >= MIN_PCT && rPct >= MIN_PCT && lPct + rPct <= 100) {\n var fmt = function fmt(v) {\n return v.toFixed(2).replace(/\\.00$/, '') + '%';\n };\n cells.left.formatter.setFormat('width', fmt(lPct));\n cells.right.formatter.setFormat('width', fmt(rPct));\n if (typeof cells.left.applyFormatStyles === 'function') cells.left.applyFormatStyles();\n if (typeof cells.right.applyFormatStyles === 'function') cells.right.applyFormatStyles();\n this._dragStartLeft = lPct;\n this._dragStartRight = rPct;\n return; // primed for normal drag math\n }\n }\n // Promotion not possible (zero-width cells, missing DOM, etc.) →\n // bail. Visible cursor still says col-resize so user knows the\n // affordance exists; subsequent moves will no-op gracefully.\n this._dragCells = null;\n }\n }\n }, {\n key: \"onDrag\",\n value: function onDrag(dx /*, dy, e */) {\n if (!this._dragCells || !this._dragGridWidth) return;\n var dxPct = dx / this._dragGridWidth * 100;\n var total = this._dragStartLeft + this._dragStartRight;\n var newLeft = Math.max(MIN_PCT, Math.min(total - MIN_PCT, this._dragStartLeft + dxPct));\n var newRight = total - newLeft;\n this._applyPair(this._dragCells, newLeft, newRight);\n }\n }, {\n key: \"onDragEnd\",\n value: function onDragEnd(/* e */\n ) {\n this._dragCells = null;\n this._dragGridWidth = 0;\n }\n\n // ─── Helpers ─────────────────────────────────────────────────────\n\n /** Resolve the {left, right} cell pair for this boundary. Returns null\n * if boundary index is out of range (cell removed since mount). */\n }, {\n key: \"_pair\",\n value: function _pair() {\n var cells = this.element.cells;\n var i = this.opts.boundaryIndex;\n if (!Array.isArray(cells) || i < 0 || i >= cells.length - 1) return null;\n var left = cells[i];\n var right = cells[i + 1];\n if (!left || !left.domNode || !right || !right.domNode) return null;\n return {\n left: left,\n right: right\n };\n }\n }, {\n key: \"_readPct\",\n value: function _readPct(cell) {\n var raw = cell.formatter.getFormat('width');\n if (raw === null || raw === undefined) return NaN;\n if (typeof raw === 'number') return raw; // bare-legacy\n var s = String(raw).trim();\n if (/%$/.test(s)) return parseFloat(s);\n // 'auto', 'px', 'em' etc. — treat as un-resizable via this boundary.\n return NaN;\n }\n }, {\n key: \"_applyPair\",\n value: function _applyPair(cells, newLeft, newRight) {\n var fmt = function fmt(v) {\n return v.toFixed(2).replace(/\\.00$/, '') + '%';\n };\n cells.left.formatter.setFormat('width', fmt(newLeft));\n cells.right.formatter.setFormat('width', fmt(newRight));\n // NO-FLICKER (I9): patch inline styles — NEVER renderElementControls.\n if (typeof cells.left.applyFormatStyles === 'function') cells.left.applyFormatStyles();\n if (typeof cells.right.applyFormatStyles === 'function') cells.right.applyFormatStyles();\n // If applyFormatStyles isn't present on the cell (legacy), fall back\n // to render() — less efficient but structurally correct.\n else {\n if (typeof cells.left.render === 'function') cells.left.render();\n if (typeof cells.right.render === 'function') cells.right.render();\n }\n }\n }]);\n}(_DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridColumnResizeOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/GridColumnResizeOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/GridInsertColumnOverlay.js":
/*!**********************************************************!*\
!*** ./src/includes/overlays/GridInsertColumnOverlay.js ***!
\**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * GridInsertColumnOverlay — Phase 1.5\n *\n * One \"+\" button instance per insertion boundary on a Grid. For an\n * n-cell grid, GridElement.getOverlays() composes (n + 1) instances:\n * insertAt = 0 → button on left edge of cell 0 (insert-before-first)\n * insertAt = i (1..n-1) → button on right edge of cell i-1\n * insertAt = n → button on right edge of last cell (insert-at-end)\n *\n * Click → grid.addCellAt(insertAt) → re-select previously-selected element\n * (cell index shifts by +1 if insert was at-or-before the old position).\n * Re-select is a one-shot, user-driven action — well within SA invariant\n * I9 (NO-FLICKER applies to drag/keystroke hot-paths, not click boundaries).\n *\n * Trigger: 'select' on the parent Grid. Grid's own isHoverable() is false\n * so this only mounts when the user explicitly selects the grid via the\n * breadcrumb / GridControl card (SA invariant I7).\n *\n * Visual: 24×24 circle button with material-symbols \"add\" icon. Positioned\n * 12 px above the grid's top edge, horizontally centered on the boundary\n * X coordinate. Top placement is deliberate — keeps the button clear of\n * the GridColumnResizeOverlay drag zone (full cell height) so the two\n * affordances never collide.\n *\n * See docs/core/OVERLAY.md §7.1 + docs/archived/OVERLAY_PLAN.md §3.6.\n */\n\n\nvar SIZE = 24;\nvar ABOVE_OFFSET = 12; // half-button above grid top edge\nvar GridInsertColumnOverlay = /*#__PURE__*/function (_BaseOverlay) {\n function GridInsertColumnOverlay() {\n _classCallCheck(this, GridInsertColumnOverlay);\n return _callSuper(this, GridInsertColumnOverlay, arguments);\n }\n _inherits(GridInsertColumnOverlay, _BaseOverlay);\n return _createClass(GridInsertColumnOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'select';\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this = this;\n this.domNode = document.createElement('button');\n this.domNode.type = 'button';\n this.domNode.classList.add('bjs-ovl-insert-button');\n // Functional control — escapes canvas-clip (the insert button sits\n // straddling the column boundary, often half-outside the cell rect).\n // See OVERLAY.md §24 Canvas-clip contract.\n this.domNode.classList.add('bjs-ovl-no-clip');\n this.domNode.setAttribute('data-interactive', '');\n this.domNode.setAttribute('tabindex', '0');\n var labelKey = this.opts.boundary === 'before' ? 'overlay.insert_column_before' : 'overlay.insert_column_after';\n var labelFallback = this.opts.boundary === 'before' ? 'Insert column before' : 'Insert column after';\n var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey, labelFallback);\n this.domNode.setAttribute('aria-label', label);\n this.domNode.setAttribute('data-tooltip', label);\n var icon = document.createElement('span');\n icon.classList.add('material-symbols-rounded');\n icon.setAttribute('aria-hidden', 'true');\n icon.textContent = 'add';\n this.domNode.appendChild(icon);\n this.domNode.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this._insert();\n });\n }\n }, {\n key: \"position\",\n value: function position() {\n var _this2 = this;\n var grid = this.element;\n if (!grid || !grid.domNode) return;\n var cells = Array.isArray(grid.cells) ? grid.cells : [];\n var insertAt = this.opts.insertAt;\n\n // Boundary anchor cell + edge:\n // insertAt 0 → cell 0 left edge\n // insertAt cells.len → last cell right edge\n // else → cell (insertAt - 1) right edge\n var targetCell;\n var edge;\n if (insertAt === 0) {\n targetCell = cells[0];\n edge = 'left';\n } else if (insertAt >= cells.length) {\n targetCell = cells[cells.length - 1];\n edge = 'right';\n } else {\n targetCell = cells[insertAt - 1];\n edge = 'right';\n }\n if (!targetCell || !targetCell.domNode) {\n // Stale boundary (cell was removed since mount) — hide rather\n // than throw. Next reflow will retry.\n this.domNode.style.display = 'none';\n return;\n }\n this.domNode.style.display = '';\n\n // Wire observers to the target cell so the button repositions on\n // any reflow that affects that cell (and, transitively, the grid).\n targetCell.matchingDomNode(this.domNode, 0, function () {\n var rect = targetCell.domNode.getBoundingClientRect();\n var iframe = targetCell.domNode.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe ? iframe.getBoundingClientRect() : {\n top: 0,\n left: 0\n };\n var gridRect = grid.domNode.getBoundingClientRect();\n var boundaryX = edge === 'left' ? iframeRect.left + rect.left : iframeRect.left + rect.right;\n // Anchor at grid's top edge so all (n+1) buttons line up on the\n // SAME row regardless of cell-height variation. Falls back to\n // cell rect if grid rect is degenerate.\n var topAnchor = gridRect.height ? gridRect.top : rect.top;\n var top = iframeRect.top + topAnchor - ABOVE_OFFSET;\n Object.assign(_this2.domNode.style, {\n position: 'fixed',\n top: top + 'px',\n left: boundaryX - SIZE / 2 + 'px',\n width: SIZE + 'px',\n height: SIZE + 'px'\n });\n });\n }\n\n /**\n * Insert a cell at this overlay's boundary, then re-select whatever\n * element was selected before so the sidebar + canvas overlays\n * refresh with the new cell count. Cell index shifts by +1 if the\n * previously-selected cell sits at-or-after the insert boundary.\n */\n }, {\n key: \"_insert\",\n value: function _insert() {\n var grid = this.element;\n if (!grid || typeof grid.addCellAt !== 'function') return;\n var host = this.host;\n var prevSelected = host ? host.selectedElement : null;\n var prevCellIndex = prevSelected && Array.isArray(grid.cells) ? grid.cells.indexOf(prevSelected) : -1;\n try {\n grid.addCellAt(this.opts.insertAt);\n } catch (err) {\n /* eslint-disable-next-line no-console */\n console.error('[overlay] GridInsertColumnOverlay addCellAt threw:', err);\n return;\n }\n if (!host || typeof host.selectElement !== 'function') return;\n\n // Decide what to re-select:\n // - cell was selected → its NEW index after the insert\n // - grid was selected → re-select grid (refreshes overlays)\n // - nothing was selected → select grid so user sees new structure\n var target;\n if (prevCellIndex >= 0) {\n var newIndex = prevCellIndex >= this.opts.insertAt ? prevCellIndex + 1 : prevCellIndex;\n target = grid.cells[newIndex] || grid;\n } else {\n target = grid;\n }\n\n // selectElement is a full-cycle re-init: unselect → render controls\n // → highlight → mount overlays. One-shot at click boundary; not in\n // hot-path. Within SA I9 budget.\n host.selectElement(target);\n }\n }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridInsertColumnOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/GridInsertColumnOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/GridStructureOverlay.js":
/*!*******************************************************!*\
!*** ./src/includes/overlays/GridStructureOverlay.js ***!
\*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./StructureVisualizerOverlay.js */ \"./src/includes/overlays/StructureVisualizerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * GridStructureOverlay — Phase 1.3\n *\n * When a Grid is selected, draws a dashed outline per cell so the user\n * sees the logical column structure while editing. Pair with (n-1)\n * `GridColumnResizeOverlay` instances that give drag-to-resize separators\n * between neighboring cells.\n *\n * `GridElement.isHoverable()` is false, so this overlay's trigger is\n * 'select' — mounts when user selects the grid via breadcrumb or\n * `GridControl` card in the sidebar (SA invariant I7).\n *\n * Composition: `layoutChildren()` runs on every reflow (scroll / resize /\n * DOM mutation / ResizeObserver fire) and redraws per-cell dashed boundaries.\n * The drawing is absolute-positioned children inside the overlay's root\n * (which covers the whole grid domNode).\n *\n * See docs/core/OVERLAY.md §7.1, docs/archived/OVERLAY_PLAN.md §3.4.\n */\n\nvar GridStructureOverlay = /*#__PURE__*/function (_StructureVisualizerO) {\n function GridStructureOverlay() {\n _classCallCheck(this, GridStructureOverlay);\n return _callSuper(this, GridStructureOverlay, arguments);\n }\n _inherits(GridStructureOverlay, _StructureVisualizerO);\n return _createClass(GridStructureOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'select';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(GridStructureOverlay, \"render\", this, 3)([]); // builds this.domNode with pointer-events: none\n this.domNode.classList.add('bjs-ovl-grid-structure');\n }\n }, {\n key: \"layoutChildren\",\n value: function layoutChildren() {\n var _this = this;\n // Wipe previous boundary children; separator overlays are separate\n // instances (Phase 1.3 GridColumnResizeOverlay) mounted alongside,\n // not inside this domNode — their pointer events can't be blocked\n // by this overlay's pass-through mask.\n this.domNode.innerHTML = '';\n var gridEl = this.element;\n if (!gridEl.cells || gridEl.cells.length === 0) return;\n var gridRect = gridEl.domNode.getBoundingClientRect();\n if (!gridRect.width || !gridRect.height) return;\n gridEl.cells.forEach(function (cell) {\n if (!cell || !cell.domNode) return;\n var cellRect = cell.domNode.getBoundingClientRect();\n if (!cellRect.width || !cellRect.height) return;\n var boundary = document.createElement('div');\n boundary.className = 'bjs-ovl-grid-cell-boundary';\n // Coordinates are LOCAL to the overlay's root (which matchingDomNode\n // sized to match gridRect). Don't add iframe offset here.\n Object.assign(boundary.style, {\n position: 'absolute',\n left: cellRect.left - gridRect.left + 'px',\n top: cellRect.top - gridRect.top + 'px',\n width: cellRect.width + 'px',\n height: cellRect.height + 'px'\n });\n _this.domNode.appendChild(boundary);\n });\n }\n }]);\n}(_StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridStructureOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/GridStructureOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ImageActionsOverlay.js":
/*!******************************************************!*\
!*** ./src/includes/overlays/ImageActionsOverlay.js ***!
\******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./FloatingActionBarOverlay.js */ \"./src/includes/overlays/FloatingActionBarOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageActionsOverlay — Phase 1.4\n *\n * Floating pill row anchored top-right of a selected image. Gives the user\n * one-click Upload / Effects / Resize / Crop / Link actions without leaving\n * the canvas.\n *\n * Trigger: 'select'. Mounts when user selects an ImageElement.\n *\n * Upload: opens file picker → FileReader dataURL → element.src = X + render()\n * Effects: enterEditMode('effects-popover') — mounts ImageEffectPopoverOverlay\n * Resize: enterEditMode('resize-popover') / 'resize' — popover or modal\n * Crop: enterEditMode('crop-popover') / 'crop' — popover or modal\n * Link: enterEditMode('link-popover') — mounts LinkPopoverOverlay\n * (2026-04-19, replaces the legacy BuilderjsPopup.prompt flow).\n *\n * `e.stopPropagation()` on each click prevents the element's select/deselect\n * flow from firing from a button click. (§12 OVERLAY.md troubleshooting.)\n *\n * See docs/core/OVERLAY.md §7.2 + docs/archived/OVERLAY_PLAN.md §3.5.\n */\n\n\n\n/* Surface preference per action — single map, swap a value to flip\n * between the modal popup and the anchored popover for that action.\n * Long-term knob (per IMAGE_OVERLAY_REFACTOR_PLAN.md user feedback):\n * keep both surfaces flexible — toggling crop / resize / link between\n * 'popup' and 'popover' should be a one-line edit here, not a\n * code-path rewrite.\n *\n * 'popup' → InlineEditorOverlay subclass (full-viewport mask).\n * Best for deep editing.\n * 'popover' → AnchoredPopoverOverlay subclass (anchored next to\n * the action button, canvas stays interactive).\n * Best for quick edits without losing context.\n */\nvar SURFACE_MODE = {\n crop: 'popover',\n // ← change to 'popup' to flip Crop to modal\n resize: 'popover',\n // ← change to 'popup' to flip Resize to modal\n effects: 'popover',\n // ← change to 'popup' to flip Effects to modal\n link: 'popover' // ← change to 'popup' to flip Link to modal (restore BuilderjsPopup.prompt)\n};\nvar EDIT_MODE = {\n crop: {\n popup: 'crop',\n popover: 'crop-popover'\n },\n resize: {\n popup: 'resize',\n popover: 'resize-popover'\n },\n effects: {\n popup: 'effects',\n popover: 'effects-popover'\n },\n link: {\n popup: 'link',\n popover: 'link-popover'\n }\n};\nvar ImageActionsOverlay = /*#__PURE__*/function (_FloatingActionBarOve) {\n function ImageActionsOverlay(element) {\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, ImageActionsOverlay);\n return _callSuper(this, ImageActionsOverlay, [element, Object.assign({\n anchor: 'top-right'\n }, opts)]);\n }\n _inherits(ImageActionsOverlay, _FloatingActionBarOve);\n return _createClass(ImageActionsOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'select';\n }\n }, {\n key: \"getButtons\",\n value: function getButtons() {\n var _this = this;\n return [{\n icon: 'upload',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.upload', 'Upload'),\n onClick: function onClick() {\n return _this._triggerUpload();\n }\n },\n // 2026-04-19 — replaced \"Replace\" (which duplicated Upload) with\n // \"Effects\" so the action bar covers all five distinct image\n // operations: Upload · Effects · Resize · Crop · Link. Each\n // edit-mode action opens via the SURFACE_MODE map so users get\n // a coherent Image edit surface.\n {\n icon: 'wand_shine',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.effects', 'Effects'),\n onClick: function onClick(e) {\n return _this._enterAction('effects', e);\n }\n }, {\n icon: 'open_in_full',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize', 'Resize'),\n onClick: function onClick(e) {\n return _this._enterAction('resize', e);\n }\n }, {\n icon: 'crop',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop', 'Crop'),\n onClick: function onClick(e) {\n return _this._enterAction('crop', e);\n }\n }, {\n icon: 'link',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.link', 'Link'),\n onClick: function onClick(e) {\n return _this._enterAction('link', e);\n }\n }];\n }\n\n /** Enter the edit mode for `action` ('crop' | 'resize') using the\n * surface ('popup' | 'popover') configured in SURFACE_MODE.\n * Records the action button rect so the anchored variant can\n * position itself next to the click target. */\n }, {\n key: \"_enterAction\",\n value: function _enterAction(action, e) {\n if (typeof this.element.enterEditMode !== 'function') return;\n var surface = SURFACE_MODE[action] || 'popup';\n var editMode = EDIT_MODE[action][surface];\n // Stash anchor rect for the popover variant — read at\n // popover.position() time. The action button is e.currentTarget.\n if (e && e.currentTarget && typeof e.currentTarget.getBoundingClientRect === 'function') {\n this.element._lastActionAnchorRect = e.currentTarget.getBoundingClientRect();\n } else {\n this.element._lastActionAnchorRect = null;\n }\n this.element.enterEditMode(editMode);\n }\n }, {\n key: \"_triggerUpload\",\n value: function _triggerUpload() {\n var _this2 = this;\n var input = document.createElement('input');\n input.type = 'file';\n input.accept = 'image/*';\n input.style.display = 'none';\n input.addEventListener('change', function (e) {\n var file = e.target.files && e.target.files[0];\n if (!file) return;\n // Size guard — refuse files > 10MB (spec'd in failure-state audit;\n // matches host app convention; emit console.warn for visibility).\n var MAX_BYTES = 10 * 1024 * 1024;\n if (file.size > MAX_BYTES) {\n // eslint-disable-next-line no-console\n console.warn('[overlay] image upload >10MB refused:', file.size, 'bytes');\n return;\n }\n // MIME guard — refuse non-image (input accept=\"image/*\" is advisory only).\n if (!/^image\\//.test(file.type || '')) {\n // eslint-disable-next-line no-console\n console.warn('[overlay] image upload rejected — not an image:', file.type);\n return;\n }\n var reader = new FileReader();\n reader.onload = function () {\n _this2.element.src = reader.result;\n if (typeof _this2.element.render === 'function') _this2.element.render();\n // Dual-view sync (SA invariant I4): patch sidebar preview\n // in place. Pattern parallels the ImageCropInlineOverlay\n // sync established in Phase 1.4 (D33). NO renderElementControls\n // (NO-FLICKER, SA invariant I9) — `syncFromExternal` patches\n // <img src> + filename + dimensions in the existing DOM.\n _this2._syncSidebar();\n };\n reader.onerror = function () {\n // eslint-disable-next-line no-console\n console.error('[overlay] image upload FileReader error:', reader.error);\n };\n reader.readAsDataURL(file);\n });\n document.body.appendChild(input);\n input.click();\n // Clean up input node after click — file picker keeps working via closure.\n setTimeout(function () {\n if (input.parentNode) input.parentNode.removeChild(input);\n }, 0);\n }\n }, {\n key: \"_enterCrop\",\n value: function _enterCrop() {\n if (typeof this.element.enterEditMode === 'function') {\n this.element.enterEditMode('crop');\n }\n }\n\n /**\n * Notify the sidebar's ImageControl (if mounted) that this element's\n * `src` / `alt` changed via the overlay. Looks the control up on the\n * shared `builder._activeControls.image` slot — set at construction\n * time by every ImageControl instance. Same pattern as the\n * ImageCropInlineOverlay → ImageCropControl sync established in\n * Phase 1.4 (D33). No-op when no sidebar control is currently mounted\n * (e.g. element has just been deselected — overlay still alive\n * mid-upload).\n */\n }, {\n key: \"_syncSidebar\",\n value: function _syncSidebar() {\n var _this$host;\n var ctrl = (_this$host = this.host) === null || _this$host === void 0 || (_this$host = _this$host._activeControls) === null || _this$host === void 0 ? void 0 : _this$host.image;\n if (ctrl && typeof ctrl.syncFromExternal === 'function') {\n ctrl.syncFromExternal({\n src: this.element.src,\n alt: this.element.alt\n });\n }\n }\n\n /* The Link action is now an edit-mode entrypoint via `_enterAction('link', e)`\n * — LinkPopoverOverlay handles apply/cancel + sidebar refresh. Flip back\n * to the modal popup: set SURFACE_MODE.link = 'popup' + restore a\n * BuilderjsPopup.prompt({ title, label, value, placeholder, kind })\n * method here for the 'popup' branch. */\n }]);\n}(_FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageActionsOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageActionsOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ImageCropInlineOverlay.js":
/*!*********************************************************!*\
!*** ./src/includes/overlays/ImageCropInlineOverlay.js ***!
\*********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./InlineEditorOverlay.js */ \"./src/includes/overlays/InlineEditorOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageCropInlineOverlay — 2026-04-19 (refactored to embed the real\n * ImageCropControl per IMAGE_OVERLAY_REFACTOR_PLAN.md Phase C).\n *\n * Modal \"Crop image\" popup mounted by ImageActionsOverlay's Crop action.\n * The popup body EMBEDS the same ImageCropControl the sidebar uses —\n * single source of truth for the rich crop UI (preview with focus dot,\n * aspect chips, custom ratio input, zoom slider, focus X/Y sliders,\n * reset button). Multiple instances of the control coexist (sidebar +\n * this popup); both subscribe to element.crop via `addSyncListener` so\n * any mutation in either surface re-syncs the other live (SA I13 R3).\n *\n * Body composition:\n * 1. Header — \"Crop image\" + crop icon.\n * 2. Embedded ImageCropControl (the entire rich UI from the sidebar).\n * 3. Footer — Cancel / Done. Cancel reverts element.crop to the\n * pre-edit snapshot (Object.assign in place — preserves the live\n * reference held by sidebar control's _sourceValueRef.crop).\n *\n * The previous implementation duplicated a stripped-down toggle + chip\n * grid + info banner inline. That divergence was the source of \"two\n * places to maintain crop UI\" complaints. After refactor, adding any\n * crop feature happens in ImageCropControl alone — sidebar + popup\n * pick it up automatically.\n *\n * Lifecycle: embedded control is destroyed in beforeDestroy() so its\n * subscribe disposer fires (SA I14).\n *\n * NO-FLICKER (SA I9): every mutation routes through the embedded\n * control's setCrop callback → element.render() → notifySyncListeners.\n * NEVER builder.renderElementControls in any path.\n */\n\n\nvar ImageCropInlineOverlay = /*#__PURE__*/function (_InlineEditorOverlay) {\n function ImageCropInlineOverlay() {\n _classCallCheck(this, ImageCropInlineOverlay);\n return _callSuper(this, ImageCropInlineOverlay, arguments);\n }\n _inherits(ImageCropInlineOverlay, _InlineEditorOverlay);\n return _createClass(ImageCropInlineOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'edit';\n }\n }, {\n key: \"getEditMode\",\n value: function getEditMode() {\n return 'crop';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(ImageCropInlineOverlay, \"render\", this, 3)([]);\n this.domNode.classList.add('bjs-ovl-image-crop-mask');\n this.domNode.setAttribute('aria-modal', 'true');\n this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-image-crop-title');\n\n // Snapshot pre-edit state for Cancel revert.\n this._snapshot = this._cloneCrop(this.element.crop);\n this._embedded = null;\n var panel = document.createElement('div');\n panel.className = 'bjs-ovl-image-crop-panel';\n panel.setAttribute('data-interactive', '');\n panel.appendChild(this._renderHeader());\n\n // Scrollable body — embed the real ImageCropControl.\n var body = document.createElement('div');\n body.className = 'bjs-ovl-image-crop-body';\n body.appendChild(this._renderEmbeddedControl());\n panel.appendChild(body);\n panel.appendChild(this._renderFooter());\n this.domNode.appendChild(panel);\n this._panel = panel;\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n if (this._embedded && typeof this._embedded.destroy === 'function') {\n try {\n this._embedded.destroy();\n } catch (_) {/* no-op */}\n }\n this._embedded = null;\n }\n }, {\n key: \"afterMount\",\n value: function afterMount() {\n var _this = this;\n // First focus → the crop toggle inside the embedded control. The\n // ImageCropControl renders an <input class=\"icrop-toggle-input\">\n // checkbox at the top of its DOM.\n requestAnimationFrame(function () {\n var toggle = _this.domNode.querySelector('.icrop-toggle-input');\n if (toggle && typeof toggle.focus === 'function') toggle.focus();\n });\n }\n\n // ────────────────────────── Sub-renderers ─────────────────────────────\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var header = document.createElement('div');\n header.className = 'bjs-ovl-image-crop-header';\n var iconWrap = document.createElement('span');\n iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded';\n icon.textContent = 'crop';\n iconWrap.appendChild(icon);\n var title = document.createElement('h3');\n title.className = 'bjs-ovl-image-crop-title';\n title.id = 'bjs-ovl-image-crop-title';\n title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_title', 'Crop image');\n header.appendChild(iconWrap);\n header.appendChild(title);\n return header;\n }\n }, {\n key: \"_renderEmbeddedControl\",\n value: function _renderEmbeddedControl() {\n var wrap = document.createElement('div');\n wrap.className = 'bjs-ovl-image-crop-embed';\n // ImageElement.buildCropControl() returns a fresh, sync-aware\n // instance. The popup never knows the internal DOM shape — it\n // just appends the control's domNode. When the user mutates\n // anything (toggle, chip, slider, reset), the control's\n // setCrop callback fires → element.render() →\n // notifySyncListeners → sidebar instance + this instance both\n // re-sync via syncFromExternal.\n this._embedded = this.element.buildCropControl();\n if (this._embedded && this._embedded.domNode) {\n wrap.appendChild(this._embedded.domNode);\n }\n return wrap;\n }\n }, {\n key: \"_renderFooter\",\n value: function _renderFooter() {\n var _this2 = this;\n var footer = document.createElement('div');\n footer.className = 'bjs-ovl-image-crop-footer';\n var cancel = document.createElement('button');\n cancel.type = 'button';\n cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n cancel.addEventListener('click', function (e) {\n e.preventDefault();\n _this2._cancel();\n });\n var apply = document.createElement('button');\n apply.type = 'button';\n apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n apply.addEventListener('click', function (e) {\n e.preventDefault();\n _this2._apply();\n });\n footer.appendChild(cancel);\n footer.appendChild(apply);\n return footer;\n }\n\n // ────────────────────────── State actions ─────────────────────────────\n }, {\n key: \"_cloneCrop\",\n value: function _cloneCrop(c) {\n if (!c) return null;\n return {\n enabled: !!c.enabled,\n ratioX: c.ratioX,\n ratioY: c.ratioY,\n zoom: c.zoom,\n posX: c.posX,\n posY: c.posY\n };\n }\n }, {\n key: \"_apply\",\n value: function _apply() {\n if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n }\n }, {\n key: \"_cancel\",\n value: function _cancel() {\n // Revert via Object.assign IN PLACE so the sidebar control's\n // _sourceValueRef.crop reference stays valid (SA I13 R1).\n if (!this.element.crop) {\n this.element.crop = {\n enabled: false,\n ratioX: 3,\n ratioY: 2,\n zoom: 1,\n posX: 50,\n posY: 50\n };\n }\n if (this._snapshot) {\n Object.assign(this.element.crop, this._snapshot);\n } else {\n Object.assign(this.element.crop, {\n enabled: false,\n ratioX: 3,\n ratioY: 2,\n zoom: 1,\n posX: 50,\n posY: 50\n });\n }\n if (typeof this.element.render === 'function') this.element.render();\n if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n }\n }]);\n}(_InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageCropInlineOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageCropInlineOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ImageCropPopoverOverlay.js":
/*!**********************************************************!*\
!*** ./src/includes/overlays/ImageCropPopoverOverlay.js ***!
\**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageCropPopoverOverlay — 2026-04-19 (Phase E).\n *\n * Anchored popover variant of ImageCropInlineOverlay. Same body\n * (embedded ImageCropControl), different surface chrome — popover\n * anchored next to the action-bar Crop button rather than full-viewport\n * modal. Mounted via `enterEditMode('crop-popover')` so the standard\n * mode filter routes it correctly.\n */\n\n\nvar ImageCropPopoverOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n function ImageCropPopoverOverlay() {\n _classCallCheck(this, ImageCropPopoverOverlay);\n return _callSuper(this, ImageCropPopoverOverlay, arguments);\n }\n _inherits(ImageCropPopoverOverlay, _AnchoredPopoverOverl);\n return _createClass(ImageCropPopoverOverlay, [{\n key: \"getEditMode\",\n value: function getEditMode() {\n return 'crop-popover';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(ImageCropPopoverOverlay, \"render\", this, 3)([]);\n this.domNode.classList.add('bjs-ovl-image-crop-popover');\n this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-image-crop-popover-title');\n\n // Snapshot for Cancel revert.\n this._snapshot = this._cloneCrop(this.element.crop);\n this._embedded = null;\n this.domNode.appendChild(this._renderHeader());\n var body = document.createElement('div');\n body.className = 'bjs-ovl-image-crop-popover-body bjs-ovl-image-crop-body';\n // Embed the same ImageCropControl factory as the modal popup.\n // Two surfaces, one control class — they auto-sync via subscribe.\n this._embedded = this.element.buildCropControl();\n if (this._embedded && this._embedded.domNode) {\n body.appendChild(this._embedded.domNode);\n }\n this.domNode.appendChild(body);\n this.domNode.appendChild(this._renderFooter());\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n _superPropGet(ImageCropPopoverOverlay, \"beforeDestroy\", this, 3)([]);\n if (this._embedded && typeof this._embedded.destroy === 'function') {\n try {\n this._embedded.destroy();\n } catch (_) {/* no-op */}\n }\n this._embedded = null;\n }\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var header = document.createElement('div');\n header.className = 'bjs-ovl-image-crop-header';\n var iconWrap = document.createElement('span');\n iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded';\n icon.textContent = 'crop';\n iconWrap.appendChild(icon);\n var title = document.createElement('h3');\n title.className = 'bjs-ovl-image-crop-title';\n title.id = 'bjs-ovl-image-crop-popover-title';\n title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_title', 'Crop image');\n header.appendChild(iconWrap);\n header.appendChild(title);\n return header;\n }\n }, {\n key: \"_renderFooter\",\n value: function _renderFooter() {\n var _this = this;\n var footer = document.createElement('div');\n footer.className = 'bjs-ovl-image-crop-footer';\n var cancel = document.createElement('button');\n cancel.type = 'button';\n cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n cancel.addEventListener('click', function (e) {\n e.preventDefault();\n _this._cancel();\n });\n var apply = document.createElement('button');\n apply.type = 'button';\n apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n apply.addEventListener('click', function (e) {\n e.preventDefault();\n _this._apply();\n });\n footer.appendChild(cancel);\n footer.appendChild(apply);\n return footer;\n }\n }, {\n key: \"_cloneCrop\",\n value: function _cloneCrop(c) {\n if (!c) return null;\n return {\n enabled: !!c.enabled,\n ratioX: c.ratioX,\n ratioY: c.ratioY,\n zoom: c.zoom,\n posX: c.posX,\n posY: c.posY\n };\n }\n }, {\n key: \"_apply\",\n value: function _apply() {\n if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n }\n }, {\n key: \"_cancel\",\n value: function _cancel() {\n if (!this.element.crop) {\n this.element.crop = {\n enabled: false,\n ratioX: 3,\n ratioY: 2,\n zoom: 1,\n posX: 50,\n posY: 50\n };\n }\n if (this._snapshot) {\n Object.assign(this.element.crop, this._snapshot);\n } else {\n Object.assign(this.element.crop, {\n enabled: false,\n ratioX: 3,\n ratioY: 2,\n zoom: 1,\n posX: 50,\n posY: 50\n });\n }\n if (typeof this.element.render === 'function') this.element.render();\n if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n }\n }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageCropPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageCropPopoverOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ImageEdgeResizerOverlay.js":
/*!**********************************************************!*\
!*** ./src/includes/overlays/ImageEdgeResizerOverlay.js ***!
\**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _EdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./EdgeResizerOverlay.js */ \"./src/includes/overlays/EdgeResizerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageEdgeResizerOverlay — 2026-04-19 (aspect-lock visibility gating)\n *\n * Single-axis resize handle on a named edge of a selected ImageElement.\n * - 'left' / 'right' edges → drag adjusts WIDTH only (height unchanged).\n * - 'top' / 'bottom' edges → drag adjusts HEIGHT only (width unchanged).\n *\n * Edges are the **distortion affordance** — the only way to deliberately\n * squash/stretch the image (or crop frame, when crop is on). Corners are\n * the \"nice resize\" affordance and always preserve the current aspect.\n *\n * Design contract — the popover \"Lock aspect ratio\" toggle governs edge\n * **visibility** only; drag math is unchanged (always single-axis, always\n * distorts when the user drags):\n * - LOCK ON (element._aspectLocked === true, the default) — edges are\n * HIDDEN. Enforcement surface: the toggle promises \"my proportions\n * are protected\", so the app removes the distortion handles to keep\n * that promise. Corners stay visible and ratio-preserving.\n * - LOCK OFF — edges visible; user can distort freely per axis. Corners\n * still stay ratio-preserving (corners have fixed semantics — the\n * toggle does NOT flip corner drag behavior).\n *\n * Works identically whether crop is on (drag resizes the crop FRAME) or\n * off (drag resizes the IMAGE) — the formatter writes affect width/height\n * on the element's wrapper, and `_getHighlightTarget()` routes positioning\n * to the visible target. Mental model: \"edges distort whatever you see.\"\n *\n * Visibility is driven reactively by subscribing to the element's sync\n * listener channel in `afterMount()` and flipping `display` on the domNode\n * whenever `_aspectLocked` changes. Mount is unconditional so toggling the\n * lock in either direction is immediately reflected without re-entering\n * the overlay mount/destroy cycle. Disposer fires in `beforeDestroy` so\n * the sync-listener Map stays bounded across selection cycles (SA I14).\n *\n * Trigger: `'select'`. Four instances mounted per selected image.\n *\n * Width/height format: same auto-promote pattern as the corner overlay —\n * first drag from `'auto'` / unset / non-px writes back as `Npx`; subsequent\n * drags work in pixels until the user changes the unit via the sidebar\n * DimensionControl or the new ResizeInline overlay.\n *\n * NO-FLICKER (SA I9): `formatter.setFormat + applyFormatStyles` per frame\n * if available, else `element.render()`. Never `renderElementControls`.\n *\n * See docs/core/OVERLAY.md §7.2 (Image overlays).\n */\n\nvar HORIZONTAL = ['left', 'right'];\nvar ImageEdgeResizerOverlay = /*#__PURE__*/function (_EdgeResizerOverlay) {\n function ImageEdgeResizerOverlay(element) {\n var _this;\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, ImageEdgeResizerOverlay);\n _this = _callSuper(this, ImageEdgeResizerOverlay, [element, opts]);\n _this._lockListenerId = null;\n _this._lockDisposer = null;\n return _this;\n }\n _inherits(ImageEdgeResizerOverlay, _EdgeResizerOverlay);\n return _createClass(ImageEdgeResizerOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'select';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(ImageEdgeResizerOverlay, \"render\", this, 3)([]);\n this.domNode.classList.add('bjs-ovl-image-handle');\n this.domNode.classList.add('bjs-ovl-image-handle--edge');\n this.domNode.classList.add(\"bjs-ovl-image-handle--edge-\".concat(this.opts.edge));\n }\n }, {\n key: \"afterMount\",\n value: function afterMount() {\n var _this2 = this;\n // Subscribe to element-state changes so toggling aspect-lock\n // (popover or inline overlay) flips edge visibility on the next\n // frame. Listener name is per-instance so all four edges coexist\n // in the sync Map without stomping.\n this._lockListenerId = \"ImageEdgeResizer:\".concat(this.opts.edge, \":\").concat(Math.random().toString(36).slice(2, 7));\n this._lockDisposer = this.element.addSyncListener(this._lockListenerId, function () {\n return _this2._refreshLockVisibility();\n });\n this._refreshLockVisibility();\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n var _superPropGet2;\n if (typeof this._lockDisposer === 'function') {\n try {\n this._lockDisposer();\n } catch (_) {/* no-op */}\n }\n this._lockDisposer = null;\n this._lockListenerId = null;\n (_superPropGet2 = _superPropGet(ImageEdgeResizerOverlay, \"beforeDestroy\", this, 3)) === null || _superPropGet2 === void 0 || _superPropGet2([]);\n }\n\n /** Toggle edge visibility based on element._aspectLocked. Default is\n * LOCK ON (undefined → treated as locked via !==false), so a fresh\n * selection hides the edges until the user opts into free distortion. */\n }, {\n key: \"_refreshLockVisibility\",\n value: function _refreshLockVisibility() {\n if (!this.domNode) return;\n var locked = this.element._aspectLocked !== false;\n this.domNode.style.display = locked ? 'none' : '';\n // When coming back into view, refresh the position — observers\n // keep the transform live during a session, but a resize-before-\n // unhide edge case would leave stale coords if we relied on that\n // alone.\n if (!locked) this.position();\n }\n\n /** Override edge primitive's element-wrapper-hugging position with one\n * that hugs the visible image. Same rationale as\n * ImageResizeCornerOverlay.position() — wrapper is wider than image\n * when parent has padding / alignment, so handles sit off-image. */\n }, {\n key: \"position\",\n value: function position() {\n var _this3 = this;\n var edge = this.opts.edge || 'right';\n var THICK = 6;\n // Read `_visualTarget()` INSIDE the callback so the closure\n // never holds a stale DOM reference after ImageElement re-render\n // replaces the inner <img>. See ImageResizeCornerOverlay.position\n // for the full root-cause story (2026-04-19 user report: \"after\n // resize popup closes anchors don't show\").\n this.element.matchingDomNode(this.domNode, 0, function () {\n var target = _this3._visualTarget();\n if (!target) return;\n var r = target.getBoundingClientRect();\n var iframe = target.ownerDocument.defaultView.frameElement;\n var ir = iframe ? iframe.getBoundingClientRect() : {\n top: 0,\n left: 0\n };\n var absTop = ir.top + r.top;\n var absLeft = ir.left + r.left;\n var style = {\n position: 'fixed'\n };\n if (edge === 'left') Object.assign(style, {\n top: absTop + 'px',\n left: absLeft - THICK / 2 + 'px',\n width: THICK + 'px',\n height: r.height + 'px'\n });else if (edge === 'right') Object.assign(style, {\n top: absTop + 'px',\n left: absLeft + r.width - THICK / 2 + 'px',\n width: THICK + 'px',\n height: r.height + 'px'\n });else if (edge === 'top') Object.assign(style, {\n top: absTop - THICK / 2 + 'px',\n left: absLeft + 'px',\n width: r.width + 'px',\n height: THICK + 'px'\n });else Object.assign(style, {\n top: absTop + r.height - THICK / 2 + 'px',\n left: absLeft + 'px',\n width: r.width + 'px',\n height: THICK + 'px'\n });\n Object.assign(_this3.domNode.style, style);\n });\n }\n }, {\n key: \"_visualTarget\",\n value: function _visualTarget() {\n if (typeof this.element._getHighlightTarget === 'function') {\n return this.element._getHighlightTarget();\n }\n return this.element.domNode;\n }\n }, {\n key: \"onDragStart\",\n value: function onDragStart(/* e */\n ) {\n var tgt = this._visualTarget() || this.element.domNode;\n var rect = tgt.getBoundingClientRect();\n this._dragStartRect = {\n width: rect.width,\n height: rect.height\n };\n var isHorizontal = HORIZONTAL.includes(this.opts.edge);\n var fmtKey = isHorizontal ? 'width' : 'height';\n var raw = this.element.formatter.getFormat(fmtKey);\n var str = raw == null ? '' : String(raw).trim();\n if (/%$/.test(str)) {\n this._dragUnit = '%';\n var parent = this.element.domNode.parentElement;\n this._dragParentSize = isHorizontal ? parent ? parent.getBoundingClientRect().width : rect.width : parent ? parent.getBoundingClientRect().height : rect.height;\n } else {\n // auto / fill / px / em / unset → first drag promotes to Npx.\n this._dragUnit = 'px';\n }\n }\n }, {\n key: \"onDrag\",\n value: function onDrag(dx, dy /*, e */) {\n if (!this._dragStartRect) return;\n var edge = this.opts.edge;\n // Edge → axis + sign:\n // left → -dx grows width (drag left = bigger when on left edge)\n // right → +dx grows width\n // top → -dy grows height\n // bottom → +dy grows height\n var newPx;\n var fmtKey;\n if (edge === 'right') {\n newPx = this._dragStartRect.width + dx;\n fmtKey = 'width';\n } else if (edge === 'left') {\n newPx = this._dragStartRect.width - dx;\n fmtKey = 'width';\n } else if (edge === 'bottom') {\n newPx = this._dragStartRect.height + dy;\n fmtKey = 'height';\n } else {\n // top\n newPx = this._dragStartRect.height - dy;\n fmtKey = 'height';\n }\n\n // Clamp to a sane minimum (below ~16px the image is practically invisible\n // and the handle stack collapses). Image-specific minimum, larger than\n // the generic 5px corner clamp because edges deliberately allow non-\n // aspect-preserved distortion and tiny dimensions would be a UX trap.\n newPx = Math.max(16, newPx);\n var serialized;\n if (this._dragUnit === '%' && this._dragParentSize > 0) {\n var pct = newPx / this._dragParentSize * 100;\n serialized = pct.toFixed(2).replace(/\\.00$/, '') + '%';\n } else {\n serialized = Math.round(newPx) + 'px';\n }\n this.element.formatter.setFormat(fmtKey, serialized);\n if (typeof this.element.applyFormatStyles === 'function') {\n this.element.applyFormatStyles();\n } else if (typeof this.element.render === 'function') {\n this.element.render();\n }\n }\n }, {\n key: \"onDragEnd\",\n value: function onDragEnd(/* e */\n ) {\n this._dragStartRect = null;\n this._dragUnit = 'px';\n this._dragParentSize = 0;\n }\n }]);\n}(_EdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageEdgeResizerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageEdgeResizerOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ImageEffectPopoverOverlay.js":
/*!************************************************************!*\
!*** ./src/includes/overlays/ImageEffectPopoverOverlay.js ***!
\************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageEffectPopoverOverlay — 2026-04-19 (Phase E expansion).\n *\n * Anchored popover for image effects (filters: grayscale, sepia, invert,\n * blur, brightness, contrast, saturate, hue-rotate, opacity). Mounted by\n * ImageActionsOverlay's \"Effects\" action when SURFACE_MODE.effects ===\n * 'popover'. Embeds the same ImageEffectControl factory the sidebar\n * uses — single source of truth for the slider math + preview render +\n * reset logic. Multi-surface sync via subscribe (SA I13).\n *\n * Anatomy:\n * 1. Header — \"Effects\" + tune icon.\n * 2. Embedded ImageEffectControl (preview thumbnail + 9 slider rows\n * with reset buttons + \"Reset all\" footer button).\n * 3. Footer — Cancel / Done. Cancel reverts element.effect to the\n * pre-edit snapshot (Object.assign in place — preserves the live\n * reference any other surface holds).\n *\n * Mode: 'effects-popover'. Modal counterpart 'effects' is reserved for\n * future SURFACE_MODE.effects = 'popup' switching.\n */\n\n\nvar ImageEffectPopoverOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n function ImageEffectPopoverOverlay() {\n _classCallCheck(this, ImageEffectPopoverOverlay);\n return _callSuper(this, ImageEffectPopoverOverlay, arguments);\n }\n _inherits(ImageEffectPopoverOverlay, _AnchoredPopoverOverl);\n return _createClass(ImageEffectPopoverOverlay, [{\n key: \"getEditMode\",\n value: function getEditMode() {\n return 'effects-popover';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(ImageEffectPopoverOverlay, \"render\", this, 3)([]);\n this.domNode.classList.add('bjs-ovl-image-effect-popover');\n this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-image-effect-popover-title');\n\n // Snapshot for Cancel revert (clone — no shared mutation).\n this._snapshot = Object.assign({}, this.element.effect);\n this._embedded = null;\n this.domNode.appendChild(this._renderHeader());\n var body = document.createElement('div');\n body.className = 'bjs-ovl-image-effect-popover-body bjs-ovl-image-crop-body';\n // Embed the SAME ImageEffectControl the sidebar uses. Both\n // instances subscribe to element.effect via the factory's\n // capability token and stay in sync via syncFromExternal.\n this._embedded = this.element.buildEffectControl();\n if (this._embedded && this._embedded.domNode) {\n body.appendChild(this._embedded.domNode);\n }\n this.domNode.appendChild(body);\n this.domNode.appendChild(this._renderFooter());\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n _superPropGet(ImageEffectPopoverOverlay, \"beforeDestroy\", this, 3)([]);\n if (this._embedded && typeof this._embedded.destroy === 'function') {\n try {\n this._embedded.destroy();\n } catch (_) {/* no-op */}\n }\n this._embedded = null;\n }\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var header = document.createElement('div');\n header.className = 'bjs-ovl-image-crop-header';\n var iconWrap = document.createElement('span');\n iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded';\n icon.textContent = 'wand_shine';\n iconWrap.appendChild(icon);\n var title = document.createElement('h3');\n title.className = 'bjs-ovl-image-crop-title';\n title.id = 'bjs-ovl-image-effect-popover-title';\n title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.effects', 'Effects');\n header.appendChild(iconWrap);\n header.appendChild(title);\n return header;\n }\n }, {\n key: \"_renderFooter\",\n value: function _renderFooter() {\n var _this = this;\n var footer = document.createElement('div');\n footer.className = 'bjs-ovl-image-crop-footer';\n var cancel = document.createElement('button');\n cancel.type = 'button';\n cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n cancel.addEventListener('click', function (e) {\n e.preventDefault();\n _this._cancel();\n });\n var apply = document.createElement('button');\n apply.type = 'button';\n apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n apply.addEventListener('click', function (e) {\n e.preventDefault();\n _this._apply();\n });\n footer.appendChild(cancel);\n footer.appendChild(apply);\n return footer;\n }\n }, {\n key: \"_apply\",\n value: function _apply() {\n if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n }\n }, {\n key: \"_cancel\",\n value: function _cancel() {\n // Revert effect via Object.assign in place — preserves the\n // reference held by any concurrent surface (sidebar, etc).\n if (this._snapshot) {\n Object.assign(this.element.effect, this._snapshot);\n }\n if (typeof this.element.render === 'function') this.element.render();\n if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n }\n }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageEffectPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageEffectPopoverOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ImageResizeCornerOverlay.js":
/*!***********************************************************!*\
!*** ./src/includes/overlays/ImageResizeCornerOverlay.js ***!
\***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _ResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ResizeCornerOverlay.js */ \"./src/includes/overlays/ResizeCornerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageResizeCornerOverlay — Phase 1.4\n *\n * Draggable corner handle (nw / ne / se / sw) on a selected image. Drag\n * updates `width` + `height` formatter values proportionally — corners are\n * **always** aspect-locked regardless of the popover \"Lock aspect ratio\"\n * toggle (design contract, matches Figma/Photoshop/Canva — corners are\n * the \"nice resize\" affordance, edges are the \"deliberate distort\"\n * affordance). The toggle affects the popover Width/Height INPUTS only;\n * canvas handles have fixed semantics so muscle memory works the same\n * whether the toggle is on or off, whether crop is on or off.\n *\n * The preserved ratio is the **current** rendered aspect captured at drag\n * start (`rect.width / rect.height`) — dragging preserves whatever\n * proportion the user is looking at right now, including after prior\n * edge-drag distortion. To restore the original natural ratio, the user\n * flips the lock on in the popover and edits the inputs.\n *\n * Uses the ResizeCornerOverlay primitive for positioning + cursor; subclasses\n * only the drag-math callbacks.\n *\n * Trigger: 'select'. Four instances mounted per selected image.\n *\n * Width format: respects existing unit convention. Reads current\n * `formatter.getFormat('width')` string; if it's \"%\" based, treats dragging as\n * relative to parent width; if \"px\" based, absolute px. Falls back to px.\n *\n * NO-FLICKER (I9): `formatter.setFormat + applyFormatStyles` per frame if\n * available, else `element.render()`.\n *\n * See docs/core/OVERLAY.md §7.2 + docs/archived/OVERLAY_PLAN.md §3.5.\n */\n\nvar ImageResizeCornerOverlay = /*#__PURE__*/function (_ResizeCornerOverlay) {\n function ImageResizeCornerOverlay(element) {\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, ImageResizeCornerOverlay);\n // `aspectLock: true` is the fixed design contract for image\n // corners — see header rationale. Not derived from element state.\n return _callSuper(this, ImageResizeCornerOverlay, [element, Object.assign({\n aspectLock: true\n }, opts)]);\n }\n _inherits(ImageResizeCornerOverlay, _ResizeCornerOverlay);\n return _createClass(ImageResizeCornerOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'select';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(ImageResizeCornerOverlay, \"render\", this, 3)([]);\n // Image-specific class so styling diverges from generic `.bjs-ovl-resize-corner`\n // (warm accent + rounder handle) without forking the primitive.\n this.domNode.classList.add('bjs-ovl-image-handle');\n this.domNode.classList.add('bjs-ovl-image-handle--corner');\n }\n\n /** Override the primitive's element-wrapper-hugging position with one\n * that hugs the actual VISIBLE IMAGE (the `<img>` inside the wrapper,\n * or the crop wrapper when crop is enabled). Without this the corners\n * sit on the wrapper edge — which is wider than the image when the\n * parent has padding or auto-centers — and the user sees a gap\n * between the image edge and the handle. Mirrors the same trick\n * ImageElement.addSelectedHighlight uses for `image-highlight-box`. */\n }, {\n key: \"position\",\n value: function position() {\n var _this = this;\n var corner = this.opts.corner || 'se';\n // Read `_visualTarget()` INSIDE the callback (not outside) — the\n // inner <img> / crop wrapper gets replaced whenever ImageElement\n // re-renders (popup mutations, sidebar edits, programmatic\n // setFormat). Capturing the target outside leaves the closure\n // holding a detached DOM node whose getBoundingClientRect\n // returns zeros — handles position at (0,0) and visually\n // disappear off-canvas. (User report 2026-04-19: \"after resize\n // popup closes, anchors don't show; click re-shows them\" — the\n // re-click triggered fresh select-mount which re-evaluated the\n // target, masking the stale-closure root cause.)\n this.element.matchingDomNode(this.domNode, 0, function () {\n var target = _this._visualTarget();\n if (!target) return;\n var r = target.getBoundingClientRect();\n var iframe = target.ownerDocument.defaultView.frameElement;\n var ir = iframe ? iframe.getBoundingClientRect() : {\n top: 0,\n left: 0\n };\n var half = 7; // half of CSS handle size (14)\n var absTop = ir.top + r.top;\n var absLeft = ir.left + r.left;\n var top, left;\n switch (corner) {\n case 'nw':\n top = absTop - half;\n left = absLeft - half;\n break;\n case 'ne':\n top = absTop - half;\n left = absLeft + r.width - half;\n break;\n case 'sw':\n top = absTop + r.height - half;\n left = absLeft - half;\n break;\n case 'se':\n default:\n top = absTop + r.height - half;\n left = absLeft + r.width - half;\n break;\n }\n Object.assign(_this.domNode.style, {\n position: 'fixed',\n top: top + 'px',\n left: left + 'px'\n });\n });\n }\n }, {\n key: \"_visualTarget\",\n value: function _visualTarget() {\n if (typeof this.element._getHighlightTarget === 'function') {\n return this.element._getHighlightTarget();\n }\n return this.element.domNode;\n }\n }, {\n key: \"onDragStart\",\n value: function onDragStart(/* e */\n ) {\n var tgt = this._visualTarget() || this.element.domNode;\n var rect = tgt.getBoundingClientRect();\n this._dragStartRect = {\n width: rect.width,\n height: rect.height\n };\n this._dragAspect = rect.height > 0 ? rect.width / rect.height : 1;\n // Detect unit from current width format. Treat unset / 'auto' as px\n // so first-time drag always works (auto-promote pattern, mirrors\n // GridColumnResizeOverlay 2026-04-19 fix).\n var wFmt = this.element.formatter.getFormat('width');\n var wStr = wFmt == null ? '' : String(wFmt).trim();\n if (/%$/.test(wStr)) {\n this._dragUnit = '%';\n var parent = this.element.domNode.parentElement;\n this._dragParentWidth = parent ? parent.getBoundingClientRect().width : rect.width;\n this._dragStartPct = parseFloat(wStr) || 100;\n } else {\n // 'auto' / 'fill' / unset / 'px' / 'em' etc → drag in px against\n // the rendered rect. The setFormat below writes 'Npx' which\n // makes subsequent drags trivially in-range.\n this._dragUnit = 'px';\n }\n }\n }, {\n key: \"onDrag\",\n value: function onDrag(dx, dy /*, e */) {\n if (!this._dragStartRect) return;\n var corner = this.opts.corner || 'se';\n // Translate drag direction per corner. SE grows with (+dx, +dy);\n // NW shrinks with (+dx, +dy); NE = +dx, -dy; SW = -dx, +dy.\n var dirX = corner === 'ne' || corner === 'se' ? 1 : -1;\n var dirY = corner === 'se' || corner === 'sw' ? 1 : -1;\n var newWidthPx = this._dragStartRect.width + dirX * dx;\n var newHeightPx = this._dragStartRect.height + dirY * dy;\n\n // Aspect-lock — corners are ALWAYS aspect-preserving (fixed\n // design contract per docs/core/OVERLAY.md §7.2; decoupled from the\n // popover's `_aspectLocked` toggle, which only governs the\n // Width/Height inputs + edge-handle visibility). Width dominates\n // (typical resize gestures are horizontal-first).\n if (this.opts.aspectLock !== false && this._dragAspect > 0) {\n newHeightPx = newWidthPx / this._dragAspect;\n }\n\n // Clamp to 20px minimum (below that the handles crowd each other).\n newWidthPx = Math.max(20, newWidthPx);\n newHeightPx = Math.max(20, newHeightPx);\n var newWidthStr, newHeightStr;\n if (this._dragUnit === '%' && this._dragParentWidth > 0) {\n var pct = newWidthPx / this._dragParentWidth * 100;\n newWidthStr = pct.toFixed(2).replace(/\\.00$/, '') + '%';\n // Height: keep px for % width (common pattern: \"width: 50%; height: auto\" —\n // here we force a numeric height to preserve the dragged aspect).\n newHeightStr = Math.round(newHeightPx) + 'px';\n } else {\n newWidthStr = Math.round(newWidthPx) + 'px';\n newHeightStr = Math.round(newHeightPx) + 'px';\n }\n this.element.formatter.setFormat('width', newWidthStr);\n this.element.formatter.setFormat('height', newHeightStr);\n // NO-FLICKER: prefer applyFormatStyles, fall back to render.\n if (typeof this.element.applyFormatStyles === 'function') {\n this.element.applyFormatStyles();\n } else if (typeof this.element.render === 'function') {\n this.element.render();\n }\n }\n }, {\n key: \"onDragEnd\",\n value: function onDragEnd(/* e */\n ) {\n this._dragStartRect = null;\n this._dragAspect = 0;\n this._dragUnit = 'px';\n this._dragParentWidth = 0;\n }\n }]);\n}(_ResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageResizeCornerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageResizeCornerOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ImageResizeInlineOverlay.js":
/*!***********************************************************!*\
!*** ./src/includes/overlays/ImageResizeInlineOverlay.js ***!
\***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./InlineEditorOverlay.js */ \"./src/includes/overlays/InlineEditorOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageResizeInlineOverlay — 2026-04-19 (refactored to embed real\n * DimensionControl instances per IMAGE_OVERLAY_REFACTOR_PLAN.md Phase C).\n *\n * Modal \"Resize image\" popup mounted by ImageActionsOverlay's Resize\n * action. The popup body EMBEDS the same DimensionControl instances the\n * sidebar uses — single source of truth for the input/slider/unit/preset\n * UI. Multiple instances of the same control coexist (sidebar + this\n * popup); both subscribe to element state via `addSyncListener` so any\n * mutation in either surface re-syncs the other live (SA I13 R3 + R4).\n *\n * Body composition (top to bottom):\n * 1. Image preview thumbnail — context for dimension changes.\n * 2. Width — embedded DimensionControl (full feature set: slider +\n * input + unit dropdown + presets in dim-menu).\n * 3. Height — same.\n * 4. Aspect lock toggle — in-memory element state (`element._aspectLocked`,\n * default ON). When ON, editing either width or height in the\n * embedded DimensionControl couples the companion axis via\n * `ImageElement._writeCoupledDimensions` using the crop/natural\n * aspect ratio. State persists across popup open/close within the\n * session (NOT serialized — saved templates stay free of UI\n * preferences). See ImageElement.buildAspectLockRow for the shared\n * row DOM + sync wiring.\n * 5. Crop-on hint banner — only when element.crop.enabled.\n * 6. Advanced collapsible — embeds 4 more DimensionControls\n * (max_width, max_height, min_width, min_height).\n *\n * Footer: Cancel / Done. Cancel reverts the formatter to a snapshot\n * captured in render(); Done exits cleanly (mutations already committed\n * via the embedded DimensionControl onChange callbacks).\n *\n * Lifecycle: each embedded control is destroyed in beforeDestroy() so\n * its subscribe disposer fires and the element's listener Set stays\n * bounded across open/close cycles (SA I14 control lifecycle).\n *\n * NO-FLICKER (SA I9): every mutation routes through the embedded\n * control's onChange → element.setFormat → element.render() →\n * notifySyncListeners. NEVER builder.renderElementControls in any path.\n */\n\n\nvar ImageResizeInlineOverlay = /*#__PURE__*/function (_InlineEditorOverlay) {\n function ImageResizeInlineOverlay() {\n _classCallCheck(this, ImageResizeInlineOverlay);\n return _callSuper(this, ImageResizeInlineOverlay, arguments);\n }\n _inherits(ImageResizeInlineOverlay, _InlineEditorOverlay);\n return _createClass(ImageResizeInlineOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'edit';\n }\n }, {\n key: \"getEditMode\",\n value: function getEditMode() {\n return 'resize';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(ImageResizeInlineOverlay, \"render\", this, 3)([]);\n this.domNode.classList.add('bjs-ovl-image-crop-mask');\n this.domNode.classList.add('bjs-ovl-image-resize-mask');\n this.domNode.setAttribute('aria-modal', 'true');\n this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-image-resize-title');\n\n // Snapshot every formatter key the popup edits, so Cancel can\n // revert the entire dimension set in one go.\n this._snapshot = this._snapshotFormats();\n this._aspectDisposer = null;\n this._embeddedControls = [];\n var panel = document.createElement('div');\n panel.className = 'bjs-ovl-image-crop-panel bjs-ovl-image-resize-panel';\n panel.setAttribute('data-interactive', '');\n panel.appendChild(this._renderHeader());\n var body = document.createElement('div');\n body.className = 'bjs-ovl-image-crop-body';\n\n // 1. Preview thumbnail — small image preserved-aspect thumb so the\n // user keeps visual context while editing dimensions.\n body.appendChild(this._renderPreview());\n\n // 2 + 3. Width + Height — embedded DimensionControl instances.\n // coupleAspect: true wires these to element._aspectLocked.\n var widthSection = this._embedControl(this.element.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_width', 'Width'), 'width', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'], {\n coupleAspect: true\n }));\n body.appendChild(widthSection);\n var heightSection = this._embedControl(this.element.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_height', 'Height'), 'height', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'], {\n coupleAspect: true\n }));\n body.appendChild(heightSection);\n\n // 4. Aspect lock toggle — shared helper on ImageElement\n // (single source of truth for DOM + state wiring).\n var aspect = this.element.buildAspectLockRow({\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_aspect_lock', 'Lock aspect ratio'),\n hint: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_aspect_hint', 'Editing one dimension updates the other proportionally.')\n });\n body.appendChild(aspect.row);\n this._aspectDisposer = aspect.dispose;\n\n // 5. Crop-on hint banner — observer pattern would be overkill for\n // a single conditional render; we re-check on each open.\n if (this._isCropOn()) body.appendChild(this._renderCropHint());\n\n // 6. Advanced section with max/min DimensionControls.\n body.appendChild(this._renderAdvancedSection());\n panel.appendChild(body);\n panel.appendChild(this._renderFooter());\n this.domNode.appendChild(panel);\n this._panel = panel;\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n // Destroy every embedded control so its subscribe disposer fires —\n // keeps element.addSyncListener Set bounded (SA I14).\n if (typeof this._aspectDisposer === 'function') {\n try {\n this._aspectDisposer();\n } catch (_) {/* no-op */}\n this._aspectDisposer = null;\n }\n if (Array.isArray(this._embeddedControls)) {\n var _iterator = _createForOfIteratorHelper(this._embeddedControls),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var c = _step.value;\n if (c && typeof c.destroy === 'function') {\n try {\n c.destroy();\n } catch (_) {/* no-op */}\n }\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n }\n this._embeddedControls = null;\n }\n }, {\n key: \"afterMount\",\n value: function afterMount() {\n var _this = this;\n // First focus → the width input (the most common edit target).\n requestAnimationFrame(function () {\n var input = _this.domNode.querySelector('.bjs-ovl-image-resize-embed .dim-value');\n if (input && typeof input.focus === 'function') {\n input.focus();\n if (typeof input.select === 'function') input.select();\n }\n });\n }\n\n // ────────────────────────── Sub-renderers ─────────────────────────────\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var header = document.createElement('div');\n header.className = 'bjs-ovl-image-crop-header';\n var iconWrap = document.createElement('span');\n iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded';\n icon.textContent = 'open_in_full';\n iconWrap.appendChild(icon);\n var title = document.createElement('h3');\n title.className = 'bjs-ovl-image-crop-title';\n title.id = 'bjs-ovl-image-resize-title';\n title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_title', 'Resize image');\n header.appendChild(iconWrap);\n header.appendChild(title);\n return header;\n }\n }, {\n key: \"_renderPreview\",\n value: function _renderPreview() {\n var wrap = document.createElement('div');\n wrap.className = 'bjs-ovl-image-resize-preview';\n var img = document.createElement('img');\n img.className = 'bjs-ovl-image-resize-preview-img';\n img.src = this.element.transferMediaAbsUrl ? this.element.transferMediaAbsUrl(this.element.src) : this.element.src || '';\n img.alt = '';\n img.draggable = false;\n wrap.appendChild(img);\n return wrap;\n }\n\n /** Embed a control's domNode + register destroy disposer. Returns a\n * section wrapper so callers get back a single child to append. */\n }, {\n key: \"_embedControl\",\n value: function _embedControl(control) {\n var section = document.createElement('div');\n section.className = 'bjs-ovl-image-resize-embed';\n if (control && control.domNode) {\n section.appendChild(control.domNode);\n }\n if (control) this._embeddedControls.push(control);\n return section;\n }\n }, {\n key: \"_renderAdvancedSection\",\n value: function _renderAdvancedSection() {\n var _this2 = this;\n var section = document.createElement('div');\n section.className = 'bjs-ovl-image-resize-advanced';\n var header = document.createElement('button');\n header.type = 'button';\n header.className = 'bjs-ovl-image-resize-advanced-toggle';\n header.setAttribute('aria-expanded', 'false');\n var chev = document.createElement('span');\n chev.className = 'material-symbols-rounded bjs-ovl-image-resize-advanced-chev';\n chev.textContent = 'chevron_right';\n var label = document.createElement('span');\n label.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_advanced', 'Advanced — max / min');\n header.appendChild(chev);\n header.appendChild(label);\n header.addEventListener('click', function (e) {\n e.preventDefault();\n var open = !section.classList.contains('is-open');\n section.classList.toggle('is-open', open);\n header.setAttribute('aria-expanded', open ? 'true' : 'false');\n });\n section.appendChild(header);\n var body = document.createElement('div');\n body.className = 'bjs-ovl-image-resize-advanced-body';\n var advConfig = [{\n key: 'max_width',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.max_width', 'Max Width'),\n units: ['px', '%', 'em', 'rem', 'vw']\n }, {\n key: 'max_height',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.max_height', 'Max Height'),\n units: ['px', '%', 'em', 'rem', 'vh']\n }, {\n key: 'min_width',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.min_width', 'Min Width'),\n units: ['px', '%', 'em', 'rem', 'vw']\n }, {\n key: 'min_height',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.min_height', 'Min Height'),\n units: ['px', '%', 'em', 'rem', 'vh']\n }];\n advConfig.forEach(function (cfg) {\n body.appendChild(_this2._embedControl(_this2.element.buildDimensionControl(cfg.label, cfg.key, cfg.units)));\n });\n section.appendChild(body);\n return section;\n }\n }, {\n key: \"_renderCropHint\",\n value: function _renderCropHint() {\n var banner = document.createElement('div');\n banner.className = 'bjs-ovl-image-crop-info bjs-ovl-image-resize-crop-hint';\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded bjs-ovl-image-crop-info-icon';\n icon.textContent = 'crop';\n var text = document.createElement('span');\n text.className = 'bjs-ovl-image-crop-info-text';\n var c = this.element.crop || {};\n text.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_crop_hint', \"Crop is on (\".concat(c.ratioX || '?', \":\").concat(c.ratioY || '?', \"). Resizing keeps the crop frame; the cropped area re-fits to your new dimensions.\"));\n banner.appendChild(icon);\n banner.appendChild(text);\n return banner;\n }\n }, {\n key: \"_renderFooter\",\n value: function _renderFooter() {\n var _this3 = this;\n var footer = document.createElement('div');\n footer.className = 'bjs-ovl-image-crop-footer';\n var cancel = document.createElement('button');\n cancel.type = 'button';\n cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n cancel.addEventListener('click', function (e) {\n e.preventDefault();\n _this3._cancel();\n });\n var apply = document.createElement('button');\n apply.type = 'button';\n apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n apply.addEventListener('click', function (e) {\n e.preventDefault();\n _this3._apply();\n });\n footer.appendChild(cancel);\n footer.appendChild(apply);\n return footer;\n }\n\n // ────────────────────────── State actions ─────────────────────────────\n }, {\n key: \"_isCropOn\",\n value: function _isCropOn() {\n return !!(this.element.crop && this.element.crop.enabled);\n }\n }, {\n key: \"_snapshotFormats\",\n value: function _snapshotFormats() {\n var f = this.element.formatter;\n return {\n width: f.getFormat('width'),\n height: f.getFormat('height'),\n max_width: f.getFormat('max_width'),\n max_height: f.getFormat('max_height'),\n min_width: f.getFormat('min_width'),\n min_height: f.getFormat('min_height')\n };\n }\n }, {\n key: \"_apply\",\n value: function _apply() {\n if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n }\n }, {\n key: \"_cancel\",\n value: function _cancel() {\n var f = this.element.formatter;\n Object.entries(this._snapshot || {}).forEach(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n k = _ref2[0],\n v = _ref2[1];\n f.setFormat(k, v);\n });\n if (typeof this.element.render === 'function') this.element.render();\n if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n }\n }]);\n}(_InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageResizeInlineOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageResizeInlineOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ImageResizePopoverOverlay.js":
/*!************************************************************!*\
!*** ./src/includes/overlays/ImageResizePopoverOverlay.js ***!
\************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageResizePopoverOverlay — 2026-04-19 (Phase E).\n *\n * Anchored popover variant of ImageResizeInlineOverlay. Embeds the same\n * DimensionControl factories (single source of truth for the input/\n * slider/unit UI), surrounded by anchored popover chrome instead of a\n * full-viewport modal mask. Mounted via `enterEditMode('resize-popover')`.\n *\n * Body composition mirrors the modal version:\n * 1. Width — embedded DimensionControl (sync-aware).\n * 2. Height — embedded DimensionControl.\n * 3. Aspect lock toggle — overlay-specific affordance.\n * 4. Crop-on hint banner (when element.crop.enabled).\n *\n * Advanced section + image preview omitted from the popover variant —\n * the popover is sized for quick edits without losing canvas context.\n * For deep editing (advanced max/min, preview), the modal popup is the\n * better fit.\n */\n\n\nvar ImageResizePopoverOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n function ImageResizePopoverOverlay() {\n _classCallCheck(this, ImageResizePopoverOverlay);\n return _callSuper(this, ImageResizePopoverOverlay, arguments);\n }\n _inherits(ImageResizePopoverOverlay, _AnchoredPopoverOverl);\n return _createClass(ImageResizePopoverOverlay, [{\n key: \"getEditMode\",\n value: function getEditMode() {\n return 'resize-popover';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(ImageResizePopoverOverlay, \"render\", this, 3)([]);\n this.domNode.classList.add('bjs-ovl-image-resize-popover');\n this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-image-resize-popover-title');\n this._snapshot = this._snapshotFormats();\n this._embeddedControls = [];\n this._aspectDisposer = null;\n this.domNode.appendChild(this._renderHeader());\n var body = document.createElement('div');\n body.className = 'bjs-ovl-image-resize-popover-body bjs-ovl-image-crop-body';\n\n // coupleAspect: true — width/height edits honor element._aspectLocked.\n body.appendChild(this._embedControl(this.element.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_width', 'Width'), 'width', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'], {\n coupleAspect: true\n })));\n body.appendChild(this._embedControl(this.element.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_height', 'Height'), 'height', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'], {\n coupleAspect: true\n })));\n var aspect = this.element.buildAspectLockRow({\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_aspect_lock', 'Lock aspect ratio')\n });\n body.appendChild(aspect.row);\n this._aspectDisposer = aspect.dispose;\n if (this._isCropOn()) body.appendChild(this._renderCropHint());\n this.domNode.appendChild(body);\n this.domNode.appendChild(this._renderFooter());\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n _superPropGet(ImageResizePopoverOverlay, \"beforeDestroy\", this, 3)([]);\n if (typeof this._aspectDisposer === 'function') {\n try {\n this._aspectDisposer();\n } catch (_) {/* no-op */}\n this._aspectDisposer = null;\n }\n if (Array.isArray(this._embeddedControls)) {\n var _iterator = _createForOfIteratorHelper(this._embeddedControls),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var c = _step.value;\n if (c && typeof c.destroy === 'function') {\n try {\n c.destroy();\n } catch (_) {/* no-op */}\n }\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n }\n this._embeddedControls = null;\n }\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var header = document.createElement('div');\n header.className = 'bjs-ovl-image-crop-header';\n var iconWrap = document.createElement('span');\n iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded';\n icon.textContent = 'open_in_full';\n iconWrap.appendChild(icon);\n var title = document.createElement('h3');\n title.className = 'bjs-ovl-image-crop-title';\n title.id = 'bjs-ovl-image-resize-popover-title';\n title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_title', 'Resize image');\n header.appendChild(iconWrap);\n header.appendChild(title);\n return header;\n }\n }, {\n key: \"_embedControl\",\n value: function _embedControl(control) {\n var section = document.createElement('div');\n section.className = 'bjs-ovl-image-resize-embed';\n if (control && control.domNode) section.appendChild(control.domNode);\n if (control) this._embeddedControls.push(control);\n return section;\n }\n }, {\n key: \"_renderCropHint\",\n value: function _renderCropHint() {\n var banner = document.createElement('div');\n banner.className = 'bjs-ovl-image-crop-info bjs-ovl-image-resize-crop-hint';\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded bjs-ovl-image-crop-info-icon';\n icon.textContent = 'crop';\n var text = document.createElement('span');\n text.className = 'bjs-ovl-image-crop-info-text';\n var c = this.element.crop || {};\n text.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_crop_hint', \"Crop is on (\".concat(c.ratioX || '?', \":\").concat(c.ratioY || '?', \"). Resizing keeps the crop frame; the cropped area re-fits to your new dimensions.\"));\n banner.appendChild(icon);\n banner.appendChild(text);\n return banner;\n }\n }, {\n key: \"_renderFooter\",\n value: function _renderFooter() {\n var _this = this;\n var footer = document.createElement('div');\n footer.className = 'bjs-ovl-image-crop-footer';\n var cancel = document.createElement('button');\n cancel.type = 'button';\n cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n cancel.addEventListener('click', function (e) {\n e.preventDefault();\n _this._cancel();\n });\n var apply = document.createElement('button');\n apply.type = 'button';\n apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n apply.addEventListener('click', function (e) {\n e.preventDefault();\n _this._apply();\n });\n footer.appendChild(cancel);\n footer.appendChild(apply);\n return footer;\n }\n }, {\n key: \"_isCropOn\",\n value: function _isCropOn() {\n return !!(this.element.crop && this.element.crop.enabled);\n }\n }, {\n key: \"_snapshotFormats\",\n value: function _snapshotFormats() {\n var f = this.element.formatter;\n return {\n width: f.getFormat('width'),\n height: f.getFormat('height')\n };\n }\n }, {\n key: \"_apply\",\n value: function _apply() {\n if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n }\n }, {\n key: \"_cancel\",\n value: function _cancel() {\n var f = this.element.formatter;\n Object.entries(this._snapshot || {}).forEach(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n k = _ref2[0],\n v = _ref2[1];\n return f.setFormat(k, v);\n });\n if (typeof this.element.render === 'function') this.element.render();\n if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n }\n }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageResizePopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageResizePopoverOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/InlineEditorOverlay.js":
/*!******************************************************!*\
!*** ./src/includes/overlays/InlineEditorOverlay.js ***!
\******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * InlineEditorOverlay — full-cover editor UI for `'edit'` trigger overlays.\n *\n * Use for modal-like inline editing on the canvas:\n * - Image inline crop (Phase 1.4)\n * - (future) inline alt-text editor, inline link editor\n *\n * Entered via element.enterEditMode(modeName) from a 'select'-trigger\n * overlay (e.g. ImageActionsOverlay's Crop button). Exited via:\n * - this.element.exitEditMode() from inside (Done/Confirm button)\n * - Escape keydown (auto-wired by this class)\n * - Element deselected / removed (framework cleanup)\n *\n * Base class wires:\n * - Escape key handler (document-level, cleaned up in beforeDestroy)\n * - pointer-events: auto on root (so full-cover mask catches clicks)\n *\n * Subclasses override render() to build the specific editor UI + call\n * super.render() first to get Escape wiring.\n */\n\nvar InlineEditorOverlay = /*#__PURE__*/function (_BaseOverlay) {\n function InlineEditorOverlay() {\n _classCallCheck(this, InlineEditorOverlay);\n return _callSuper(this, InlineEditorOverlay, arguments);\n }\n _inherits(InlineEditorOverlay, _BaseOverlay);\n return _createClass(InlineEditorOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'edit';\n }\n }, {\n key: \"render\",\n value: function render() {\n if (!this.domNode) {\n this.domNode = document.createElement('div');\n }\n this.domNode.classList.add('bjs-ovl-inline-editor');\n this.domNode.setAttribute('data-interactive', '');\n this.domNode.setAttribute('role', 'dialog');\n this.domNode.setAttribute('aria-modal', 'false'); // inline, not a true modal\n\n this._bindEscape();\n }\n\n /**\n * Override BaseOverlay.position() — inline editors are full-viewport modal\n * masks, NOT element-hug overlays. If we delegated to matchingDomNode()\n * (which sizes the node to the element's bounding rect), centering the\n * panel inside that rect overflows the viewport whenever the element sits\n * near a viewport edge (reported 2026-04-18: crop panel's header clipped\n * above the top of the window when the target image was near the top of\n * the canvas). Pinning to the viewport via `position: fixed; inset: 0`\n * keeps the internal flex centering relative to the window — identical\n * positioning semantics to a real `<dialog>` / .bjs-popup backdrop.\n *\n * Skipping matchingDomNode also means we don't install its iframe-scroll\n * / resize observers — which is correct here because a full-cover mask\n * never needs to re-anchor on scroll.\n */\n }, {\n key: \"position\",\n value: function position() {\n if (!this.domNode) return;\n Object.assign(this.domNode.style, {\n position: 'fixed',\n top: '0',\n left: '0',\n right: '0',\n bottom: '0',\n width: 'auto',\n height: 'auto'\n });\n }\n }, {\n key: \"_bindEscape\",\n value: function _bindEscape() {\n var _this = this;\n if (this._escapeBound) return;\n this._escapeBound = true;\n this._onKey = function (e) {\n if (e.key === 'Escape' || e.key === 'Esc') {\n e.preventDefault();\n try {\n _this.element.exitEditMode();\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[overlay] InlineEditorOverlay exit threw:', err);\n }\n }\n };\n document.addEventListener('keydown', this._onKey);\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n var _superPropGet2;\n if (this._onKey) {\n document.removeEventListener('keydown', this._onKey);\n this._onKey = null;\n this._escapeBound = false;\n }\n (_superPropGet2 = _superPropGet(InlineEditorOverlay, \"beforeDestroy\", this, 3)) === null || _superPropGet2 === void 0 || _superPropGet2([]);\n }\n }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InlineEditorOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/InlineEditorOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/LinkOnSelectionPopoverOverlay.js":
/*!****************************************************************!*\
!*** ./src/includes/overlays/LinkOnSelectionPopoverOverlay.js ***!
\****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\n/* harmony import */ var _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../LinkConfigControl.js */ \"./src/includes/LinkConfigControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * LinkOnSelectionPopoverOverlay — W1.3 (TEXT_INLINE_PLAN, 2026-04-24).\n *\n * NOT the existing `LinkPopoverOverlay` (which wraps the whole element's\n * href). This popover wraps JUST the selected text range in `<a>`.\n *\n * Mount pattern mirrors `TextColorPopoverOverlay` / `AIRewritePopoverOverlay`:\n * a lightweight non-`BaseOverlay` class, owned by the singleton\n * `TextInlineToolbarOverlay` (one popover per open cycle), mounted inside\n * `document.body`, anchored to the toolbar's Link button via\n * `ToolbarPositioner.attach`, disposed on toolbar unmount.\n *\n * HARD RULE T9 consequence #8 — anchor-wrap logic:\n * (a) selection fully OUTSIDE any `<a>` → `execCommand('createLink', url)`.\n * Browser's native surroundContents handles DOM validity; post-process\n * patches `target` / `rel` / `title` / `download` on the newly-created\n * anchor(s).\n * (b) selection fully INSIDE an existing `<a>` (non-host) → mutate attrs in\n * place; no execCommand. Removing the link unwraps the anchor.\n * (c) selection CROSSES anchor boundary → `execCommand('createLink', url)`\n * which the browser handles by splitting + re-wrapping. Post-process\n * patches non-href attrs. `unlink` covers the removal case same way.\n * (d) selection host IS an `<a>` (LinkElement) → mutate host attrs directly\n * (element-level link). Remove is DISABLED (unwrapping would break the\n * element — user must delete the element from canvas).\n *\n * Dual-view sync (HARD RULE T3): the popover body embeds the shared\n * `LinkConfigControl` — exact same class the sidebar Link tab uses. Future\n * W4.3 will extend that control (aria-label / referrerpolicy / UTM builder);\n * popover inherits those for free.\n *\n * Selection preservation (HARD RULE T1 / T2): the iframe selection range is\n * captured at open and restored immediately before the apply path runs, so\n * the user clicking into the popover's inputs never loses the range. Apply\n * writes via execCommand (engine-native range-split) + `InlineSanitizer.\n * normalize(host)` + `input` event dispatch + `tracker.refresh()` — caret\n * stable, round-trip invariant preserved.\n *\n * Failure-visible (HARD RULE T6): execCommand failures flash `.is-error` on\n * the Apply button; `hostIsAnchor` Remove attempt surfaces a sticky banner\n * instead of silently no-opping.\n */\n\n\n\n\n\nvar LinkOnSelectionPopoverOverlay = /*#__PURE__*/function () {\n /**\n * @param {TextInlineToolbarOverlay} toolbar — owner (shares selection\n * save/restore + iframe access).\n * @param {{ anchorBtn: HTMLElement }} opts\n */\n function LinkOnSelectionPopoverOverlay(toolbar, opts) {\n _classCallCheck(this, LinkOnSelectionPopoverOverlay);\n if (!toolbar || !opts || !opts.anchorBtn) {\n throw new Error('LinkOnSelectionPopoverOverlay: toolbar + opts.anchorBtn required');\n }\n this._toolbar = toolbar;\n this._builder = toolbar._builder;\n this._anchorBtn = opts.anchorBtn;\n this.domNode = null;\n this._linkControl = null;\n this._positionHandle = null;\n this._onDocKey = null;\n this._onDocMouseDown = null;\n this._mounted = false;\n\n // Selection at open time — captured before any input can steal focus\n // from the iframe (which would collapse the selection).\n this._savedRange = null;\n\n // Scope snapshot at open. Drives Remove-link visibility + Apply\n // routing. Re-computed at Apply time too (selection may have\n // shifted inside the popover interaction).\n this._scopeAtOpen = null;\n }\n\n /* ── public lifecycle ─────────────────────────────────────────── */\n return _createClass(LinkOnSelectionPopoverOverlay, [{\n key: \"open\",\n value: function open() {\n var _this = this;\n if (this._mounted) return;\n try {\n this._captureSelection();\n this._scopeAtOpen = this._resolveAnchorScope();\n this._build();\n document.body.appendChild(this.domNode);\n this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n anchor: function anchor() {\n return _this._anchorBtn.getBoundingClientRect();\n },\n target: this.domNode,\n offset: 8,\n collisionPadding: 12,\n preferredSide: 'below',\n flip: true\n });\n this._registerDismissListeners();\n this._mounted = true;\n this._anchorBtn.setAttribute('aria-expanded', 'true');\n // Defer focus — ToolbarPositioner needs one tick to measure.\n setTimeout(function () {\n return _this._focusFirstInput();\n }, 0);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[bjs:link-popover] open failed:', err);\n this.close();\n }\n }\n }, {\n key: \"close\",\n value: function close() {\n if (!this._mounted && !this.domNode) return;\n this._unregisterDismissListeners();\n if (this._positionHandle) {\n try {\n this._positionHandle.dispose();\n } catch (_) {}\n this._positionHandle = null;\n }\n if (this._linkControl && typeof this._linkControl.destroy === 'function') {\n try {\n this._linkControl.destroy();\n } catch (_) {}\n }\n this._linkControl = null;\n if (this.domNode && this.domNode.parentNode) {\n try {\n this.domNode.parentNode.removeChild(this.domNode);\n } catch (_) {}\n }\n this.domNode = null;\n this._mounted = false;\n this._savedRange = null;\n this._scopeAtOpen = null;\n try {\n this._anchorBtn.setAttribute('aria-expanded', 'false');\n } catch (_) {}\n }\n }, {\n key: \"isOpen\",\n value: function isOpen() {\n return this._mounted;\n }\n\n /* ── selection capture / restore ──────────────────────────────── */\n }, {\n key: \"_captureSelection\",\n value: function _captureSelection() {\n var payload = this._toolbar && this._toolbar._currentPayload;\n if (payload && payload.range) {\n this._savedRange = payload.range.cloneRange();\n return;\n }\n // Fallback — active selection inside iframe.\n try {\n var idoc = this._iframeDoc();\n var sel = idoc && idoc.defaultView && idoc.defaultView.getSelection();\n if (sel && sel.rangeCount > 0) {\n this._savedRange = sel.getRangeAt(0).cloneRange();\n }\n } catch (_) {\n this._savedRange = null;\n }\n }\n }, {\n key: \"_restoreSelection\",\n value: function _restoreSelection() {\n if (!this._savedRange) return false;\n try {\n var idoc = this._iframeDoc();\n var iwin = idoc && idoc.defaultView;\n if (!iwin) return false;\n var sel = iwin.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange);\n return true;\n } catch (_) {\n return false;\n }\n }\n }, {\n key: \"_iframeDoc\",\n value: function _iframeDoc() {\n return this._builder && this._builder.iframe && this._builder.iframe.contentDocument;\n }\n }, {\n key: \"_host\",\n value: function _host() {\n var payload = this._toolbar && this._toolbar._currentPayload;\n var idoc = this._iframeDoc();\n if (!idoc || !payload || !payload.elementUid) return null;\n return idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(payload.elementUid, \"\\\"]\"));\n }\n\n /* ── anchor scope detection ───────────────────────────────────── */\n\n /**\n * Introspect the saved range against the element host to classify the\n * selection into one of: OUTSIDE / INSIDE / CROSSING / HOST_IS_ANCHOR.\n * Returns a stable shape — all fields present even when not applicable.\n */\n }, {\n key: \"_resolveAnchorScope\",\n value: function _resolveAnchorScope() {\n var host = this._host();\n var range = this._savedRange;\n var result = {\n host: host,\n hostIsAnchor: false,\n anchorEl: null,\n insideAnchor: false,\n crossing: false,\n existingHref: '',\n existingTarget: '',\n existingRel: '',\n existingTitle: '',\n existingDownload: ''\n };\n if (!host || !range) return result;\n if (host.tagName === 'A') {\n result.hostIsAnchor = true;\n result.anchorEl = host;\n result.insideAnchor = true;\n result.existingHref = host.getAttribute('href') || '';\n result.existingTarget = host.getAttribute('target') || '';\n result.existingRel = host.getAttribute('rel') || '';\n result.existingTitle = host.getAttribute('title') || '';\n result.existingDownload = host.getAttribute('download') || '';\n result.existingAriaLabel = host.getAttribute('aria-label') || '';\n return result;\n }\n var startA = this._closestAnchor(range.startContainer, host);\n var endA = this._closestAnchor(range.endContainer, host);\n if (startA && endA && startA === endA) {\n this._seedFromAnchor(result, startA);\n result.insideAnchor = true;\n result.anchorEl = startA;\n return result;\n }\n if (startA || endA) {\n // One end inside an <a>, other end outside — or two different\n // anchors. Either way this is a crossing.\n result.crossing = true;\n // Seed fields from whichever anchor we found — reasonable default\n // if user wants to \"edit the link they're crossing out of\".\n this._seedFromAnchor(result, startA || endA);\n return result;\n }\n\n // Downward scan — covers the `selectNodeContents(host)` case where\n // the range's start/end containers are the host itself (so walking\n // UP never finds an anchor child). If the range intersects exactly\n // one anchor and the range's text is identical to that anchor's\n // textContent, the user effectively selected the whole anchor —\n // treat as INSIDE. If the range text spans beyond the anchor(s) or\n // touches >1 anchors, it's CROSSING.\n try {\n var allAnchors = Array.from(host.querySelectorAll('a[href]'));\n var intersecting = allAnchors.filter(function (a) {\n try {\n return range.intersectsNode(a);\n } catch (_) {\n return false;\n }\n });\n if (intersecting.length > 0) {\n var rangeText = range.toString();\n var singleAnchor = intersecting.length === 1 ? intersecting[0] : null;\n if (singleAnchor && rangeText.length > 0 && rangeText === singleAnchor.textContent) {\n this._seedFromAnchor(result, singleAnchor);\n result.insideAnchor = true;\n result.anchorEl = singleAnchor;\n } else {\n // Text extends past the anchor(s), or hits multiple.\n result.crossing = true;\n this._seedFromAnchor(result, intersecting[0]);\n }\n }\n } catch (_) {/* keep OUTSIDE default */}\n return result;\n }\n }, {\n key: \"_seedFromAnchor\",\n value: function _seedFromAnchor(result, a) {\n if (!a) return;\n result.existingHref = a.getAttribute('href') || '';\n result.existingTarget = a.getAttribute('target') || '';\n result.existingRel = a.getAttribute('rel') || '';\n result.existingTitle = a.getAttribute('title') || '';\n result.existingDownload = a.getAttribute('download') || '';\n result.existingAriaLabel = a.getAttribute('aria-label') || '';\n }\n }, {\n key: \"_closestAnchor\",\n value: function _closestAnchor(node, host) {\n var cur = node && node.nodeType === 1 ? node : node && node.parentElement;\n while (cur && cur !== host && cur !== host.parentElement) {\n if (cur.tagName === 'A') return cur;\n cur = cur.parentElement;\n }\n return null;\n }\n\n /* ── build DOM ────────────────────────────────────────────────── */\n }, {\n key: \"_build\",\n value: function _build() {\n var p = document.createElement('div');\n p.className = 'bjs-ovl bjs-ovl-link-on-selection-popover';\n p.setAttribute('role', 'dialog');\n p.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.title'));\n p.setAttribute('data-interactive', '');\n p.setAttribute('data-scope', this._scopeString(this._scopeAtOpen));\n\n // Preserve iframe selection on mousedown inside the popover body —\n // otherwise clicking the popover chrome would collapse the range.\n // Inputs/buttons still take focus normally via stopPropagation gates.\n p.addEventListener('mousedown', function (e) {\n var t = e.target;\n if (t && t.closest('input, textarea, select, button')) return;\n e.preventDefault();\n });\n p.appendChild(this._renderHeader());\n p.appendChild(this._renderBody());\n p.appendChild(this._renderFooter());\n this.domNode = p;\n }\n }, {\n key: \"_scopeString\",\n value: function _scopeString(scope) {\n if (!scope) return 'outside';\n if (scope.hostIsAnchor) return 'host-anchor';\n if (scope.crossing) return 'crossing';\n if (scope.insideAnchor) return 'inside';\n return 'outside';\n }\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var _this2 = this;\n var header = document.createElement('div');\n header.className = 'bjs-link-popover-header';\n var iconWrap = document.createElement('span');\n iconWrap.className = 'bjs-link-popover-header-icon';\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded';\n icon.textContent = 'link';\n icon.setAttribute('aria-hidden', 'true');\n iconWrap.appendChild(icon);\n var title = document.createElement('h3');\n title.className = 'bjs-link-popover-title';\n title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.title');\n header.appendChild(iconWrap);\n header.appendChild(title);\n\n // Remove-link chip — visible only when selection is inside an <a>.\n var scope = this._scopeAtOpen;\n if (scope && (scope.insideAnchor || scope.crossing)) {\n var chip = document.createElement('button');\n chip.type = 'button';\n chip.className = 'bjs-link-popover-remove';\n chip.setAttribute('data-action', 'remove');\n var chipIcon = document.createElement('span');\n chipIcon.className = 'material-symbols-rounded';\n chipIcon.textContent = 'link_off';\n chipIcon.setAttribute('aria-hidden', 'true');\n var chipText = document.createElement('span');\n chipText.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.remove');\n chip.appendChild(chipIcon);\n chip.appendChild(chipText);\n chip.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.remove'));\n if (scope.hostIsAnchor) {\n // Can't unlink without breaking the element — disable +\n // announce via tooltip why (HARD RULE T6).\n chip.classList.add('is-disabled');\n chip.setAttribute('aria-disabled', 'true');\n chip.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.remove_disabled_host_anchor'));\n chip.addEventListener('click', function (e) {\n e.preventDefault();\n _this2._flashBanner(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.remove_disabled_host_anchor'));\n });\n } else {\n chip.addEventListener('click', function (e) {\n e.preventDefault();\n _this2._removeLink();\n });\n }\n header.appendChild(chip);\n }\n return header;\n }\n }, {\n key: \"_renderBody\",\n value: function _renderBody() {\n var body = document.createElement('div');\n body.className = 'bjs-link-popover-body';\n var scope = this._scopeAtOpen;\n this._linkControl = new _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.title'), {\n url: scope ? scope.existingHref : '',\n target: scope ? scope.existingTarget : '',\n rel: scope ? scope.existingRel : '',\n title: scope ? scope.existingTitle : '',\n download: scope ? scope.existingDownload : '',\n ariaLabel: scope ? scope.existingAriaLabel : ''\n },\n // No-op callback — commits happen on Apply click, not field blur.\n // LinkConfigControl still validates on every change + paints\n // `.is-error` states, so the user gets live feedback without a\n // premature DOM write that would mid-edit the selection.\n {\n setLink: function setLink() {}\n }, null);\n body.appendChild(this._linkControl.domNode);\n\n // Banner slot for failure-visible messages (HARD RULE T6).\n this._banner = document.createElement('div');\n this._banner.className = 'bjs-link-popover-banner';\n this._banner.setAttribute('role', 'status');\n this._banner.setAttribute('aria-live', 'polite');\n this._banner.hidden = true;\n body.appendChild(this._banner);\n return body;\n }\n }, {\n key: \"_renderFooter\",\n value: function _renderFooter() {\n var _this3 = this;\n var footer = document.createElement('div');\n footer.className = 'bjs-link-popover-footer';\n var cancel = document.createElement('button');\n cancel.type = 'button';\n cancel.className = 'bjs-link-popover-btn bjs-link-popover-btn--secondary';\n cancel.setAttribute('data-action', 'cancel');\n cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.cancel');\n cancel.addEventListener('click', function (e) {\n e.preventDefault();\n _this3.close();\n });\n var apply = document.createElement('button');\n apply.type = 'button';\n apply.className = 'bjs-link-popover-btn bjs-link-popover-btn--primary';\n apply.setAttribute('data-action', 'apply');\n apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.apply');\n apply.addEventListener('click', function (e) {\n e.preventDefault();\n _this3._applyLink(apply);\n });\n footer.appendChild(cancel);\n footer.appendChild(apply);\n return footer;\n }\n }, {\n key: \"_focusFirstInput\",\n value: function _focusFirstInput() {\n if (!this.domNode) return;\n var input = this.domNode.querySelector('input[data-field=\"web.url\"], input[data-field=\"email.to\"], input[data-field=\"phone.number\"], input[data-field=\"anchor.id\"], .bjs-text-input');\n if (input) {\n try {\n input.focus();\n input.select && input.select();\n } catch (_) {}\n }\n }\n\n /* ── apply / remove ───────────────────────────────────────────── */\n }, {\n key: \"_applyLink\",\n value: function _applyLink(applyBtn) {\n var payload = this._linkControl && typeof this._linkControl.getValue === 'function' ? this._linkControl.getValue() : null;\n if (!payload) {\n this._flashButtonError(applyBtn);\n return;\n }\n // Validate errors already surfaced via LinkConfigControl's own UI.\n // If URL is empty post-validation, Apply becomes an implicit\n // \"remove link\" when selection is inside an anchor. Otherwise it's\n // a no-op (wrap with no href = invalid T9) — banner the user.\n if (!payload.url) {\n if (this._scopeAtOpen && (this._scopeAtOpen.insideAnchor || this._scopeAtOpen.crossing)) {\n this._removeLink();\n } else {\n this._flashBanner(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.err_empty_url'));\n }\n return;\n }\n var ok = this._doWriteAnchor(payload);\n if (!ok) {\n this._flashButtonError(applyBtn);\n return;\n }\n this.close();\n }\n }, {\n key: \"_removeLink\",\n value: function _removeLink() {\n var scope = this._resolveAnchorScope();\n if (scope.hostIsAnchor) {\n // Defensive — UI should already prevent this.\n this._flashBanner(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.remove_disabled_host_anchor'));\n return;\n }\n var host = scope.host;\n if (!host) return;\n var restored = this._restoreSelection();\n if (!restored) return;\n var idoc = this._iframeDoc();\n var ok = false;\n try {\n ok = idoc.execCommand('unlink', false, null);\n } catch (_) {\n ok = false;\n }\n if (!ok) {\n // Fallback — manual unwrap of the known anchor.\n if (scope.anchorEl && scope.anchorEl.parentNode) {\n try {\n while (scope.anchorEl.firstChild) {\n scope.anchorEl.parentNode.insertBefore(scope.anchorEl.firstChild, scope.anchorEl);\n }\n scope.anchorEl.parentNode.removeChild(scope.anchorEl);\n ok = true;\n } catch (_) {\n ok = false;\n }\n }\n }\n if (!ok) {\n this._flashBanner(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.err_remove_failed'));\n return;\n }\n this._postWrite(host);\n this.close();\n }\n\n /**\n * @param {{url, target, rel, title, download}} payload\n * @returns {boolean} success\n */\n }, {\n key: \"_doWriteAnchor\",\n value: function _doWriteAnchor(payload) {\n var _this4 = this;\n var scope = this._resolveAnchorScope();\n var host = scope.host;\n if (!host) return false;\n var restored = this._restoreSelection();\n if (!restored) return false;\n var idoc = this._iframeDoc();\n if (!idoc) return false;\n try {\n if (scope.hostIsAnchor) {\n // LinkElement — mutate host attrs only. Don't try to wrap\n // (would nest); don't unwrap (would destroy the element).\n this._setAnchorAttrs(host, payload);\n // Push through the element's link setter so Formatter /\n // serializer / sidebar stay in sync. LinkElement exposes\n // `setLink({url, target, rel, title, download})`.\n var el = this._resolveElement(host);\n if (el && typeof el.setLink === 'function') {\n try {\n el.setLink(payload);\n } catch (_) {}\n }\n } else if (scope.insideAnchor && !scope.crossing) {\n // Case (b) — edit in place.\n if (scope.anchorEl) {\n this._setAnchorAttrs(scope.anchorEl, payload);\n }\n } else {\n // Case (a) — outside, or case (c) — crossing.\n // Use browser-native createLink to handle range surround +\n // split. `document.execCommand` returns false on unsupported\n // / empty-selection; fall back to manual surroundContents\n // for the outside case.\n var createdOk = false;\n try {\n createdOk = idoc.execCommand('createLink', false, payload.url);\n } catch (_) {\n createdOk = false;\n }\n if (!createdOk) {\n if (!scope.crossing) {\n // OUTSIDE — try manual wrap.\n var a = idoc.createElement('a');\n this._setAnchorAttrs(a, payload);\n try {\n this._savedRange.surroundContents(a);\n createdOk = true;\n } catch (_) {\n createdOk = false;\n }\n }\n }\n if (!createdOk) return false;\n\n // Patch non-href attrs onto whatever anchors now carry the\n // target href inside the host. createLink only sets href;\n // target/rel/title/download must be written after.\n var matches = host.querySelectorAll('a[href]');\n matches.forEach(function (a) {\n if ((a.getAttribute('href') || '') === payload.url) {\n _this4._setAnchorAttrs(a, payload);\n }\n });\n }\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[bjs:link-popover] write failed:', err);\n return false;\n }\n this._postWrite(host);\n return true;\n }\n }, {\n key: \"_setAnchorAttrs\",\n value: function _setAnchorAttrs(a, payload) {\n if (!a) return;\n if (payload.url) a.setAttribute('href', payload.url);else a.removeAttribute('href');\n if (payload.target) a.setAttribute('target', payload.target);else a.removeAttribute('target');\n if (payload.rel) a.setAttribute('rel', payload.rel);else a.removeAttribute('rel');\n if (payload.title) a.setAttribute('title', payload.title);else a.removeAttribute('title');\n if (payload.download) a.setAttribute('download', payload.download);else a.removeAttribute('download');\n\n // W4.3 — optional a11y override surviving round-trip.\n if (payload.ariaLabel) a.setAttribute('aria-label', payload.ariaLabel);else a.removeAttribute('aria-label');\n }\n }, {\n key: \"_resolveElement\",\n value: function _resolveElement(host) {\n if (!host) return null;\n var uid = host.getAttribute('data-bjs-inline-text');\n if (!uid) return null;\n var uiMgr = this._builder && this._builder.uiManager;\n if (!uiMgr || !Array.isArray(uiMgr.elements)) return null;\n return uiMgr.elements.find(function (el) {\n return el && el.id === uid;\n }) || null;\n }\n\n /**\n * Post-write housekeeping — canonicalize markup, fire input event so\n * W0.2b's auto-wired `setText` picks up the new HTML, refresh tracker\n * so toolbar button states re-read. Shared by both wrap/edit paths and\n * the remove-link path.\n */\n }, {\n key: \"_postWrite\",\n value: function _postWrite(host) {\n if (!host) return;\n try {\n _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].normalize(host);\n } catch (_) {}\n try {\n var idoc = this._iframeDoc();\n if (idoc) {\n host.dispatchEvent(new idoc.defaultView.Event('input', {\n bubbles: true\n }));\n }\n } catch (_) {}\n try {\n var tracker = this._builder && this._builder.textSelectionTracker;\n if (tracker && typeof tracker.refresh === 'function') tracker.refresh();\n } catch (_) {}\n }\n\n /* ── error surfacing (HARD RULE T6) ───────────────────────────── */\n }, {\n key: \"_flashButtonError\",\n value: function _flashButtonError(btn) {\n if (!btn) return;\n btn.classList.add('is-error');\n setTimeout(function () {\n return btn.classList.remove('is-error');\n }, 600);\n }\n }, {\n key: \"_flashBanner\",\n value: function _flashBanner(msg) {\n if (!this._banner) return;\n this._banner.textContent = msg;\n this._banner.hidden = false;\n this._banner.classList.add('is-visible');\n }\n\n /* ── dismissal ────────────────────────────────────────────────── */\n }, {\n key: \"_registerDismissListeners\",\n value: function _registerDismissListeners() {\n var _this5 = this;\n this._onDocKey = function (e) {\n if (e.key === 'Escape') {\n e.stopPropagation();\n _this5.close();\n }\n };\n document.addEventListener('keydown', this._onDocKey, true);\n this._onDocMouseDown = function (e) {\n if (!_this5.domNode) return;\n var t = e.target;\n if (_this5.domNode.contains(t)) return;\n if (t && _this5._anchorBtn && _this5._anchorBtn.contains(t)) return;\n _this5.close();\n };\n // Defer one tick — the click that OPENED this popover mustn't be\n // picked up by the outside-click handler (would close immediately).\n setTimeout(function () {\n if (_this5._mounted) document.addEventListener('mousedown', _this5._onDocMouseDown, true);\n }, 0);\n }\n }, {\n key: \"_unregisterDismissListeners\",\n value: function _unregisterDismissListeners() {\n if (this._onDocKey) {\n document.removeEventListener('keydown', this._onDocKey, true);\n this._onDocKey = null;\n }\n if (this._onDocMouseDown) {\n document.removeEventListener('mousedown', this._onDocMouseDown, true);\n this._onDocMouseDown = null;\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LinkOnSelectionPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/LinkOnSelectionPopoverOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/LinkPopoverOverlay.js":
/*!*****************************************************!*\
!*** ./src/includes/overlays/LinkPopoverOverlay.js ***!
\*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * LinkPopoverOverlay — 2026-04-19.\n *\n * Anchored popover for editing an element's link without taking over the\n * viewport with a modal. Embeds the REAL control the sidebar uses — not a\n * hand-rolled mini version — so the popover and sidebar stay in lock-step\n * via the dual-view sync bus (SA I13 subscribe/readState).\n *\n * Pattern mirrors ImageCropPopoverOverlay / ImageResizePopoverOverlay /\n * ImageEffectPopoverOverlay:\n *\n * - Shared `.bjs-ovl-anchored-popover` shell (Esc + outside-click + smart-\n * flip anchoring). No custom chrome here, just header + body + footer.\n * - Body = `this.element.buildLinkControl().domNode`. Factory returns a\n * fresh LinkConfigControl / LinkInputControl instance wired to the\n * element via subscribe/readState. Opening the popover does NOT clone\n * state into the popover — it binds the popover to the same source of\n * truth (the element), so every keystroke propagates to the sidebar\n * control without manual bridging.\n * - Snapshot on mount → Cancel reverts via one `setLink()` call, which\n * fires `applyLinkAttrs()` + `notifySyncListeners()` so every live\n * control snaps back in place.\n *\n * Surface flip: keep both `BuilderjsPopup.prompt` + this popover in reach.\n * ImageActionsOverlay / ButtonActionsOverlay each expose a SURFACE_MODE\n * map; set SURFACE_MODE.link = 'popup' and restore the legacy prompt call\n * to revert — no code deletion required, the popover stays registered but\n * dormant (edit-mode 'link-popover' is never entered).\n *\n * See docs/core/OVERLAY.md §7.5 + BUILDER.md Lesson 39.\n */\n\n\nvar LinkPopoverOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n function LinkPopoverOverlay() {\n _classCallCheck(this, LinkPopoverOverlay);\n return _callSuper(this, LinkPopoverOverlay, arguments);\n }\n _inherits(LinkPopoverOverlay, _AnchoredPopoverOverl);\n return _createClass(LinkPopoverOverlay, [{\n key: \"getEditMode\",\n value: function getEditMode() {\n return 'link-popover';\n }\n }, {\n key: \"render\",\n value: function render() {\n _superPropGet(LinkPopoverOverlay, \"render\", this, 3)([]);\n this.domNode.classList.add('bjs-ovl-link-popover');\n this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-link-popover-title');\n\n // Snapshot so Cancel / Esc reverts via one setLink round-trip.\n // Reads whatever fields the element carries — url for everything,\n // target + rel + title + download on ButtonElement, just url +\n // target on ImageElement. The element's own setLink callback\n // picks off the fields it cares about.\n this._snapshot = {\n url: this.element.url || '',\n target: this.element.target || '',\n rel: this.element.rel || '',\n title: this.element.title || '',\n download: this.element.download || ''\n };\n this._embedded = null;\n this.domNode.appendChild(this._renderHeader());\n var body = document.createElement('div');\n body.className = 'bjs-ovl-link-popover-body';\n\n // Embed the real control — same class as the sidebar, wired to the\n // element via subscribe/readState. Sidebar + popover see the same\n // source of truth (the element); there is no separate \"popover\n // state\" to keep in sync.\n this._embedded = this.element.buildLinkControl();\n if (this._embedded && this._embedded.domNode) {\n body.appendChild(this._embedded.domNode);\n }\n this.domNode.appendChild(body);\n this.domNode.appendChild(this._renderFooter());\n }\n }, {\n key: \"afterMount\",\n value: function afterMount() {\n // Focus the first text input inside the embedded control so Enter\n // / Esc feel natural without a click. Works for both LinkConfig\n // (first [data-field=\"web.url\"]) and LinkInputControl (first\n // [name=\"link-url\"]).\n if (!this.domNode) return;\n var input = this.domNode.querySelector('[data-field=\"web.url\"], [name=\"link-url\"], .bjs-text-input');\n if (input) {\n try {\n input.focus();\n input.select && input.select();\n } catch (_) {/* no-op on detached / weird DOM */}\n }\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n _superPropGet(LinkPopoverOverlay, \"beforeDestroy\", this, 3)([]);\n // Dispose the embedded control's subscription so it stops reacting\n // to element mutations after the popover closes. Without this the\n // popover's control stays subscribed to a detached DOM (SA I13c).\n if (this._embedded && typeof this._embedded.destroy === 'function') {\n try {\n this._embedded.destroy();\n } catch (_) {/* no-op */}\n }\n this._embedded = null;\n }\n }, {\n key: \"_renderHeader\",\n value: function _renderHeader() {\n var header = document.createElement('div');\n header.className = 'bjs-ovl-image-crop-header';\n var iconWrap = document.createElement('span');\n iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded';\n icon.textContent = 'link';\n iconWrap.appendChild(icon);\n var title = document.createElement('h3');\n title.className = 'bjs-ovl-image-crop-title';\n title.id = 'bjs-ovl-link-popover-title';\n title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.link', 'Link');\n header.appendChild(iconWrap);\n header.appendChild(title);\n return header;\n }\n }, {\n key: \"_renderFooter\",\n value: function _renderFooter() {\n var _this = this;\n var footer = document.createElement('div');\n footer.className = 'bjs-ovl-image-crop-footer';\n var cancel = document.createElement('button');\n cancel.type = 'button';\n cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n cancel.addEventListener('click', function (e) {\n e.preventDefault();\n _this._cancel();\n });\n var apply = document.createElement('button');\n apply.type = 'button';\n apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n apply.addEventListener('click', function (e) {\n e.preventDefault();\n _this._apply();\n });\n footer.appendChild(cancel);\n footer.appendChild(apply);\n return footer;\n }\n }, {\n key: \"_apply\",\n value: function _apply() {\n // Live edits have already flowed through the embedded control's\n // debounced input → element.setLink → notifySyncListeners path.\n // Apply is just \"close the popover\".\n if (this.element && typeof this.element.exitEditMode === 'function') {\n this.element.exitEditMode();\n }\n }\n }, {\n key: \"_cancel\",\n value: function _cancel() {\n // Revert to snapshot. Prefer the element's own setter (keeps\n // derived logic — applyLinkAttrs + sync notify — consistent with\n // any other setLink callsite). Falls back to direct assign + render\n // for elements whose setter signature doesn't match the Button/\n // Image contract.\n if (!this.element) return;\n var s = this._snapshot || {};\n var controls = this.element.getControls ? null : null; // kept for reference\n // ButtonElement's link control callback takes `{ url, target, rel, title, download }`;\n // ImageElement's LinkInputControl callback takes `(url, target)`. The\n // element's buildLinkControl factory wires both shapes — we just set\n // the element fields directly here (they're the source of truth)\n // + run applyLinkAttrs OR render, same as the factory callback.\n this.element.url = s.url;\n this.element.target = s.target;\n if ('rel' in this.element) this.element.rel = s.rel;\n if ('title' in this.element) this.element.title = s.title;\n if ('download' in this.element) this.element.download = s.download;\n if (typeof this.element.applyLinkAttrs === 'function') {\n this.element.applyLinkAttrs();\n } else if (typeof this.element.render === 'function') {\n this.element.render();\n }\n if (typeof this.element.exitEditMode === 'function') {\n this.element.exitEditMode();\n }\n }\n }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LinkPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/LinkPopoverOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/NativeDragHandleOverlay.js":
/*!**********************************************************!*\
!*** ./src/includes/overlays/NativeDragHandleOverlay.js ***!
\**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * NativeDragHandleOverlay — HTML5 DnD drag handle primitive.\n *\n * Counterpart to DraggableHandleOverlay. Use this ONLY when the gesture\n * must produce native `dragstart → dragover → drop` events that feed into\n * existing HTML5 DnD pipelines (UIManager.dragOver / drop). Block drag\n * anchor is the canonical example (Phase 1.6).\n *\n * The grabber (typically an inner <span draggable=\"true\">) fires `dragstart`.\n * Pointer events (pointerdown/move/up) are NOT used — they're suppressed\n * by the browser once dragstart fires. Do NOT mix with setPointerCapture.\n *\n * Preserves Safari drag-ghost 3-layer workaround (SA invariant I3 + BUILDER.md\n * Lesson 11) — without these, Safari emits blank drag ghosts when the source\n * is inside an overflow:hidden ancestor:\n * Layer 1: dataTransfer.setData('text/plain', '')\n * Layer 2: dataTransfer.effectAllowed = 'all'\n * Layer 3: off-screen clone at left:-10000px for Safari-only setDragImage\n *\n * Subclasses override:\n * - _buildHandle() — populate this.domNode with draggable=\"true\" grabber\n * - onDragStart(e) — hook into UIManager.addDraggableItem() pipeline\n */\n\nvar NativeDragHandleOverlay = /*#__PURE__*/function (_BaseOverlay) {\n function NativeDragHandleOverlay() {\n _classCallCheck(this, NativeDragHandleOverlay);\n return _callSuper(this, NativeDragHandleOverlay, arguments);\n }\n _inherits(NativeDragHandleOverlay, _BaseOverlay);\n return _createClass(NativeDragHandleOverlay, [{\n key: \"render\",\n value: function render() {\n var _this = this;\n if (!this.domNode) {\n this.domNode = document.createElement('div');\n }\n this.domNode.classList.add('bjs-ovl-native-handle');\n // Functional handles MUST escape canvas-clip — block drag anchor\n // explicitly protrudes past the element right edge by 2 px so the\n // user can grab \"outside\" the block. Clipping at canvas edge would\n // hide the handle when a block sits at canvas right edge.\n // See OVERLAY.md §24 Canvas-clip contract.\n this.domNode.classList.add('bjs-ovl-no-clip');\n this.domNode.setAttribute('data-interactive', '');\n\n // Subclass populates the grabber.\n this._buildHandle();\n\n // dragstart bubbles from the inner draggable grabber.\n this.domNode.addEventListener('dragstart', function (e) {\n return _this._onNativeDragStart(e);\n });\n }\n }, {\n key: \"_onNativeDragStart\",\n value: function _onNativeDragStart(e) {\n e.stopPropagation();\n\n // HTML5 DnD requires setData + effectAllowed for Safari compatibility.\n try {\n e.dataTransfer.setData('text/plain', '');\n e.dataTransfer.effectAllowed = 'all';\n } catch (_) {\n // Non-fatal on some browsers/contexts.\n }\n\n // Safari drag-ghost 3-layer workaround (SA invariant I3).\n // Chrome handles default drag-image capture fine — do NOT setDragImage\n // on Chrome (can interact badly with ancestor transforms).\n var ua = typeof navigator !== 'undefined' && navigator.userAgent || '';\n var isSafari = /safari/i.test(ua) && !/chrome|chromium|crios|android/i.test(ua);\n if (isSafari && e.dataTransfer && typeof e.dataTransfer.setDragImage === 'function') {\n try {\n var clone = this.domNode.cloneNode(true);\n Object.assign(clone.style, {\n position: 'fixed',\n top: '0',\n left: '-10000px',\n // off-screen but rendered\n pointerEvents: 'none',\n // don't block real pointer input\n opacity: '0.95',\n zIndex: '-1'\n });\n document.body.appendChild(clone);\n var rect = this.domNode.getBoundingClientRect();\n e.dataTransfer.setDragImage(clone, rect.width / 2, rect.height / 2);\n // Remove clone after Safari has captured (sync in dragstart, so\n // microtask-0 is enough).\n setTimeout(function () {\n if (clone.parentNode) clone.parentNode.removeChild(clone);\n }, 0);\n } catch (_) {\n // Non-fatal — fall back to browser default drag-image.\n }\n }\n\n // Subclass hook to wire into UIManager pipeline.\n try {\n this.onDragStart(e);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[overlay] NativeDragHandleOverlay.onDragStart threw:', err);\n }\n }\n\n /** Subclass populates this.domNode with a grabber that has draggable=\"true\".\n * Example: `this.domNode.innerHTML = '<span draggable=\"true\">...</span>';`\n * Framework does NOT auto-set draggable on this.domNode because the\n * intended grabber is usually a specific inner element. */\n }, {\n key: \"_buildHandle\",\n value: function _buildHandle() {\n // Default: make the root itself draggable. Subclasses typically override\n // to put the draggable attribute on an inner grabber span.\n this.domNode.setAttribute('draggable', 'true');\n }\n\n /** Subclass hook — called after Safari workaround is applied. Typical\n * implementation hands off to UIManager.addDraggableItem(...) or similar. */\n }, {\n key: \"onDragStart\",\n value: function onDragStart(/* e */) {}\n }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (NativeDragHandleOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/NativeDragHandleOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/PaddingVisualizerOverlay.js":
/*!***********************************************************!*\
!*** ./src/includes/overlays/PaddingVisualizerOverlay.js ***!
\***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./StructureVisualizerOverlay.js */ \"./src/includes/overlays/StructureVisualizerOverlay.js\");\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ui/holedBoxClipPath.js */ \"./src/includes/ui/holedBoxClipPath.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * PaddingVisualizerOverlay — inset guides + per-side region fills that\n * visualise the 4 padding sides of a container element.\n *\n * PLAN_EFFECT W0.2. Implements D4 (Hybrid) + D5 (edge tick marks):\n * - Quiet state (default, every side): 1px dashed inset guide at the\n * inner padding boundary. 10–45 % alpha accent. Constant passive\n * affordance when an element is selected.\n * - Focused state (one side at a time): 22 % alpha fill + solid inner\n * border. Triggered by `region:focus` on `builder.events` with\n * matching `elementUid`. Subsequent `region:blur` reverts to quiet.\n * - Label + ruler tick marks land in W3.3 + W3.4 (this primitive\n * already exposes `data-region` hooks those items will extend).\n *\n * Contract:\n * - trigger: 'select'. Owner element decides whether to return this\n * overlay from getOverlays() (consumer wiring = W3.1 + W3.5 + W3.6).\n * - Reads `padding_top` / `padding_right` / `padding_bottom` /\n * `padding_left` from `element.formatter`. Non-numeric / null values\n * collapse to 0 (region hidden).\n * - Structure-preserving: first layoutChildren() builds 4 <div>s once;\n * subsequent reflows patch `left/top/width/height/display` in place.\n * No innerHTML churn on every reflow (I5).\n * - Observer cleanup: BaseOverlay.destroy() disconnects\n * MutationObserver + ResizeObserver via matchingDomNode. Our\n * beforeDestroy() additionally disposes bus subscribers (I3).\n *\n * Not part of this primitive (handled elsewhere):\n * - getOverlays() wiring on BlockElement / CellElement / PageElement\n * (W3.1 / W3.5 / W3.6, flag-gated by `usePaddingVisualizer`).\n * - PaddingMarginControl → bus emit on input focus/blur (W3.2).\n * - Dim-label sub-primitive (W3.3).\n * - Ruler tick marks (W3.4).\n */\n\n\n\nvar REGION_KEYS = ['padding-top', 'padding-right', 'padding-bottom', 'padding-left'];\nvar PaddingVisualizerOverlay = /*#__PURE__*/function (_StructureVisualizerO) {\n /**\n * @param {BaseElement} element\n * @param {object} opts\n * @param {string} [opts.namespace='padding'] — W3.6. Bus\n * filter scope. Default matches the 5 legacy\n * events (region:focus/blur, panel-focus/blur,\n * padding:pin/unpin). A non-default namespace\n * (e.g. 'block_padding') scopes the overlay\n * to a different control instance on the same\n * element — lets PageElement run two\n * independent padding controls without the\n * bus events cross-talking.\n * @param {object} [opts.keys] — W3.6. If\n * provided, read padding values from these\n * keys on the element itself (e.g.\n * `{ top: 'block_padding_top', … }`) instead\n * of from `element.formatter.getFormat('padding_*')`.\n * Matches PageElement.block_padding_* which\n * lives as instance props, not in the formatter.\n * @param {Function} [opts.readSide] — W3.7. Most\n * flexible value source: `(side) => number`,\n * called with 'top'/'right'/'bottom'/'left'.\n * Takes precedence over both `opts.keys` and\n * the formatter fallback. Used by BlockElement\n * to cascade to page.block_padding_* when\n * the Block's own formatter value is null.\n */\n function PaddingVisualizerOverlay(element) {\n var _this;\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n _classCallCheck(this, PaddingVisualizerOverlay);\n _this = _callSuper(this, PaddingVisualizerOverlay, [element, opts]);\n _this.namespace = opts.namespace || 'padding';\n _this.keys = opts.keys || null;\n _this.readSide = typeof opts.readSide === 'function' ? opts.readSide : null;\n _this._busDisposers = [];\n _this._regionNodes = null; // built lazily in layoutChildren\n // State drivers — recomputed by _recomputeAllStates() whenever any\n // of these flip.\n _this._panelFocused = false; // region:panel-focus held\n _this._sideFocused = null; // which regionKey has focus, if any\n _this._pinned = false; // Set membership cache\n return _this;\n }\n _inherits(PaddingVisualizerOverlay, _StructureVisualizerO);\n return _createClass(PaddingVisualizerOverlay, [{\n key: \"getTrigger\",\n value: function getTrigger() {\n return 'select';\n }\n }, {\n key: \"render\",\n value: function render() {\n if (!this.domNode) {\n this.domNode = document.createElement('div');\n }\n this.domNode.classList.add('bjs-ovl-padding');\n // StructureVisualizerOverlay sets pointer-events: none on the root\n // via CSS; belt-and-suspenders here for clarity.\n this.domNode.style.pointerEvents = 'none';\n }\n }, {\n key: \"afterMount\",\n value: function afterMount() {\n var _this$host$options,\n _this$host,\n _this$host2,\n _this2 = this;\n // Resolve host. `BaseElement.mountOverlays()` assigns\n // `overlay.host = element.host` before mount(), but tests\n // sometimes construct + mount the overlay directly. As a\n // fallback, read the host off the owned element.\n if (!this.host && this.element && this.element.host) {\n this.host = this.element.host;\n }\n\n // Self-skip when host's `usePaddingVisualizer` flag is off.\n // Originally gated at parse-time in CellElement / PageElement /\n // BlockElement getOverlays(); commit 6 moves the gate here so\n // those parse-time global reach-ins can drop out entirely\n // (parse runs before _adopt — host is null then).\n //\n // No host AT ALL → mount under \"primitive test\" semantics\n // (e.g. e2e/padding-visualizer-overlay.spec.js exercising\n // shape + bus wiring without a Builder). Treat absent host as\n // \"flag is on\" so the primitive itself stays testable.\n if (this.host && ((_this$host$options = this.host.options) === null || _this$host$options === void 0 ? void 0 : _this$host$options.usePaddingVisualizer) !== true) {\n try {\n this.destroy();\n } catch (_) {/* not yet mounted */}\n return;\n }\n\n // Bus + pin set come from the owning Builder via host injection\n // (W3.6: pinKey includes namespace so Page's two padding\n // controls pin independently). When no host is wired, leave\n // both null — primitive renders quiet state, no bus traffic.\n var bus = ((_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events) || null;\n var pinSet = ((_this$host2 = this.host) === null || _this$host2 === void 0 ? void 0 : _this$host2._pinnedPaddingElements) || null;\n if (pinSet && typeof pinSet.has === 'function') {\n this._pinned = pinSet.has(this._pinKey());\n }\n if (bus) {\n this._busDisposers.push(bus.on('region:panel-focus', function (p) {\n return _this2._onPanelFocus(p);\n }));\n this._busDisposers.push(bus.on('region:panel-blur', function (p) {\n return _this2._onPanelBlur(p);\n }));\n this._busDisposers.push(bus.on('region:focus', function (p) {\n return _this2._onSideFocus(p);\n }));\n this._busDisposers.push(bus.on('region:blur', function (p) {\n return _this2._onSideBlur(p);\n }));\n this._busDisposers.push(bus.on('padding:pin', function (p) {\n return _this2._onPin(p);\n }));\n this._busDisposers.push(bus.on('padding:unpin', function (p) {\n return _this2._onUnpin(p);\n }));\n }\n\n // Apply pin-derived state immediately so the overlay shows its\n // initial visual (e.g. a pinned-then-reselected element renders\n // rich right away without waiting for a bus event).\n this._recomputeAllStates();\n }\n }, {\n key: \"_pinKey\",\n value: function _pinKey() {\n // Back-compat: default namespace uses the bare UID (pre-W3.6\n // Map members — existing tests still pass). Non-default\n // namespace composes a distinct key.\n return this.namespace === 'padding' ? this.element.id : \"\".concat(this.element.id, \"::\").concat(this.namespace);\n }\n }, {\n key: \"beforeDestroy\",\n value: function beforeDestroy() {\n var _iterator = _createForOfIteratorHelper(this._busDisposers),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var dispose = _step.value;\n try {\n dispose();\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].error('PaddingVisualizerOverlay:dispose', err);\n }\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n this._busDisposers = [];\n this._regionNodes = null;\n }\n }, {\n key: \"_isMine\",\n value: function _isMine(payload) {\n if (!payload || payload.elementUid !== this.element.id) return false;\n // W3.6 — match namespace. Absent namespace defaults to\n // 'padding' (back-compat with callers that predate this field).\n var ns = payload.namespace || 'padding';\n return ns === this.namespace;\n }\n }, {\n key: \"_onPanelFocus\",\n value: function _onPanelFocus(payload) {\n if (!this._isMine(payload)) return;\n if (this._panelFocused) return;\n this._panelFocused = true;\n this._recomputeAllStates();\n }\n }, {\n key: \"_onPanelBlur\",\n value: function _onPanelBlur(payload) {\n if (!this._isMine(payload)) return;\n if (!this._panelFocused) return;\n this._panelFocused = false;\n this._recomputeAllStates();\n }\n }, {\n key: \"_onSideFocus\",\n value: function _onSideFocus(payload) {\n if (!this._isMine(payload)) return;\n if (!REGION_KEYS.includes(payload.regionKey)) return;\n if (this._sideFocused === payload.regionKey) return;\n this._sideFocused = payload.regionKey;\n this._recomputeAllStates();\n }\n }, {\n key: \"_onSideBlur\",\n value: function _onSideBlur(payload) {\n if (!this._isMine(payload)) return;\n if (!REGION_KEYS.includes(payload.regionKey)) return;\n if (this._sideFocused !== payload.regionKey) return;\n this._sideFocused = null;\n this._recomputeAllStates();\n }\n }, {\n key: \"_onPin\",\n value: function _onPin(payload) {\n if (!this._isMine(payload)) return;\n if (this._pinned) return;\n this._pinned = true;\n this._recomputeAllStates();\n }\n }, {\n key: \"_onUnpin\",\n value: function _onUnpin(payload) {\n if (!this._isMine(payload)) return;\n if (!this._pinned) return;\n this._pinned = false;\n this._recomputeAllStates();\n }\n\n /**\n * Per-side state ladder (highest priority wins):\n * 1. rich-focused — side's input is currently focused\n * 2. rich-pinned — user pinned this element via the toggle\n * 3. rich-grouped — panel has any focused input\n * 4. quiet — default\n *\n * On every flip we recompute ALL 4 sides in one pass so the DOM stays\n * canonical (no partial updates, no stale states).\n */\n }, {\n key: \"_recomputeAllStates\",\n value: function _recomputeAllStates() {\n if (!this._regionNodes) return;\n for (var _i = 0, _REGION_KEYS = REGION_KEYS; _i < _REGION_KEYS.length; _i++) {\n var regionKey = _REGION_KEYS[_i];\n var node = this._regionNodes[regionKey];\n if (!node) continue;\n var state = void 0;\n if (this._sideFocused === regionKey) state = 'rich-focused';else if (this._pinned) state = 'rich-pinned';else if (this._panelFocused) state = 'rich-grouped';else state = 'quiet';\n if (node.dataset.state !== state) node.dataset.state = state;\n }\n // Hatch-box pattern follows pin state (hatch ↔ dots). Cheap class\n // toggle, no layout thrash.\n this._syncHatchMode();\n }\n\n /**\n * StructureVisualizerOverlay's position() wires us into every reflow.\n * Read current padding + resize/position the 4 region divs in place.\n */\n }, {\n key: \"layoutChildren\",\n value: function layoutChildren() {\n var _this3 = this;\n if (!this.domNode) return;\n\n // W3.6 / W3.7 — source resolution priority:\n // 1. `opts.readSide` — full callback (most flexible; W3.7\n // Block cascade uses it to fall back to page.block_padding).\n // 2. `opts.keys` — direct instance prop names (PageElement's\n // block_padding_* lives on instance, not formatter).\n // 3. `element.formatter.getFormat('padding_*')` — default.\n var readSide;\n if (this.readSide) {\n readSide = this.readSide;\n } else if (this.keys) {\n readSide = function readSide(side) {\n var propName = _this3.keys[side];\n if (!propName) return 0;\n return Number(_this3.element[propName]) || 0;\n };\n } else {\n var f = this.element && this.element.formatter;\n if (!f || typeof f.getFormat !== 'function') return;\n readSide = function readSide(side) {\n return Number(f.getFormat(\"padding_\".concat(side))) || 0;\n };\n }\n var padding = {\n 'padding-top': readSide('top'),\n 'padding-right': readSide('right'),\n 'padding-bottom': readSide('bottom'),\n 'padding-left': readSide('left')\n };\n\n // Build region nodes lazily — once per overlay lifetime.\n if (!this._regionNodes) {\n this.domNode.innerHTML = '';\n\n // Unified hatch/dots layer (holed-box primitive). Carries the\n // pattern fill for the whole padding frame — single gradient\n // origin, zero seam jog. The 4 per-side regions below keep\n // borders + labels + per-side rich tint; they no longer render\n // a background of their own. Pattern swaps based on pin state\n // (quiet/grouped/focused = --hatch, pinned = --dots) so pinned\n // reads as a distinct mode at a glance.\n this._hatchBox = document.createElement('div');\n this._hatchBox.classList.add('bjs-holed-box', 'bjs-holed-box--hatch');\n this._hatchBox.dataset.role = 'hatch';\n this.domNode.appendChild(this._hatchBox);\n var map = {};\n for (var _i2 = 0, _REGION_KEYS2 = REGION_KEYS; _i2 < _REGION_KEYS2.length; _i2++) {\n var regionKey = _REGION_KEYS2[_i2];\n var d = document.createElement('div');\n d.classList.add('bjs-ovl-padding-region');\n d.dataset.region = regionKey;\n d.dataset.side = regionKey.replace('padding-', '');\n d.dataset.state = 'quiet';\n d.style.position = 'absolute';\n d.style.pointerEvents = 'none';\n d.style.boxSizing = 'border-box';\n // Placeholder for W3.3 — dim-label chip. Populated lazily\n // when the side's state enters rich-*. Kept as a child so\n // the region can position the chip relative to itself.\n var label = document.createElement('span');\n label.classList.add('bjs-ovl-padding-label');\n label.setAttribute('aria-hidden', 'true');\n d.appendChild(label);\n this.domNode.appendChild(d);\n map[regionKey] = d;\n }\n this._regionNodes = map;\n // Now that nodes exist, push any deferred state in (e.g.\n // overlay mounted while pinned — afterMount set this._pinned\n // before layoutChildren ran).\n this._recomputeAllStates();\n }\n var rect = this.domNode.getBoundingClientRect();\n var W = rect.width;\n var H = rect.height;\n\n // Guard: if an author sets padding larger than the element, we still\n // render something sensible — the opposing side just gets zero\n // remaining vertical/horizontal space, not a negative strip.\n var top = Math.max(0, Math.min(padding['padding-top'], H));\n var bottom = Math.max(0, Math.min(padding['padding-bottom'], H - top));\n var left = Math.max(0, Math.min(padding['padding-left'], W));\n var right = Math.max(0, Math.min(padding['padding-right'], W - left));\n var midH = Math.max(0, H - top - bottom);\n\n // PLAN_EFFECT W3.3 — compact threshold.\n //\n // Below ~14 CSS px of region thickness the label can't fit\n // inside its strip without dominating it. `data-compact=\"true\"`\n // short-circuits the CSS display rule that shows the label —\n // the dashed inner-edge guide stays, only the dimension chip\n // hides. The structure (DOM, classes) stays identical.\n var COMPACT_PX = 14;\n var apply = function apply(node, style, visible, labelText, thickness) {\n Object.assign(node.style, style);\n node.style.display = visible ? '' : 'none';\n var compact = thickness < COMPACT_PX;\n node.dataset.compact = compact ? 'true' : 'false';\n var label = node.querySelector('.bjs-ovl-padding-label');\n if (label) label.textContent = labelText;\n };\n apply(this._regionNodes['padding-top'], {\n top: '0px',\n left: '0px',\n right: '0px',\n width: 'auto',\n bottom: 'auto',\n height: top + 'px'\n }, top > 0, \"\".concat(padding['padding-top'], \" px\"), top);\n apply(this._regionNodes['padding-bottom'], {\n bottom: '0px',\n left: '0px',\n right: '0px',\n width: 'auto',\n top: 'auto',\n height: bottom + 'px'\n }, bottom > 0, \"\".concat(padding['padding-bottom'], \" px\"), bottom);\n apply(this._regionNodes['padding-left'], {\n top: top + 'px',\n left: '0px',\n right: 'auto',\n bottom: 'auto',\n width: left + 'px',\n height: midH + 'px'\n }, left > 0 && midH > 0, \"\".concat(padding['padding-left'], \" px\"), left);\n apply(this._regionNodes['padding-right'], {\n top: top + 'px',\n right: '0px',\n left: 'auto',\n bottom: 'auto',\n width: right + 'px',\n height: midH + 'px'\n }, right > 0 && midH > 0, \"\".concat(padding['padding-right'], \" px\"), right);\n\n // Holed-box hatch frame — clip-path carves the child (content)\n // rect so the pattern only shows on the 4 padding strips. The\n // pattern MODIFIER (hatch vs dots) is toggled in _syncHatchMode()\n // based on pin state; this block just handles geometry.\n if (this._hatchBox) {\n var hasAnyPadding = top + right + bottom + left > 0;\n this._hatchBox.style.display = hasAnyPadding ? '' : 'none';\n if (hasAnyPadding) {\n this._hatchBox.style.clipPath = (0,_ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])({\n width: W,\n height: H\n }, {\n left: left,\n top: top,\n right: W - right,\n bottom: H - bottom\n });\n }\n this._syncHatchMode();\n }\n }\n\n /**\n * Swap the hatch box's pattern modifier based on the overlay's\n * current state mix. Quiet / grouped / focused use `--hatch`\n * (diagonal stripes). Pinned swaps to `--dots` so the pinned mode\n * reads as a distinct emphasis tier without changing density band.\n * Called from layoutChildren (once on build, after every reflow)\n * and from _recomputeAllStates (when pin / focus flags flip\n * without a geometry change).\n */\n }, {\n key: \"_syncHatchMode\",\n value: function _syncHatchMode() {\n if (!this._hatchBox) return;\n var wantsDots = !!this._pinned;\n this._hatchBox.classList.toggle('bjs-holed-box--dots', wantsDots);\n this._hatchBox.classList.toggle('bjs-holed-box--hatch', !wantsDots);\n }\n }]);\n}(_StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PaddingVisualizerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/PaddingVisualizerOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/ResizeCornerOverlay.js":
/*!******************************************************!*\
!*** ./src/includes/overlays/ResizeCornerOverlay.js ***!
\******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./DraggableHandleOverlay.js */ \"./src/includes/overlays/DraggableHandleOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ResizeCornerOverlay — 10×10 square handle at a named corner.\n *\n * Use for 2-axis resize gestures:\n * - Image resize (4 corners on ImageElement — Phase 1.4)\n * - (future) block max-width/max-height resize\n *\n * Subclass signature:\n * new ResizeCornerOverlay(element, { corner: 'nw' | 'ne' | 'se' | 'sw', aspectLock: true|false })\n *\n * Drag delta math is delegated to subclass `onDrag(dx, dy, e)`. This class\n * owns positioning (small square at the chosen corner) and cursor hint.\n *\n * Subclasses decide what formatter keys to update (width + height, or\n * max_width + max_height, etc) and optionally enforce aspect-lock.\n */\n\nvar CORNER_CURSORS = {\n nw: 'nwse-resize',\n ne: 'nesw-resize',\n se: 'nwse-resize',\n sw: 'nesw-resize'\n};\nvar HANDLE_SIZE = 10;\nvar ResizeCornerOverlay = /*#__PURE__*/function (_DraggableHandleOverl) {\n function ResizeCornerOverlay() {\n _classCallCheck(this, ResizeCornerOverlay);\n return _callSuper(this, ResizeCornerOverlay, arguments);\n }\n _inherits(ResizeCornerOverlay, _DraggableHandleOverl);\n return _createClass(ResizeCornerOverlay, [{\n key: \"render\",\n value: function render() {\n _superPropGet(ResizeCornerOverlay, \"render\", this, 3)([]); // pointer handlers + I2 assert\n this.domNode.classList.add('bjs-ovl-resize-corner');\n var corner = this.opts.corner || 'se';\n this.domNode.classList.add(\"bjs-ovl-corner-\".concat(corner));\n this.domNode.style.cursor = CORNER_CURSORS[corner] || 'nwse-resize';\n\n // a11y\n this.domNode.setAttribute('role', 'slider');\n this.domNode.setAttribute('aria-label', \"Resize (\".concat(corner.toUpperCase(), \" corner)\"));\n this.domNode.setAttribute('tabindex', '0');\n }\n }, {\n key: \"position\",\n value: function position() {\n var _this = this;\n var corner = this.opts.corner || 'se';\n this.element.matchingDomNode(this.domNode, 0, function () {\n var domRect = _this.element.domNode.getBoundingClientRect();\n var iframe = _this.element.domNode.ownerDocument.defaultView.frameElement;\n var iframeRect = iframe ? iframe.getBoundingClientRect() : {\n top: 0,\n left: 0\n };\n var absTop = iframeRect.top + domRect.top;\n var absLeft = iframeRect.left + domRect.left;\n var half = HANDLE_SIZE / 2;\n var top, left;\n switch (corner) {\n case 'nw':\n top = absTop - half;\n left = absLeft - half;\n break;\n case 'ne':\n top = absTop - half;\n left = absLeft + domRect.width - half;\n break;\n case 'sw':\n top = absTop + domRect.height - half;\n left = absLeft - half;\n break;\n case 'se':\n default:\n top = absTop + domRect.height - half;\n left = absLeft + domRect.width - half;\n break;\n }\n Object.assign(_this.domNode.style, {\n position: 'fixed',\n top: top + 'px',\n left: left + 'px',\n width: HANDLE_SIZE + 'px',\n height: HANDLE_SIZE + 'px'\n });\n });\n }\n }]);\n}(_DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ResizeCornerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ResizeCornerOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/RichDropdownMenuOverlay.js":
/*!**********************************************************!*\
!*** ./src/includes/overlays/RichDropdownMenuOverlay.js ***!
\**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * RichDropdownMenuOverlay — W2.1 (TEXT_INLINE_PLAN, 2026-04-24).\n *\n * macOS / Notion-style sectioned dropdown menu. Standalone primitive —\n * NOT coupled to the inline toolbar. Backs W2.2 (clipboard + format\n * section), W2.3 (paragraph / case / insert / semantic submenus), and\n * any future kebab / overflow menu in BuilderJS.\n *\n * Section + item model (matches Notion's native menu):\n *\n * {\n * ariaLabel?: string, // screen-reader label for root menu\n * width?: number, // default 260px (auto-fits long shortcut hints)\n * sections: [\n * {\n * heading?: string, // optional section label row\n * items: [\n * {\n * id?: string, // stable key (surfaced to onSelect)\n * icon?: string, // material-symbols-rounded glyph (left)\n * label: string, // row label (required)\n * shortcut?: string, // keyboard hint (right-aligned kbd)\n * disabled?: boolean, // dims + aria-disabled=true, skipped by kbd nav\n * destructive?: boolean, // red text + red hover (delete / remove link)\n * onActivate?: fn, // row-specific callback, runs before onSelect\n * submenu?: { // nested menu — opens on → / hover / click\n * ariaLabel?: string,\n * sections: [...]\n * },\n * ariaLabel?: string, // override label for a11y when icon-only\n * },\n * { divider: true }, // same-section horizontal line row\n * ],\n * },\n * ],\n * onSelect?: fn(id, item), // global activation callback\n * onClose?: fn(), // lifecycle hook\n * preferredSide?: 'below' | 'above' | 'right' | 'left', // default 'below'\n * }\n *\n * Keyboard contract (HARD RULE T5 — real accelerators, not macOS cloning):\n *\n * ↑ / ↓ move focus prev / next enabled item, wraps, skips\n * dividers + headings + disabled.\n * Home / End first / last enabled.\n * Enter / Space activate current item (fires onActivate + onSelect\n * then close() — except submenu rows, which open).\n * Esc close menu (if inside submenu, close submenu first\n * and return focus to parent row).\n * → on a submenu row, open submenu + focus its first.\n * ← inside submenu, close submenu + focus parent row.\n * A–Z type-ahead 1-second buffer; prefix-matches item.label\n * (case-insensitive, skipping disabled).\n *\n * ARIA (WCAG 2.1 \"Menu\" pattern):\n *\n * root role=\"menu\" + aria-label\n * item role=\"menuitem\" + aria-disabled (when disabled)\n * submenu item additionally aria-haspopup=\"menu\" + aria-expanded\n * divider role=\"separator\" + aria-hidden (purely visual)\n * heading role=\"presentation\" (screen-reader visible via grouped items)\n *\n * Dismissal (7-path contract — mirrors W1.2 / W1.3 / W3.1 popovers):\n *\n * (a) Escape → close (submenu first)\n * (b) Click outside root → close\n * (c) Activating an item (non-submenu) → close\n * (d) External owner calls .close() → close\n * (e) Focus leaves menu + submenu → close (after 1 tick, so Tab still works)\n * (f) anchorEl removed from DOM → close (MutationObserver)\n * (g) Window scroll / resize → reposition (not close)\n *\n * Anchored via `ToolbarPositioner.attach` — so scroll / resize / anchor\n * motion keeps the menu pinned. Preferred side defaults to 'below' (drop-\n * down semantics); submenus default to 'right' (nested menu semantics).\n *\n * Not a BaseOverlay subclass. The inline toolbar + every other caller\n * owns the single-popover invariant themselves (e.g. `toolbar._richMenu`).\n */\n\n\n\nvar DEFAULT_WIDTH = 260;\nvar TYPEAHEAD_WINDOW_MS = 1000;\nvar RichDropdownMenuOverlay = /*#__PURE__*/function () {\n /**\n * @param {{\n * anchorEl: HTMLElement,\n * sections: Array,\n * ariaLabel?: string,\n * width?: number,\n * preferredSide?: 'below'|'above'|'right'|'left',\n * onSelect?: Function,\n * onClose?: Function,\n * parent?: RichDropdownMenuOverlay, // internal — set on submenus\n * }} opts\n */\n function RichDropdownMenuOverlay(opts) {\n _classCallCheck(this, RichDropdownMenuOverlay);\n if (!opts || !opts.anchorEl) {\n throw new Error('RichDropdownMenuOverlay: opts.anchorEl required');\n }\n if (!Array.isArray(opts.sections) || opts.sections.length === 0) {\n throw new Error('RichDropdownMenuOverlay: opts.sections must be a non-empty array');\n }\n this._anchorEl = opts.anchorEl;\n this._sections = opts.sections;\n this._ariaLabel = opts.ariaLabel || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rich_menu.aria_label');\n this._width = typeof opts.width === 'number' ? opts.width : DEFAULT_WIDTH;\n this._preferredSide = opts.preferredSide || 'below';\n this._onSelect = typeof opts.onSelect === 'function' ? opts.onSelect : null;\n this._onClose = typeof opts.onClose === 'function' ? opts.onClose : null;\n this._parent = opts.parent || null;\n this.domNode = null;\n this._mounted = false;\n this._positionHandle = null;\n this._rowEls = []; // enabled item row elements (in tab order)\n this._focusIndex = -1;\n this._typeahead = '';\n this._typeaheadTimer = null;\n this._openSubmenu = null; // child RichDropdownMenuOverlay instance\n this._openSubmenuRow = null; // HTMLElement of the row that opened it\n\n this._onDocKey = null;\n this._onDocMouseDown = null;\n this._onFocusOut = null;\n this._onAnchorDetach = null; // MutationObserver\n }\n\n /* ── public lifecycle ─────────────────────────────────────────── */\n return _createClass(RichDropdownMenuOverlay, [{\n key: \"open\",\n value: function open() {\n var _this = this;\n if (this._mounted) return;\n this._build();\n if (!this.domNode) return;\n document.body.appendChild(this.domNode);\n this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n anchor: function anchor() {\n return _this._anchorEl.getBoundingClientRect();\n },\n target: this.domNode,\n offset: 6,\n collisionPadding: 12,\n preferredSide: this._preferredSide,\n flip: true\n });\n this._registerDismissListeners();\n this._watchAnchorDetach();\n this._mounted = true;\n try {\n this._anchorEl.setAttribute('aria-expanded', 'true');\n } catch (_) {}\n // Focus first enabled row so keyboard users land somewhere actionable.\n this._focusIndex = this._firstEnabledIndex();\n this._applyFocusVisual();\n }\n }, {\n key: \"close\",\n value: function close() {\n if (!this._mounted && !this.domNode) return;\n // Cascade — close nested submenu first so focus can return cleanly.\n if (this._openSubmenu) {\n try {\n this._openSubmenu.close();\n } catch (_) {}\n this._openSubmenu = null;\n this._openSubmenuRow = null;\n }\n this._unregisterDismissListeners();\n this._stopWatchingAnchor();\n if (this._positionHandle) {\n try {\n this._positionHandle.dispose();\n } catch (_) {}\n this._positionHandle = null;\n }\n if (this.domNode && this.domNode.parentNode) {\n try {\n this.domNode.parentNode.removeChild(this.domNode);\n } catch (_) {}\n }\n this.domNode = null;\n this._mounted = false;\n this._rowEls = [];\n this._focusIndex = -1;\n this._clearTypeahead();\n try {\n this._anchorEl.setAttribute('aria-expanded', 'false');\n } catch (_) {}\n if (this._onClose) {\n try {\n this._onClose();\n } catch (_) {}\n }\n }\n }, {\n key: \"isOpen\",\n value: function isOpen() {\n return this._mounted;\n }\n\n /** Re-anchor + reposition without rebuilding. For owners that keep\n * the anchor stable but want to nudge placement after layout shifts. */\n }, {\n key: \"reposition\",\n value: function reposition() {\n if (this._positionHandle) {\n try {\n this._positionHandle.reposition();\n } catch (_) {}\n }\n }\n\n /* ── build ────────────────────────────────────────────────────── */\n }, {\n key: \"_build\",\n value: function _build() {\n var root = document.createElement('div');\n root.className = 'bjs-ovl bjs-ovl-rich-menu';\n root.setAttribute('role', 'menu');\n root.setAttribute('aria-label', this._ariaLabel);\n root.setAttribute('data-interactive', '');\n if (this._parent) root.setAttribute('data-submenu', '1');\n root.style.width = this._width + 'px';\n\n // Keyboard owner — capture keydowns on the menu itself so arrow\n // keys don't bubble into host-page shortcut handlers.\n root.addEventListener('keydown', this._onMenuKeyDown.bind(this));\n this._rowEls = [];\n for (var i = 0; i < this._sections.length; i++) {\n var section = this._sections[i];\n // Divider between sections (skip before first).\n if (i > 0) root.appendChild(this._renderSectionDivider());\n if (section.heading) root.appendChild(this._renderHeading(section.heading));\n var _iterator = _createForOfIteratorHelper(section.items || []),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var item = _step.value;\n if (item && item.divider) {\n root.appendChild(this._renderDivider());\n continue;\n }\n var rowEl = this._renderItem(item);\n root.appendChild(rowEl);\n if (!item.disabled) this._rowEls.push(rowEl);\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n }\n this.domNode = root;\n }\n }, {\n key: \"_renderHeading\",\n value: function _renderHeading(text) {\n var h = document.createElement('div');\n h.className = 'bjs-rich-menu-heading';\n h.setAttribute('role', 'presentation');\n h.textContent = text;\n return h;\n }\n }, {\n key: \"_renderDivider\",\n value: function _renderDivider() {\n var d = document.createElement('div');\n d.className = 'bjs-rich-menu-divider';\n d.setAttribute('role', 'separator');\n d.setAttribute('aria-hidden', 'true');\n return d;\n }\n }, {\n key: \"_renderSectionDivider\",\n value: function _renderSectionDivider() {\n // Same glyph, but distinct class so sections can adjust margin in\n // CSS (a bit more breathing room than an inline divider).\n var d = this._renderDivider();\n d.classList.add('bjs-rich-menu-section-divider');\n return d;\n }\n }, {\n key: \"_renderItem\",\n value: function _renderItem(item) {\n var _this2 = this;\n var row = document.createElement('button');\n row.type = 'button';\n row.className = 'bjs-rich-menu-item';\n row.setAttribute('role', 'menuitem');\n if (item.id) row.setAttribute('data-item-id', item.id);\n var hasSubmenu = !!(item.submenu && Array.isArray(item.submenu.sections) && item.submenu.sections.length);\n if (hasSubmenu) {\n row.classList.add('has-submenu');\n row.setAttribute('aria-haspopup', 'menu');\n row.setAttribute('aria-expanded', 'false');\n }\n if (item.disabled) {\n row.classList.add('is-disabled');\n row.setAttribute('aria-disabled', 'true');\n row.setAttribute('tabindex', '-1');\n }\n if (item.destructive) row.classList.add('is-destructive');\n if (item.ariaLabel) row.setAttribute('aria-label', item.ariaLabel);\n\n // Left — icon cell (always present so rows line up even when icon missing).\n var iconCell = document.createElement('span');\n iconCell.className = 'bjs-rich-menu-item-icon';\n iconCell.setAttribute('aria-hidden', 'true');\n if (item.icon) {\n var ic = document.createElement('span');\n ic.className = 'material-symbols-rounded';\n ic.textContent = item.icon;\n iconCell.appendChild(ic);\n }\n row.appendChild(iconCell);\n\n // Middle — label.\n var labelCell = document.createElement('span');\n labelCell.className = 'bjs-rich-menu-item-label';\n labelCell.textContent = item.label || '';\n row.appendChild(labelCell);\n\n // Right — shortcut or submenu caret.\n if (hasSubmenu) {\n var caret = document.createElement('span');\n caret.className = 'bjs-rich-menu-item-caret material-symbols-rounded';\n caret.setAttribute('aria-hidden', 'true');\n caret.textContent = 'chevron_right';\n row.appendChild(caret);\n } else if (item.shortcut) {\n var kbd = document.createElement('kbd');\n kbd.className = 'bjs-rich-menu-item-shortcut';\n kbd.setAttribute('aria-hidden', 'true'); // label already announces action\n kbd.textContent = item.shortcut;\n row.appendChild(kbd);\n }\n\n // Interaction — hover to focus (native menu behaviour), click to activate.\n row.addEventListener('mouseenter', function () {\n if (item.disabled) return;\n var idx = _this2._rowEls.indexOf(row);\n if (idx !== -1) {\n _this2._focusIndex = idx;\n _this2._applyFocusVisual();\n }\n // Submenu opens on hover (150ms delay would be ideal but native\n // menus open immediately on hover — we match).\n if (hasSubmenu && !_this2._submenuIsOpenFor(row)) {\n _this2._openSubmenuFor(row, item, {\n focusFirst: false\n });\n } else if (!hasSubmenu && _this2._openSubmenu) {\n // Hovering a non-submenu row should close any open submenu —\n // matches Notion / macOS.\n _this2._closeSubmenu();\n }\n });\n row.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n if (item.disabled) return;\n if (hasSubmenu) {\n if (_this2._submenuIsOpenFor(row)) {\n _this2._closeSubmenu();\n } else {\n _this2._openSubmenuFor(row, item, {\n focusFirst: true\n });\n }\n return;\n }\n _this2._activate(item);\n });\n return row;\n }\n\n /* ── activation ───────────────────────────────────────────────── */\n }, {\n key: \"_activate\",\n value: function _activate(item) {\n // Run row callback, then global onSelect, then close (top-most).\n var suppressClose = false;\n try {\n if (typeof item.onActivate === 'function') {\n var r = item.onActivate(item);\n if (r === false) suppressClose = true;\n }\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[bjs:rich-menu] onActivate threw:', err);\n }\n if (this._onSelect) {\n try {\n var _r = this._onSelect(item.id || null, item);\n if (_r === false) suppressClose = true;\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[bjs:rich-menu] onSelect threw:', err);\n }\n }\n if (suppressClose) return;\n this._closeAllFromRoot();\n }\n }, {\n key: \"_closeAllFromRoot\",\n value: function _closeAllFromRoot() {\n // Walk up the parent chain and close the root.\n var node = this;\n while (node._parent) node = node._parent;\n node.close();\n }\n\n /* ── submenu ──────────────────────────────────────────────────── */\n }, {\n key: \"_submenuIsOpenFor\",\n value: function _submenuIsOpenFor(row) {\n return this._openSubmenu && this._openSubmenuRow === row && this._openSubmenu.isOpen();\n }\n }, {\n key: \"_openSubmenuFor\",\n value: function _openSubmenuFor(row, item, _ref) {\n var focusFirst = _ref.focusFirst;\n if (this._openSubmenu) this._closeSubmenu();\n var sub = new RichDropdownMenuOverlay({\n anchorEl: row,\n sections: item.submenu.sections,\n ariaLabel: item.submenu.ariaLabel || item.label,\n width: item.submenu.width,\n preferredSide: 'right',\n onSelect: this._onSelect,\n parent: this\n });\n sub.open();\n this._openSubmenu = sub;\n this._openSubmenuRow = row;\n row.setAttribute('aria-expanded', 'true');\n if (focusFirst && sub.isOpen()) {\n sub._focusIndex = sub._firstEnabledIndex();\n sub._applyFocusVisual();\n }\n }\n }, {\n key: \"_closeSubmenu\",\n value: function _closeSubmenu() {\n if (!this._openSubmenu) return;\n try {\n this._openSubmenu.close();\n } catch (_) {}\n if (this._openSubmenuRow) {\n try {\n this._openSubmenuRow.setAttribute('aria-expanded', 'false');\n } catch (_) {}\n }\n this._openSubmenu = null;\n this._openSubmenuRow = null;\n }\n\n /* ── focus ────────────────────────────────────────────────────── */\n }, {\n key: \"_firstEnabledIndex\",\n value: function _firstEnabledIndex() {\n return this._rowEls.length ? 0 : -1;\n }\n }, {\n key: \"_lastEnabledIndex\",\n value: function _lastEnabledIndex() {\n return this._rowEls.length - 1;\n }\n }, {\n key: \"_applyFocusVisual\",\n value: function _applyFocusVisual() {\n for (var i = 0; i < this._rowEls.length; i++) {\n var el = this._rowEls[i];\n var isFocused = i === this._focusIndex;\n el.classList.toggle('is-focus', isFocused);\n if (isFocused) {\n try {\n el.focus({\n preventScroll: true\n });\n } catch (_) {\n try {\n el.focus();\n } catch (__) {}\n }\n }\n }\n }\n }, {\n key: \"_moveFocus\",\n value: function _moveFocus(delta) {\n if (!this._rowEls.length) return;\n var idx = this._focusIndex;\n if (idx < 0) idx = delta > 0 ? -1 : 0;\n idx = (idx + delta + this._rowEls.length) % this._rowEls.length;\n this._focusIndex = idx;\n this._applyFocusVisual();\n }\n }, {\n key: \"_focusTo\",\n value: function _focusTo(idx) {\n if (idx < 0 || idx >= this._rowEls.length) return;\n this._focusIndex = idx;\n this._applyFocusVisual();\n }\n\n /* ── keyboard ─────────────────────────────────────────────────── */\n }, {\n key: \"_onMenuKeyDown\",\n value: function _onMenuKeyDown(e) {\n // If a submenu is open it handles its own keydown via its own\n // listener; don't double-process here.\n if (this._openSubmenu && this._openSubmenu.isOpen()) return;\n var key = e.key;\n if (key === 'ArrowDown') {\n e.preventDefault();\n this._moveFocus(1);\n return;\n }\n if (key === 'ArrowUp') {\n e.preventDefault();\n this._moveFocus(-1);\n return;\n }\n if (key === 'Home') {\n e.preventDefault();\n this._focusTo(this._firstEnabledIndex());\n return;\n }\n if (key === 'End') {\n e.preventDefault();\n this._focusTo(this._lastEnabledIndex());\n return;\n }\n if (key === 'ArrowRight') {\n var row = this._currentRow();\n var item = this._currentItem();\n if (row && item && item.submenu) {\n e.preventDefault();\n this._openSubmenuFor(row, item, {\n focusFirst: true\n });\n }\n return;\n }\n if (key === 'ArrowLeft') {\n // Close this menu and return focus to parent row.\n if (this._parent) {\n e.preventDefault();\n this._parent._closeSubmenu();\n try {\n this._parent._applyFocusVisual();\n } catch (_) {}\n }\n return;\n }\n if (key === 'Enter' || key === ' ') {\n var _item = this._currentItem();\n var _row = this._currentRow();\n if (!_item || !_row) return;\n e.preventDefault();\n if (_item.submenu) {\n this._openSubmenuFor(_row, _item, {\n focusFirst: true\n });\n } else {\n this._activate(_item);\n }\n return;\n }\n if (key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n if (this._parent) {\n // Inside submenu — close self, return to parent.\n this._parent._closeSubmenu();\n try {\n this._parent._applyFocusVisual();\n } catch (_) {}\n } else {\n this.close();\n }\n return;\n }\n // Type-ahead: printable single-char.\n if (key.length === 1 && /\\S/.test(key)) {\n this._typeaheadPush(key);\n }\n }\n }, {\n key: \"_currentRow\",\n value: function _currentRow() {\n return this._focusIndex >= 0 && this._focusIndex < this._rowEls.length ? this._rowEls[this._focusIndex] : null;\n }\n }, {\n key: \"_currentItem\",\n value: function _currentItem() {\n var row = this._currentRow();\n if (!row) return null;\n var id = row.getAttribute('data-item-id');\n // Walk sections to find the item matching id OR DOM identity.\n var _iterator2 = _createForOfIteratorHelper(this._sections),\n _step2;\n try {\n for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n var section = _step2.value;\n var _iterator3 = _createForOfIteratorHelper(section.items || []),\n _step3;\n try {\n for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n var it = _step3.value;\n if (it && it.divider) continue;\n if (id && it.id === id) return it;\n if (!id && row.querySelector('.bjs-rich-menu-item-label') && row.querySelector('.bjs-rich-menu-item-label').textContent === it.label) return it;\n }\n } catch (err) {\n _iterator3.e(err);\n } finally {\n _iterator3.f();\n }\n }\n } catch (err) {\n _iterator2.e(err);\n } finally {\n _iterator2.f();\n }\n return null;\n }\n }, {\n key: \"_typeaheadPush\",\n value: function _typeaheadPush(ch) {\n var _this3 = this;\n this._typeahead += ch.toLowerCase();\n if (this._typeaheadTimer) clearTimeout(this._typeaheadTimer);\n this._typeaheadTimer = setTimeout(function () {\n return _this3._clearTypeahead();\n }, TYPEAHEAD_WINDOW_MS);\n // Find first enabled row whose label starts with the buffer.\n for (var i = 0; i < this._rowEls.length; i++) {\n var el = this._rowEls[i];\n var label = (el.querySelector('.bjs-rich-menu-item-label') || {}).textContent || '';\n if (label.toLowerCase().startsWith(this._typeahead)) {\n this._focusTo(i);\n return;\n }\n }\n }\n }, {\n key: \"_clearTypeahead\",\n value: function _clearTypeahead() {\n this._typeahead = '';\n if (this._typeaheadTimer) {\n clearTimeout(this._typeaheadTimer);\n this._typeaheadTimer = null;\n }\n }\n\n /* ── dismissal ────────────────────────────────────────────────── */\n }, {\n key: \"_registerDismissListeners\",\n value: function _registerDismissListeners() {\n var _this4 = this;\n // Esc + arrow keys are on the menu itself (root keydown). These\n // are the document-level fallbacks for outside-click + focus-loss.\n this._onDocKey = function (e) {\n // Only handle Escape at doc-level when focus is NOT inside the\n // menu (menu's own handler already owns that path). This\n // catches host-app Escape while the menu DOES still want to\n // close — e.g. user clicked canvas then hit Esc.\n if (e.key !== 'Escape') return;\n if (_this4.domNode && document.activeElement && _this4.domNode.contains(document.activeElement)) return;\n if (_this4._parent) return; // only root handles doc-level Esc\n e.stopPropagation();\n _this4.close();\n };\n document.addEventListener('keydown', this._onDocKey, true);\n this._onDocMouseDown = function (e) {\n if (!_this4.domNode) return;\n if (_this4._parent) return; // only root handles outside-click; submenu is a child of root's closure\n var t = e.target;\n // Click inside root → keep open.\n if (_this4.domNode.contains(t)) return;\n // Click inside open submenu → keep open.\n if (_this4._openSubmenu && _this4._openSubmenu.domNode && _this4._openSubmenu.domNode.contains(t)) return;\n // Click on anchor that opened the menu → toggle-off\n // (owner's click handler runs first; we stay idle so owner's\n // toggle logic works. But if click is elsewhere on the anchor\n // chain, defensive-close.)\n if (t && _this4._anchorEl && _this4._anchorEl.contains(t)) return;\n _this4.close();\n };\n // Defer so the click that opened us doesn't instantly close.\n setTimeout(function () {\n if (_this4._mounted) document.addEventListener('mousedown', _this4._onDocMouseDown, true);\n }, 0);\n }\n }, {\n key: \"_unregisterDismissListeners\",\n value: function _unregisterDismissListeners() {\n if (this._onDocKey) {\n document.removeEventListener('keydown', this._onDocKey, true);\n this._onDocKey = null;\n }\n if (this._onDocMouseDown) {\n document.removeEventListener('mousedown', this._onDocMouseDown, true);\n this._onDocMouseDown = null;\n }\n }\n\n /* ── anchor-detach watcher ────────────────────────────────────── */\n }, {\n key: \"_watchAnchorDetach\",\n value: function _watchAnchorDetach() {\n var _this5 = this;\n if (typeof MutationObserver === 'undefined') return;\n var ownerDoc = this._anchorEl.ownerDocument || document;\n var root = ownerDoc.body || ownerDoc.documentElement;\n if (!root) return;\n this._onAnchorDetach = new MutationObserver(function () {\n if (!_this5._anchorEl || !_this5._anchorEl.isConnected) {\n _this5.close();\n }\n });\n try {\n this._onAnchorDetach.observe(root, {\n childList: true,\n subtree: true\n });\n } catch (_) {\n this._onAnchorDetach = null;\n }\n }\n }, {\n key: \"_stopWatchingAnchor\",\n value: function _stopWatchingAnchor() {\n if (this._onAnchorDetach) {\n try {\n this._onAnchorDetach.disconnect();\n } catch (_) {}\n this._onAnchorDetach = null;\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RichDropdownMenuOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/RichDropdownMenuOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/StructureVisualizerOverlay.js":
/*!*************************************************************!*\
!*** ./src/includes/overlays/StructureVisualizerOverlay.js ***!
\*************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * StructureVisualizerOverlay — full-element transparent cover that draws\n * child-structure hints.\n *\n * Use for showing the logical structure of a container:\n * - Grid cell boundaries + column separators (Phase 1.3)\n * - (future) flex-track markers, table-column gutters\n *\n * Subclass signature:\n * class GridStructureOverlay extends StructureVisualizerOverlay {\n * layoutChildren() { this.domNode.innerHTML = ''; ...draw per-child hints... }\n * }\n *\n * Relayout on reflow is automatic — `position()` passes `layoutChildren` to\n * matchingDomNode's afterPosSize hook, so it fires on every iframe scroll /\n * resize / mutation / element reflow.\n *\n * The root is `pointer-events: none` (pass-through) — children that should\n * catch clicks/drags add `data-interactive` attribute or their own\n * pointer-events: auto rule. Ensure child primitives (EdgeResizerOverlay\n * instances, insert buttons) match this pattern — they already do via\n * `.bjs-ovl-handle` / `.bjs-ovl-action-bar` selectors in overlays CSS.\n */\n\nvar StructureVisualizerOverlay = /*#__PURE__*/function (_BaseOverlay) {\n function StructureVisualizerOverlay() {\n _classCallCheck(this, StructureVisualizerOverlay);\n return _callSuper(this, StructureVisualizerOverlay, arguments);\n }\n _inherits(StructureVisualizerOverlay, _BaseOverlay);\n return _createClass(StructureVisualizerOverlay, [{\n key: \"render\",\n value: function render() {\n this.domNode = document.createElement('div');\n this.domNode.classList.add('bjs-ovl-structure');\n // Root pass-through; interactive children opt in.\n this.domNode.style.pointerEvents = 'none';\n }\n }, {\n key: \"position\",\n value: function position() {\n var _this = this;\n // matchingDomNode's afterPosSize fires on every reflow; delegate child\n // relayout there so the visualisation stays glued to current geometry.\n this.element.matchingDomNode(this.domNode, 0, null, function () {\n try {\n _this.layoutChildren();\n } catch (err) {\n /* eslint-disable-next-line no-console */console.error('[overlay] layoutChildren threw:', err);\n }\n });\n }\n\n /** Subclass override: rebuild per-child visual hints inside this.domNode.\n * Called on every reflow. MUST be cheap (no async, no network). Default\n * is a no-op — useful for a bare \"this element is selected\" glow. */\n }, {\n key: \"layoutChildren\",\n value: function layoutChildren() {\n // no-op\n }\n }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (StructureVisualizerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/StructureVisualizerOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/TextColorPopoverOverlay.js":
/*!**********************************************************!*\
!*** ./src/includes/overlays/TextColorPopoverOverlay.js ***!
\**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _ui_ColorPalettePicker_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ui/ColorPalettePicker.js */ \"./src/includes/ui/ColorPalettePicker.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * TextColorPopoverOverlay — floating panel for picking a text color\n * (foreground, `execCommand('foreColor')`) or a highlight color\n * (background, `execCommand('hiliteColor')`).\n *\n * TEXT_INLINE_PLAN W1.2 (2026-04-20). 2026-04-21 refactor: the palette +\n * custom + eyedropper body is now a shared primitive\n * (`src/includes/ui/ColorPalettePicker.js`). This overlay is a thin chrome\n * host — mount/unmount, anchor positioning, dismissal wiring — around\n * the primitive. The sidebar `ColorPickerControl` will embed the same\n * primitive in a follow-up phase so canvas + sidebar share one grand\n * Google-style palette UX.\n *\n * Single class, two modes. `mode: 'foreColor' | 'hiliteColor'`.\n */\n\n\n\n\nvar RECENT_MAX = 10;\nvar TextColorPopoverOverlay = /*#__PURE__*/function () {\n /**\n * @param {TextInlineToolbarOverlay} toolbar — owner. Used to call back\n * `_applyColor` so the popover shares the toolbar's char-offset\n * selection save/restore pipeline.\n * @param {{mode: 'foreColor'|'hiliteColor', anchorBtn: HTMLElement, initialColor?: string}} opts\n */\n function TextColorPopoverOverlay(toolbar, opts) {\n _classCallCheck(this, TextColorPopoverOverlay);\n if (!toolbar || !opts || !opts.anchorBtn) {\n throw new Error('TextColorPopoverOverlay: toolbar + opts.anchorBtn required');\n }\n if (opts.mode !== 'foreColor' && opts.mode !== 'hiliteColor') {\n throw new Error('TextColorPopoverOverlay: opts.mode must be foreColor or hiliteColor');\n }\n this._toolbar = toolbar;\n this._mode = opts.mode;\n this._anchorBtn = opts.anchorBtn;\n this._initialColor = opts.initialColor || null;\n this.domNode = null;\n this._picker = null;\n this._positionHandle = null;\n this._onDocKey = null;\n this._onDocMouseDown = null;\n this._mounted = false;\n }\n\n /* ── public lifecycle ─────────────────────────────────────────── */\n return _createClass(TextColorPopoverOverlay, [{\n key: \"open\",\n value: function open() {\n var _this = this;\n if (this._mounted) return;\n try {\n this._build();\n document.body.appendChild(this.domNode);\n this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n anchor: function anchor() {\n return _this._anchorBtn.getBoundingClientRect();\n },\n target: this.domNode,\n offset: 8,\n collisionPadding: 12,\n preferredSide: 'below',\n flip: true\n });\n this._registerDismissListeners();\n this._mounted = true;\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[bjs:text-color-popover] open failed:', err);\n this.close();\n }\n }\n }, {\n key: \"close\",\n value: function close() {\n if (!this._mounted && !this.domNode) return;\n this._unregisterDismissListeners();\n if (this._positionHandle) {\n try {\n this._positionHandle.dispose();\n } catch (_) {}\n this._positionHandle = null;\n }\n if (this.domNode && this.domNode.parentNode) {\n try {\n this.domNode.parentNode.removeChild(this.domNode);\n } catch (_) {}\n }\n this.domNode = null;\n this._picker = null;\n this._mounted = false;\n }\n }, {\n key: \"isOpen\",\n value: function isOpen() {\n return this._mounted;\n }\n\n /* ── build ────────────────────────────────────────────────────── */\n }, {\n key: \"_build\",\n value: function _build() {\n var _this2 = this;\n var p = document.createElement('div');\n p.className = 'bjs-ovl bjs-ovl-color-popover';\n p.setAttribute('role', 'dialog');\n p.setAttribute('aria-label', this._titleLabel());\n p.setAttribute('data-interactive', '');\n p.setAttribute('data-mode', this._mode);\n\n // Preserve iframe selection across mousedown in the popover body.\n p.addEventListener('mousedown', function (e) {\n if (e.target && e.target.closest('input, textarea, select, button[data-role=\"eyedropper\"]')) return;\n e.preventDefault();\n });\n\n // Shared primitive. Callbacks: pick → apply+close; reset → clear+close.\n this._picker = new _ui_ColorPalettePicker_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n value: this._initialColor,\n recent: this._getRecentColors(),\n title: this._titleLabel(),\n onPick: function onPick(hex) {\n if (hex === null) {\n _this2._handleReset();\n return;\n }\n _this2._handlePick(hex);\n },\n onReset: function onReset() {\n return _this2._handleReset();\n }\n });\n p.appendChild(this._picker.domNode);\n this.domNode = p;\n }\n\n /* ── apply ─────────────────────────────────────────────────────── */\n }, {\n key: \"_handlePick\",\n value: function _handlePick(hex) {\n var applied = this._toolbar._applyColor(this._mode, hex, this._anchorBtn);\n if (applied !== false) {\n this._pushRecent(hex);\n // Update the toolbar button's color indicator (underline bar).\n this._toolbar._updateColorIndicator(this._mode, hex);\n this.close();\n }\n }\n }, {\n key: \"_handleReset\",\n value: function _handleReset() {\n var applied = this._mode === 'foreColor' ? this._toolbar._applyColor('foreColor', 'inherit', this._anchorBtn) : this._toolbar._applyColor('hiliteColor', 'transparent', this._anchorBtn);\n if (applied !== false) {\n this._toolbar._updateColorIndicator(this._mode, null);\n this.close();\n }\n }\n\n /* ── helpers ───────────────────────────────────────────────────── */\n }, {\n key: \"_titleLabel\",\n value: function _titleLabel() {\n return this._mode === 'foreColor' ? _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('inline_toolbar.text_color') : _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('inline_toolbar.highlight_color');\n }\n }, {\n key: \"_getRecentColors\",\n value: function _getRecentColors() {\n var builder = this._toolbar && this._toolbar._builder;\n if (!builder) return [];\n var key = this._mode === 'foreColor' ? '_recentTextColors' : '_recentHighlightColors';\n var arr = Array.isArray(builder[key]) ? builder[key] : [];\n return arr.slice();\n }\n }, {\n key: \"_pushRecent\",\n value: function _pushRecent(hex) {\n var builder = this._toolbar && this._toolbar._builder;\n if (!builder) return;\n if (hex === 'inherit' || hex === 'transparent') return;\n var key = this._mode === 'foreColor' ? '_recentTextColors' : '_recentHighlightColors';\n var arr = Array.isArray(builder[key]) ? builder[key].slice() : [];\n var idx = arr.findIndex(function (c) {\n return c.toLowerCase() === hex.toLowerCase();\n });\n if (idx >= 0) arr.splice(idx, 1);\n arr.unshift(hex);\n if (arr.length > RECENT_MAX) arr = arr.slice(0, RECENT_MAX);\n builder[key] = arr;\n }\n\n /* ── dismiss ───────────────────────────────────────────────────── */\n }, {\n key: \"_registerDismissListeners\",\n value: function _registerDismissListeners() {\n var _this3 = this;\n this._onDocKey = function (e) {\n if (e.key === 'Escape') {\n e.stopPropagation();\n _this3.close();\n }\n };\n document.addEventListener('keydown', this._onDocKey, true);\n this._onDocMouseDown = function (e) {\n if (!_this3.domNode) return;\n var t = e.target;\n if (_this3.domNode.contains(t)) return;\n if (t && _this3._anchorBtn && _this3._anchorBtn.contains(t)) return;\n _this3.close();\n };\n setTimeout(function () {\n if (_this3._mounted) document.addEventListener('mousedown', _this3._onDocMouseDown, true);\n }, 0);\n }\n }, {\n key: \"_unregisterDismissListeners\",\n value: function _unregisterDismissListeners() {\n if (this._onDocKey) {\n document.removeEventListener('keydown', this._onDocKey, true);\n this._onDocKey = null;\n }\n if (this._onDocMouseDown) {\n document.removeEventListener('mousedown', this._onDocMouseDown, true);\n this._onDocMouseDown = null;\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextColorPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/TextColorPopoverOverlay.js?");
/***/ }),
/***/ "./src/includes/overlays/TextInlineToolbarOverlay.js":
/*!***********************************************************!*\
!*** ./src/includes/overlays/TextInlineToolbarOverlay.js ***!
\***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\n/* harmony import */ var _TextColorPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./TextColorPopoverOverlay.js */ \"./src/includes/overlays/TextColorPopoverOverlay.js\");\n/* harmony import */ var _LinkOnSelectionPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./LinkOnSelectionPopoverOverlay.js */ \"./src/includes/overlays/LinkOnSelectionPopoverOverlay.js\");\n/* harmony import */ var _FontPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FontPopoverOverlay.js */ \"./src/includes/overlays/FontPopoverOverlay.js\");\n/* harmony import */ var _AIRewritePopoverOverlay_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./AIRewritePopoverOverlay.js */ \"./src/includes/overlays/AIRewritePopoverOverlay.js\");\n/* harmony import */ var _RichDropdownMenuOverlay_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./RichDropdownMenuOverlay.js */ \"./src/includes/overlays/RichDropdownMenuOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * TextInlineToolbarOverlay — floating pill that follows the user's text\n * selection and exposes the everyday RANGE-LEVEL formatting controls\n * (bold / italic / underline / strike) plus mount points for the later\n * popover waves (color, link, More menu, Font, Advanced, AI rewrite).\n *\n * Text alignment (L/C/R/J) was shipped in the first W1.1 cut but RETIRED\n * 2026-04-20 per TEXT_INLINE_PLAN D13/D14 — text-align is a BLOCK-LEVEL\n * CSS property (`<p style=\"text-align\">` not `<span style>`) so inline\n * align buttons would falsely promise range scope while actually mutating\n * the whole block (scope-honesty test FAIL — see BUILDER.md Hardened\n * Rules §D13). Alignment now lives exclusively in the sidebar\n * AlignControl on the owning element.\n *\n * TEXT_INLINE_PLAN W1.1 (2026-04-20). Primary release of Wave 1. Sits on\n * top of the W0 foundation:\n * - W0.2b stamps `data-bjs-inline-text` on every inline-edit surface.\n * - W0.3 (TextSelectionTracker) emits `text-selection:change` +\n * `text-selection:clear` on `builder.events`.\n * - W0.4 (ToolbarPositioner.attach) keeps the pill pinned to the\n * selection range through scroll / resize / anchor-resize.\n * - W0.5 (InlineSanitizer.normalize) canonicalises browser-divergent\n * markup after every `execCommand` (Safari `<b>` → `<strong>` etc).\n *\n * Unlike BaseOverlay, this toolbar is NOT element-scoped — selection is\n * the source of truth (HARD RULE T1). A single instance lives on the\n * Builder (`builder._textInlineToolbar`), subscribes to the bus, mounts\n * on change, unmounts on clear. Element click never opens it; focus\n * loss alone never opens it; only a non-collapsed selection inside a\n * `[data-bjs-inline-text]` host does.\n *\n * Format apply never rerenders (HARD RULE T2). Bold / italic / underline\n * / strike all go through `iframeDoc.execCommand()`, then\n * `InlineSanitizer.normalize()` runs in-place on the host so round-trip\n * invariants hold, then the tracker is asked for a fresh read so button\n * `.is-active` / `.is-mixed` states update without a full re-render.\n *\n * Stub buttons (Color W1.2 · Highlight W1.2 · Link W1.3 · More W2.1 ·\n * Font W3.1 · Advanced W4.1 · AI W6.1) are visible but inert in W1.1.\n * They emit `text-inline-toolbar:open-{key}` on the bus so the later\n * waves can subscribe without re-authoring the chrome. Their tooltip\n * carries the wave hint (\"Coming in W1.2\") and they render the\n * `.is-stub` state so the user sees the button works but the popover\n * isn't wired yet. HARD RULE T6 — failure is visible, not silent.\n *\n * Iframe coordinate translation: the tracker's range lives in the\n * builder iframe; the toolbar lives in the parent document. We\n * translate iframe-relative rects into parent-viewport coords before\n * feeding them to ToolbarPositioner. (The same trick\n * FloatingActionBarOverlay.position() uses.)\n */\n\n\n\n\n\n\n\n\n\n\n\n// Stub map: button key → wave that ships it, for tooltip hint + bus event.\nvar STUB_WAVES = Object.freeze({\n 'text-color': 'W1.2',\n 'highlight-color': 'W1.2',\n 'link': 'W1.3',\n 'more': 'W2.1',\n 'font': 'W3.1',\n 'advanced': 'W4.1',\n 'ai-rewrite': 'W6.1',\n 'paragraph-style': 'W2.3'\n});\n\n// WYSIWYG production-render gate. A stub button renders on the live\n// canvas toolbar ONLY when its flag here is true; otherwise the user\n// sees only wired-up buttons (honest \"what-ships-is-what-user-sees\"\n// discipline). Showcase mocks (demo/_partials/design/components.php +\n// host-side static spec pages) render every button statically regardless\n// of this gate — the showcase\n// is a DESIGN SPEC reference, production is a WYSIWYG manifest. When a\n// wave ships (W1.2/W1.3/W2.1/W2.3/W3.1/W4.1/W6.1), flip the corresponding\n// flag here AND add the real behaviour — the stub's bus-event path stays\n// until the real popover subscriber replaces it.\nvar SHIPPED_STUBS = Object.freeze({\n 'paragraph-style': false,\n // W2.3 Paragraph Styles submenu\n 'text-color': true,\n // W1.2 Color popover (foreground) — SHIPPED\n 'highlight-color': true,\n // W1.2 Color popover (background) — SHIPPED\n 'link': true,\n // W1.3 Link-on-Selection popover — SHIPPED\n 'more': true,\n // W2.2 More menu (clipboard + format + remove-link)\n 'font': true,\n // W3.1 Font popover — SHIPPED\n 'advanced': false,\n // W4.1 Advanced popover (dual-mount shared controls)\n 'ai-rewrite': true // W6.1 AI rewrite popover — SHIPPED\n});\n\n// Simple in-toolbar icon name → Material Symbols glyph. We rely on the\n// parent document having the font loaded (builder chrome + the engine's\n// peer-dep auto-injector both ensure this). InlineIcons registry exists\n// but its catalog does not cover\n// formatting glyphs — using the font directly is both cheaper and\n// keeps the icon set swappable at theme level.\nvar ICONS = Object.freeze({\n bold: 'format_bold',\n italic: 'format_italic',\n underline: 'format_underlined',\n strikeThrough: 'strikethrough_s',\n // `title` and `ink_highlighter` are the underline-free variants — the\n // colored-bar indicator under the icon is rendered by CSS, so the icon\n // MUST NOT carry its own built-in underline (would double up into a\n // broken-looking stripe). `format_color_text` + `format_ink_highlighter`\n // DO carry a baked line and are rejected.\n 'text-color': 'title',\n 'highlight-color': 'ink_highlighter',\n link: 'link',\n 'align-left': 'format_align_left',\n 'align-center': 'format_align_center',\n 'align-right': 'format_align_right',\n 'align-justify': 'format_align_justify',\n more: 'more_horiz',\n font: 'text_format',\n advanced: 'tune',\n 'ai-rewrite': 'auto_awesome'\n});\n\n// Platform-aware modifier glyph for tooltip shortcut hints.\nvar MOD = typeof navigator !== 'undefined' && /Mac|iPhone|iPad|iPod/.test(navigator.platform) ? '⌘' : 'Ctrl+';\nvar TextInlineToolbarOverlay = /*#__PURE__*/function () {\n /**\n * @param {Builder} host — owner. Reads `host.iframe`,\n * `host.events`, `host.textSelectionTracker`.\n */\n function TextInlineToolbarOverlay(host) {\n _classCallCheck(this, TextInlineToolbarOverlay);\n if (!host) {\n throw new Error('TextInlineToolbarOverlay: host is required');\n }\n this._builder = host;\n this._bus = host.events;\n this.domNode = null;\n this._mounted = false;\n this._positionHandle = null;\n this._currentPayload = null;\n this._offChange = null;\n this._offClear = null;\n // W1.2 color popover singleton — at most one popover open at a\n // time. When user clicks Text color while Highlight popover is\n // already open, we swap (close → open) rather than stack.\n this._colorPopover = null;\n // W1.3 link-on-selection popover singleton. Same single-popover\n // invariant — opening Link while a color popover is open swaps;\n // opening a color popover while Link is open swaps the other way.\n this._linkPopover = null;\n // W3.1 font popover singleton. Extends the invariant to 4-way\n // {color, link, font, AI} — at most ONE popover open.\n this._fontPopover = null;\n // W2.2 more-menu singleton (RichDropdownMenuOverlay instance).\n // Extends the single-popover invariant to 5-way {color, link, font,\n // more, AI} — opening any of the 5 closes the other 4.\n this._moreMenu = null;\n // W2.2 clipboard snapshot — captured at menu-open time so async\n // clipboard writes survive the menu-close focus race. Threaded\n // through `_runMoreMenuAction` as a local so the subsequent\n // close cascade can null this field without affecting in-flight\n // copy/cut promises.\n this._moreSnapshot = null;\n this._onSelectionChange = this._onSelectionChange.bind(this);\n this._onSelectionClear = this._onSelectionClear.bind(this);\n }\n\n /** Subscribe to the selection bus. Idempotent. */\n return _createClass(TextInlineToolbarOverlay, [{\n key: \"attach\",\n value: function attach() {\n if (this._offChange) return;\n this._offChange = this._bus.on('text-selection:change', this._onSelectionChange);\n this._offClear = this._bus.on('text-selection:clear', this._onSelectionClear);\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-inline-toolbar', 'attached');\n }\n\n /** Unsubscribe + tear down any mounted chrome. */\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (this._offChange) {\n this._offChange();\n this._offChange = null;\n }\n if (this._offClear) {\n this._offClear();\n this._offClear = null;\n }\n this._unmount();\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-inline-toolbar', 'destroyed');\n }\n\n /* ── Bus handlers ─────────────────────────────────────────────── */\n }, {\n key: \"_onSelectionChange\",\n value: function _onSelectionChange(payload) {\n this._currentPayload = payload;\n if (!this._mounted) {\n this._mount();\n } else {\n this._updateButtonStates(payload);\n if (this._positionHandle) this._positionHandle.reposition();\n }\n }\n }, {\n key: \"_onSelectionClear\",\n value: function _onSelectionClear() {\n this._unmount();\n }\n\n /* ── Mount / unmount ──────────────────────────────────────────── */\n }, {\n key: \"_mount\",\n value: function _mount() {\n var _this = this;\n if (this._mounted) return;\n try {\n this._build();\n document.body.appendChild(this.domNode);\n this._updateButtonStates(this._currentPayload);\n this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].attach({\n anchor: function anchor() {\n return _this._computeAnchorRect();\n },\n target: this.domNode,\n offset: 8,\n collisionPadding: 12,\n preferredSide: 'above',\n flip: true\n });\n this._mounted = true;\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-inline-toolbar:mount', this._currentPayload && this._currentPayload.elementUid);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:mount', err);\n this._unmount(); // partial-state rollback\n }\n }\n }, {\n key: \"_unmount\",\n value: function _unmount() {\n if (!this._mounted && !this.domNode) return;\n // Any open color / link / font / more popover goes with the toolbar\n // — otherwise they would linger anchored to a button that no longer\n // exists. 5-way single-popover invariant (color/link/font/more/AI).\n this._closeColorPopover();\n this._closeLinkPopover();\n this._closeFontPopover();\n this._closeMoreMenu();\n if (this._activePopover && typeof this._activePopover.close === 'function') {\n try {\n this._activePopover.close();\n } catch (_) {}\n this._activePopover = null;\n }\n if (this._positionHandle) {\n try {\n this._positionHandle.dispose();\n } catch (_) {}\n this._positionHandle = null;\n }\n if (this.domNode && this.domNode.parentNode) {\n try {\n this.domNode.parentNode.removeChild(this.domNode);\n } catch (_) {}\n }\n this.domNode = null;\n this._mounted = false;\n this._currentPayload = null;\n }\n }, {\n key: \"_computeAnchorRect\",\n value: function _computeAnchorRect() {\n var payload = this._currentPayload;\n if (!payload || !payload.range) return null;\n // Range.getBoundingClientRect() returns viewport coords in the\n // range's OWN document (the iframe). Translate by the iframe's\n // own rect in the parent document. Same translation the\n // FloatingActionBarOverlay uses for its corner anchor.\n var rr = payload.range.getBoundingClientRect();\n var iframe = this._builder.iframe;\n var ir = iframe ? iframe.getBoundingClientRect() : {\n top: 0,\n left: 0\n };\n return {\n top: ir.top + rr.top,\n left: ir.left + rr.left,\n width: rr.width,\n height: rr.height\n };\n }\n\n /* ── DOM build ────────────────────────────────────────────────── */\n }, {\n key: \"_build\",\n value: function _build() {\n var t = document.createElement('div');\n t.className = 'bjs-ovl bjs-ovl-text-inline-toolbar';\n t.setAttribute('role', 'toolbar');\n t.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.aria_label'));\n t.setAttribute('data-interactive', '');\n\n // Preserve iframe selection: mousedown on a button would steal\n // focus from the iframe and collapse the selection; preventing\n // default on mousedown keeps the range alive so execCommand\n // targets the right text. Same trick RichTextControl uses.\n t.addEventListener('mousedown', function (e) {\n // Let inputs / color pickers still take focus (future W1.2),\n // but block bare button clicks. In W1.1 every target is a\n // button or divider so the blanket preventDefault is safe.\n if (e.target && e.target.closest('input, textarea, select')) return;\n e.preventDefault();\n });\n\n // Group 1 — paragraph-style chip (W2.3). Hidden until shipped.\n if (SHIPPED_STUBS['paragraph-style']) {\n t.appendChild(this._makeParagraphStyleChip());\n t.appendChild(this._divider());\n }\n\n // Group 2 — formatting toggles (always shipped — W1.1 core)\n var formatGroup = this._group();\n formatGroup.appendChild(this._makeToggleButton('bold', MOD + 'B'));\n formatGroup.appendChild(this._makeToggleButton('italic', MOD + 'I'));\n formatGroup.appendChild(this._makeToggleButton('underline', MOD + 'U'));\n formatGroup.appendChild(this._makeToggleButton('strikeThrough', MOD + '⇧X'));\n t.appendChild(formatGroup);\n\n // Group 3 — align segmented (restored 2026-04-20, reimplemented\n // via formatter write path — NOT execCommand). Both sidebar\n // AlignControl and this inline group now write to the same\n // `element.formatter.text_align` + call `element.applyFormatStyles()`\n // → single write path, no data-race. After write, we emit\n // `formatter:change` on `builder.events` so any subscribing sidebar\n // Control (future W4.1 dual-mount) re-reads state. Refer to\n // TEXT_INLINE_PLAN §10 D13 v5 for the single-write-path rule.\n t.appendChild(this._divider());\n var alignGroup = this._group('bjs-toolbar-segmented');\n alignGroup.setAttribute('role', 'group');\n alignGroup.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.alignment'));\n alignGroup.appendChild(this._makeAlignButton('left', MOD + '⇧L'));\n alignGroup.appendChild(this._makeAlignButton('center', MOD + '⇧E'));\n alignGroup.appendChild(this._makeAlignButton('right', MOD + '⇧R'));\n alignGroup.appendChild(this._makeAlignButton('justify', MOD + '⇧J'));\n t.appendChild(alignGroup);\n\n // Group 4 — color + link (W1.2 shipped, W1.3 still stub).\n if (SHIPPED_STUBS['text-color'] || SHIPPED_STUBS['highlight-color'] || SHIPPED_STUBS['link']) {\n t.appendChild(this._divider());\n var colorGroup = this._group();\n // W1.2 — TextColorPopoverOverlay opens on click (foreColor).\n if (SHIPPED_STUBS['text-color']) colorGroup.appendChild(this._makeColorButton('text-color', 'foreColor', 'inline_toolbar.text_color'));\n // W1.2 — TextColorPopoverOverlay opens on click (hiliteColor).\n if (SHIPPED_STUBS['highlight-color']) colorGroup.appendChild(this._makeColorButton('highlight-color', 'hiliteColor', 'inline_toolbar.highlight_color'));\n if (SHIPPED_STUBS['link']) colorGroup.appendChild(this._makeLinkButton('inline_toolbar.link', MOD + 'K'));\n t.appendChild(colorGroup);\n }\n\n // Group 5 — More / Font / Advanced / AI stubs (W2.1 / W3.1 / W4.1 / W6.1).\n var hasMiscStub = SHIPPED_STUBS['more'] || SHIPPED_STUBS['font'] || SHIPPED_STUBS['advanced'] || SHIPPED_STUBS['ai-rewrite'];\n if (hasMiscStub) {\n t.appendChild(this._divider());\n var miscGroup = this._group();\n if (SHIPPED_STUBS['more']) miscGroup.appendChild(this._makeMoreButton('inline_toolbar.more'));\n if (SHIPPED_STUBS['font']) miscGroup.appendChild(this._makeFontButton('inline_toolbar.font'));\n if (SHIPPED_STUBS['advanced']) miscGroup.appendChild(this._makeStubButton('advanced', 'inline_toolbar.advanced'));\n if (SHIPPED_STUBS['ai-rewrite']) miscGroup.appendChild(this._makeAIRewriteButton('inline_toolbar.ai_rewrite'));\n t.appendChild(miscGroup);\n }\n this.domNode = t;\n }\n }, {\n key: \"_divider\",\n value: function _divider() {\n var d = document.createElement('span');\n d.className = 'bjs-toolbar-divider';\n d.setAttribute('aria-hidden', 'true');\n return d;\n }\n }, {\n key: \"_group\",\n value: function _group(extraClass) {\n var g = document.createElement('span');\n g.className = 'bjs-toolbar-group' + (extraClass ? ' ' + extraClass : '');\n return g;\n }\n }, {\n key: \"_makeIconBtn\",\n value: function _makeIconBtn(iconKey) {\n var btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'bjs-ovl-pill bjs-toolbar-btn';\n if (ICONS[iconKey]) {\n var ic = document.createElement('span');\n ic.className = 'material-symbols-rounded';\n ic.setAttribute('aria-hidden', 'true');\n ic.textContent = ICONS[iconKey];\n btn.appendChild(ic);\n }\n return btn;\n }\n }, {\n key: \"_makeToggleButton\",\n value: function _makeToggleButton(cmd, shortcutHint) {\n var _this2 = this;\n var btn = this._makeIconBtn(cmd);\n var labelKey = 'inline_toolbar.' + (cmd === 'bold' ? 'bold' : cmd === 'italic' ? 'italic' : cmd === 'underline' ? 'underline' : 'strikethrough');\n var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n btn.setAttribute('aria-label', label);\n btn.setAttribute('aria-pressed', 'false');\n btn.setAttribute('data-format-key', cmd);\n btn.setAttribute('data-tooltip', shortcutHint ? \"\".concat(label, \" (\").concat(shortcutHint, \")\") : label);\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this2._applyToggle(cmd, btn);\n });\n return btn;\n }\n\n /**\n * W1.2 — Color button. Renders like a stub button (same icon, same\n * chrome) but on click opens `TextColorPopoverOverlay` anchored to\n * itself. `mode` picks which execCommand target to write.\n */\n }, {\n key: \"_makeColorButton\",\n value: function _makeColorButton(key, mode, labelKey) {\n var _this3 = this;\n var btn = this._makeIconBtn(key);\n var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n btn.classList.add('bjs-toolbar-color-btn');\n btn.setAttribute('aria-label', label);\n btn.setAttribute('aria-haspopup', 'dialog');\n btn.setAttribute('aria-expanded', 'false');\n btn.setAttribute('data-color-key', key);\n btn.setAttribute('data-color-mode', mode);\n btn.setAttribute('data-tooltip', label);\n // DO NOT set `--bjs-color-current` inline at mount. CSS renders\n // the bar in theme-default text color via the fallback chain\n // `var(--bjs-color-current, var(--bjs-text, #111))`; inline var\n // only gets set AFTER the user actually picks a color via the\n // popover. User rule 2026-04-21: \"dùng màu chữ khi reset hay\n // ban đầu mới mở chưa chọn\".\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this3._toggleColorPopover(mode, btn);\n });\n return btn;\n }\n\n /**\n * Update the underline color bar on the toolbar's Text-color or\n * Highlight button. Called by `TextColorPopoverOverlay` after a\n * successful apply OR after Reset. HARD RULE T6: this is a visible\n * confirmation the user's pick landed.\n *\n * `hex` semantics:\n * - Valid hex / rgb string → set inline `--bjs-color-current` so\n * that color wins over the CSS theme-default fallback.\n * - `null` / `'transparent'` / `'inherit'` / undefined → REMOVE\n * the inline var so the CSS falls back to `var(--bjs-text)`\n * (light=#111, dark=#e5e7eb). This is the Reset / initial path.\n */\n }, {\n key: \"_updateColorIndicator\",\n value: function _updateColorIndicator(mode, hex) {\n if (!this.domNode) return;\n var btn = this.domNode.querySelector(\"[data-color-mode=\\\"\".concat(mode, \"\\\"]\"));\n if (!btn) return;\n var isResetLike = !hex || hex === 'transparent' || hex === 'inherit';\n if (isResetLike) {\n btn.style.removeProperty('--bjs-color-current');\n } else {\n btn.style.setProperty('--bjs-color-current', hex);\n }\n }\n }, {\n key: \"_toggleColorPopover\",\n value: function _toggleColorPopover(mode, btn) {\n // If an existing popover is open — either from the same button\n // (toggle-off) or a sibling color button (swap) — close first.\n if (this._colorPopover && this._colorPopover.isOpen()) {\n var sameAnchor = this._colorPopover._anchorBtn === btn;\n this._closeColorPopover();\n if (sameAnchor) return; // toggle-off\n }\n // Sibling single-popover invariant — close any open link / font /\n // more popover so at most one of {color, link, font, more, AI} is\n // visible.\n this._closeLinkPopover();\n this._closeFontPopover();\n this._closeMoreMenu();\n var initial = this._readInitialColor(mode);\n var pop = new _TextColorPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](this, {\n mode: mode,\n anchorBtn: btn,\n initialColor: initial\n });\n pop.open();\n this._colorPopover = pop;\n btn.setAttribute('aria-expanded', 'true');\n }\n }, {\n key: \"_closeColorPopover\",\n value: function _closeColorPopover() {\n if (this._colorPopover) {\n var prevBtn = this._colorPopover._anchorBtn;\n try {\n this._colorPopover.close();\n } catch (_) {}\n this._colorPopover = null;\n if (prevBtn) prevBtn.setAttribute('aria-expanded', 'false');\n }\n }\n\n /**\n * W1.3 — Link-on-selection button. Renders like the color buttons\n * (own chrome class, aria-haspopup, aria-expanded) and on click opens\n * the `LinkOnSelectionPopoverOverlay` anchored to itself.\n */\n }, {\n key: \"_makeLinkButton\",\n value: function _makeLinkButton(labelKey, shortcutHint) {\n var _this4 = this;\n var btn = this._makeIconBtn('link');\n var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n btn.classList.add('bjs-toolbar-link-btn');\n btn.setAttribute('aria-label', label);\n btn.setAttribute('aria-haspopup', 'dialog');\n btn.setAttribute('aria-expanded', 'false');\n btn.setAttribute('data-link-btn', '1');\n btn.setAttribute('data-tooltip', shortcutHint ? \"\".concat(label, \" (\").concat(shortcutHint, \")\") : label);\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this4._toggleLinkPopover(btn);\n });\n return btn;\n }\n }, {\n key: \"_toggleLinkPopover\",\n value: function _toggleLinkPopover(btn) {\n // Toggle-off if same button while already open.\n if (this._linkPopover && this._linkPopover.isOpen()) {\n this._closeLinkPopover();\n return;\n }\n // Single-popover invariant — close sibling popovers before opening.\n this._closeColorPopover();\n this._closeFontPopover();\n this._closeMoreMenu();\n if (this._activePopover && typeof this._activePopover.close === 'function') {\n try {\n this._activePopover.close();\n } catch (_) {}\n this._activePopover = null;\n }\n var pop = new _LinkOnSelectionPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](this, {\n anchorBtn: btn\n });\n pop.open();\n this._linkPopover = pop;\n }\n }, {\n key: \"_closeLinkPopover\",\n value: function _closeLinkPopover() {\n if (this._linkPopover) {\n try {\n this._linkPopover.close();\n } catch (_) {}\n this._linkPopover = null;\n }\n }\n\n /**\n * W3.1 — Font button. Opens `FontPopoverOverlay` anchored to itself.\n * Same mount/dismiss chrome as W1.3's Link button.\n */\n }, {\n key: \"_makeFontButton\",\n value: function _makeFontButton(labelKey) {\n var _this5 = this;\n var btn = this._makeIconBtn('font');\n var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n btn.classList.add('bjs-toolbar-font-btn');\n btn.setAttribute('aria-label', label);\n btn.setAttribute('aria-haspopup', 'dialog');\n btn.setAttribute('aria-expanded', 'false');\n btn.setAttribute('data-font-btn', '1');\n btn.setAttribute('data-tooltip', label);\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this5._toggleFontPopover(btn);\n });\n return btn;\n }\n }, {\n key: \"_toggleFontPopover\",\n value: function _toggleFontPopover(btn) {\n if (this._fontPopover && this._fontPopover.isOpen()) {\n this._closeFontPopover();\n return;\n }\n // Single-popover invariant — close sibling popovers first.\n this._closeColorPopover();\n this._closeLinkPopover();\n this._closeMoreMenu();\n if (this._activePopover && typeof this._activePopover.close === 'function') {\n try {\n this._activePopover.close();\n } catch (_) {}\n this._activePopover = null;\n }\n var pop = new _FontPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](this, {\n anchorBtn: btn\n });\n pop.open();\n this._fontPopover = pop;\n }\n }, {\n key: \"_closeFontPopover\",\n value: function _closeFontPopover() {\n if (this._fontPopover) {\n try {\n this._fontPopover.close();\n } catch (_) {}\n this._fontPopover = null;\n }\n }\n\n /**\n * W2.2 — More button. Opens a `RichDropdownMenuOverlay` anchored to\n * itself carrying the curated clipboard + format + remove-link rows.\n * Same single-popover invariant as the other 4 popovers — opening\n * this closes {color, link, font, AI}; opening any of those closes\n * this.\n */\n }, {\n key: \"_makeMoreButton\",\n value: function _makeMoreButton(labelKey) {\n var _this6 = this;\n var btn = this._makeIconBtn('more');\n var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n btn.classList.add('bjs-toolbar-more-btn');\n btn.setAttribute('aria-label', label);\n btn.setAttribute('aria-haspopup', 'menu');\n btn.setAttribute('aria-expanded', 'false');\n btn.setAttribute('data-more-btn', '1');\n btn.setAttribute('data-tooltip', label);\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this6._toggleMoreMenu(btn);\n });\n return btn;\n }\n }, {\n key: \"_toggleMoreMenu\",\n value: function _toggleMoreMenu(btn) {\n var _this7 = this;\n if (this._moreMenu && this._moreMenu.isOpen()) {\n this._closeMoreMenu();\n return;\n }\n this._closeColorPopover();\n this._closeLinkPopover();\n this._closeFontPopover();\n if (this._activePopover && typeof this._activePopover.close === 'function') {\n try {\n this._activePopover.close();\n } catch (_) {}\n this._activePopover = null;\n }\n // Snapshot the selection's HTML + text + range-character-offsets NOW,\n // before the menu mounts — by the time a menu row's onSelect fires,\n // the menu DOM has already unmounted + focus may have bounced,\n // invalidating any live range reference. Snapshot lets the async\n // clipboard path always have stable data (HARD RULE T6 — failure\n // visible only when the operation genuinely can't complete, not\n // because focus raced with the menu close).\n this._moreSnapshot = this._captureSelectionSnapshot();\n var sections = this._buildMoreMenuSections();\n var menu = new _RichDropdownMenuOverlay_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"]({\n anchorEl: btn,\n ariaLabel: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.more'),\n sections: sections,\n preferredSide: 'below',\n // Activation runs BEFORE close — we need the selection to\n // still be live. `onSelect` returns nothing so the menu\n // auto-closes after the action handler schedules its work.\n onSelect: function onSelect(id) {\n _this7._runMoreMenuAction(id, btn);\n },\n onClose: function onClose() {\n _this7._moreMenu = null;\n }\n });\n menu.open();\n this._moreMenu = menu;\n }\n }, {\n key: \"_closeMoreMenu\",\n value: function _closeMoreMenu() {\n if (this._moreMenu) {\n var wasOpen = this._moreMenu.isOpen();\n try {\n this._moreMenu.close();\n } catch (_) {}\n this._moreMenu = null;\n if (wasOpen && this.domNode) {\n var btn = this.domNode.querySelector('[data-more-btn]');\n if (btn) btn.setAttribute('aria-expanded', 'false');\n }\n }\n // Drop the snapshot when the menu closes WITHOUT firing an action\n // (Escape / outside-click / toggle-off). Actions that fire first\n // consume the snapshot synchronously via `_runMoreMenuAction`'s\n // dispatched handler, which runs BEFORE close cascade. This leaves\n // `_moreSnapshot` stale for the async path — that's intentional,\n // the async handler already captured its reference synchronously.\n this._moreSnapshot = null;\n }\n\n /**\n * Shape the 3-section dropdown for the current selection. Disabled\n * states are computed once at menu-open time (static config — matches\n * RichDropdownMenuOverlay's contract). Paste Format disabled when\n * `builder._formatClipboard` empty; Remove Link disabled unless the\n * selection sits inside an `<a>` descendant of the inline-text host.\n * HARD RULE T6 — disabled rows render with `.is-disabled` visual +\n * `aria-disabled`, skipped from keyboard nav.\n *\n * Paste / Paste Plain / Paste and Match Style items were CUT\n * 2026-04-24 (post-W2.2 initial ship). Native ⌘V / Ctrl+V / right-\n * click Paste routes through `BaseElement._wireInlineEdit`'s native\n * `paste` listener which sanitises via InlineSanitizer without any\n * permission prompt — reliable path. The menu versions required\n * `navigator.clipboard.read()` which routinely rejects for focus /\n * permission / secure-context reasons, flashing the More button red\n * without landing anything — violates HARD RULE T6 (\"failure visible,\n * not silent\") + T5 (\"menu density — every item must work\"). Cutting\n * them removes the broken-looking UX; ⌘V is the one clean path.\n */\n }, {\n key: \"_buildMoreMenuSections\",\n value: function _buildMoreMenuSections() {\n var hasFormatClip = !!this._builder._formatClipboard;\n var linkScope = this._detectRemoveLinkState();\n var removeLinkDisabled = linkScope !== 'removable';\n return [{\n heading: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.heading_clipboard'),\n items: [{\n id: 'cut',\n icon: 'content_cut',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.cut'),\n shortcut: MOD + 'X'\n }, {\n id: 'copy',\n icon: 'content_copy',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.copy'),\n shortcut: MOD + 'C'\n }]\n }, {\n heading: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.heading_format'),\n items: [{\n id: 'copy-format',\n icon: 'colorize',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.copy_format'),\n shortcut: MOD + '⌥C'\n }, {\n id: 'paste-format',\n icon: 'format_paint',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.paste_format'),\n shortcut: MOD + '⌥V',\n disabled: !hasFormatClip\n }, {\n id: 'clear-format',\n icon: 'format_clear',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.clear_format'),\n shortcut: MOD + '\\\\'\n }]\n }, {\n items: [{\n id: 'remove-link',\n icon: 'link_off',\n label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.remove_link'),\n shortcut: MOD + '⇧K',\n destructive: true,\n disabled: removeLinkDisabled\n }]\n }];\n }\n\n /**\n * 'removable' — selection is inside a descendant `<a>`; `unlink`\n * will strip the anchor from the range.\n * 'host-anchor' — host itself is an `<a>` (LinkElement). The anchor\n * wraps the whole element; unlinking inside it would\n * produce a broken LinkElement. Sidebar owns this\n * case (matches W1.3's host-anchor banner).\n * 'no-link' — selection has no ancestor `<a>` inside the host.\n *\n * Only 'removable' leaves Remove Link enabled.\n */\n }, {\n key: \"_detectRemoveLinkState\",\n value: function _detectRemoveLinkState() {\n var payload = this._currentPayload;\n if (!payload || !payload.range) return 'no-link';\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n if (!idoc) return 'no-link';\n var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(payload.elementUid, \"\\\"]\"));\n if (!host) return 'no-link';\n if (host.tagName && host.tagName.toLowerCase() === 'a') return 'host-anchor';\n var ac = payload.range.commonAncestorContainer;\n var cursor = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n while (cursor && cursor !== host) {\n if (cursor.tagName && cursor.tagName.toLowerCase() === 'a') return 'removable';\n cursor = cursor.parentElement;\n }\n return 'no-link';\n }\n }, {\n key: \"_runMoreMenuAction\",\n value: function _runMoreMenuAction(id, moreBtn) {\n // Capture the snapshot into a local at dispatch time. The menu\n // close cascade nulls `this._moreSnapshot` synchronously after\n // onSelect returns — the async clipboard actions would otherwise\n // race that cleanup and read a null. Local-scoped = immune.\n var snap = this._moreSnapshot;\n switch (id) {\n case 'cut':\n this._doCut(moreBtn, snap);\n break;\n case 'copy':\n this._doCopy(moreBtn, snap);\n break;\n case 'copy-format':\n this._doCopyFormat(moreBtn);\n break;\n case 'paste-format':\n this._doPasteFormat(moreBtn);\n break;\n case 'clear-format':\n this._doClearFormat(moreBtn);\n break;\n case 'remove-link':\n this._doRemoveLink(moreBtn);\n break;\n }\n }\n\n /* ── W2.2 clipboard actions ──────────────────────────────────── */\n\n /**\n * Put the current selection onto the OS clipboard as BOTH `text/html`\n * (preserves inline markup — bold / italic / links) AND `text/plain`\n * (for paste targets that don't accept HTML). Uses the modern async\n * Clipboard API; falls back to `writeText` when the runtime lacks\n * `ClipboardItem`. HARD RULE T6 — failure flashes the More button.\n */\n }, {\n key: \"_copyRangeToClipboard\",\n value: (function () {\n var _copyRangeToClipboard2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(btn, snap) {\n var html, text, live, item, ok;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n // Prefer the snapshot taken at menu-open time — the menu close\n // cascade may have disturbed the iframe selection / focus by the\n // time this async path resumes. Fall back to live-read only if no\n // snapshot was threaded through (e.g. future keyboard-shortcut\n // caller outside the menu context).\n html = snap && snap.html != null ? snap.html : '';\n text = snap && snap.text != null ? snap.text : '';\n if (snap) {\n _context.next = 9;\n break;\n }\n live = this._captureSelectionSnapshot();\n if (live) {\n _context.next = 7;\n break;\n }\n this._flashError(btn);\n return _context.abrupt(\"return\", false);\n case 7:\n html = live.html;\n text = live.text;\n case 9:\n if (!(!text && !html)) {\n _context.next = 12;\n break;\n }\n this._flashError(btn);\n return _context.abrupt(\"return\", false);\n case 12:\n if (!(typeof navigator !== 'undefined' && navigator.clipboard && typeof window !== 'undefined' && typeof window.ClipboardItem === 'function' && typeof navigator.clipboard.write === 'function')) {\n _context.next = 23;\n break;\n }\n _context.prev = 13;\n item = new window.ClipboardItem({\n 'text/html': new Blob([html || text], {\n type: 'text/html'\n }),\n 'text/plain': new Blob([text || ''], {\n type: 'text/plain'\n })\n });\n _context.next = 17;\n return navigator.clipboard.write([item]);\n case 17:\n return _context.abrupt(\"return\", true);\n case 20:\n _context.prev = 20;\n _context.t0 = _context[\"catch\"](13);\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:copy:clipboardItem', _context.t0);\n // fall through\n case 23:\n if (!(navigator.clipboard && typeof navigator.clipboard.writeText === 'function')) {\n _context.next = 33;\n break;\n }\n _context.prev = 24;\n _context.next = 27;\n return navigator.clipboard.writeText(text || '');\n case 27:\n return _context.abrupt(\"return\", true);\n case 30:\n _context.prev = 30;\n _context.t1 = _context[\"catch\"](24);\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:copy:writeText', _context.t1);\n // fall through\n case 33:\n // Last-resort sync fallback — widely compatible, works in non-secure\n // contexts, and runs regardless of async clipboard permission state.\n // Uses a hidden textarea + `document.execCommand('copy')`. Plain-text\n // only (HTML is lost) but the user gets a working clipboard.\n ok = this._execCommandCopyFallback(text || html || '');\n if (!ok) this._flashError(btn);\n return _context.abrupt(\"return\", ok);\n case 36:\n case \"end\":\n return _context.stop();\n }\n }, _callee, this, [[13, 20], [24, 30]]);\n }));\n function _copyRangeToClipboard(_x, _x2) {\n return _copyRangeToClipboard2.apply(this, arguments);\n }\n return _copyRangeToClipboard;\n }())\n }, {\n key: \"_execCommandCopyFallback\",\n value: function _execCommandCopyFallback(text) {\n if (!text) return false;\n var ta = null;\n try {\n ta = document.createElement('textarea');\n ta.value = text;\n ta.setAttribute('readonly', '');\n ta.style.cssText = 'position:fixed;top:0;left:-9999px;opacity:0;pointer-events:none;';\n document.body.appendChild(ta);\n var prevActive = document.activeElement;\n ta.focus();\n ta.select();\n var ok = document.execCommand && document.execCommand('copy');\n // Restore focus so the toolbar's single-popover invariant +\n // subsequent tracker reads aren't disturbed.\n if (prevActive && prevActive !== document.body && typeof prevActive.focus === 'function') {\n try {\n prevActive.focus();\n } catch (_) {}\n }\n return !!ok;\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:copy:execCommand', err);\n return false;\n } finally {\n if (ta && ta.parentNode) {\n try {\n ta.parentNode.removeChild(ta);\n } catch (_) {}\n }\n }\n }\n }, {\n key: \"_doCopy\",\n value: function () {\n var _doCopy2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(btn, snap) {\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.next = 2;\n return this._copyRangeToClipboard(btn, snap);\n case 2:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, this);\n }));\n function _doCopy(_x3, _x4) {\n return _doCopy2.apply(this, arguments);\n }\n return _doCopy;\n }()\n }, {\n key: \"_doCut\",\n value: function () {\n var _doCut2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(btn, snap) {\n var copied, payload;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.next = 2;\n return this._copyRangeToClipboard(btn, snap);\n case 2:\n copied = _context3.sent;\n payload = this._currentPayload;\n if (!(!payload || !payload.range)) {\n _context3.next = 7;\n break;\n }\n if (copied) this._flashError(btn);\n return _context3.abrupt(\"return\");\n case 7:\n try {\n payload.range.deleteContents();\n this._normalizeHost();\n this._notifyContentChanged();\n this._refreshTracker();\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:cut-delete', err);\n this._flashError(btn);\n }\n case 8:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, this);\n }));\n function _doCut(_x5, _x6) {\n return _doCut2.apply(this, arguments);\n }\n return _doCut;\n }()\n /**\n * Clone the current selection into a serialisable `{ html, text }`\n * snapshot. Called at menu-open time so the async clipboard actions\n * always have stable data, even if the menu close disturbs focus.\n */\n }, {\n key: \"_captureSelectionSnapshot\",\n value: function _captureSelectionSnapshot() {\n var payload = this._currentPayload;\n if (!payload || !payload.range) return null;\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n if (!idoc) return null;\n try {\n var frag = payload.range.cloneContents();\n var tmp = idoc.createElement('div');\n tmp.appendChild(frag);\n return {\n html: tmp.innerHTML,\n text: payload.range.toString()\n };\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:snapshot', err);\n return null;\n }\n }\n\n /* ── W2.2 format actions ─────────────────────────────────────── */\n\n /**\n * Stash the resolved computed style of the selection's common ancestor\n * into `builder._formatClipboard`. Raw CSS values — no formatter\n * coupling — so Paste Format can wrap any future selection in a single\n * `<span style>` without knowing which Element owns the range. The\n * keys mirror the W2.2 plan spec: `fontFamily`, `fontWeight`,\n * `fontStyle`, `fontSize`, `color`, `backgroundColor`,\n * `textDecorationLine`, `letterSpacing`, `lineHeight`.\n */\n }, {\n key: \"_doCopyFormat\",\n value: function _doCopyFormat(btn) {\n var snap = this._snapshotComputedFormat();\n if (!snap) {\n this._flashError(btn);\n return;\n }\n this._builder._formatClipboard = snap;\n }\n\n /**\n * Wrap the current selection in a `<span style=\"…\">` carrying the\n * properties snapshotted by Copy Format. HARD RULE T2: no element\n * rerender — we go through `_applyExecCommand('insertHTML', …)` which\n * saves + restores char-offset selection across the inline rebuild\n * and runs `InlineSanitizer.normalize` to canonicalise the markup.\n * Disabled-state is computed at menu-open time; this handler is\n * defensive if the user somehow triggers it with an empty clipboard.\n */\n }, {\n key: \"_doPasteFormat\",\n value: function _doPasteFormat(btn) {\n var snap = this._builder._formatClipboard;\n if (!snap) {\n this._flashError(btn);\n return;\n }\n var css = this._cssFromFormat(snap);\n if (!css) {\n this._flashError(btn);\n return;\n }\n var payload = this._currentPayload;\n if (!payload || !payload.range) {\n this._flashError(btn);\n return;\n }\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n if (!idoc) {\n this._flashError(btn);\n return;\n }\n var frag = payload.range.cloneContents();\n var tmp = idoc.createElement('div');\n tmp.appendChild(frag);\n var innerHtml = tmp.innerHTML;\n if (!innerHtml) {\n this._flashError(btn);\n return;\n }\n var wrapped = \"<span style=\\\"\".concat(css, \"\\\">\").concat(innerHtml, \"</span>\");\n this._applyExecCommand('insertHTML', wrapped, btn);\n }\n }, {\n key: \"_doClearFormat\",\n value: function _doClearFormat(btn) {\n // `removeFormat` strips inline formatting (bold / italic /\n // font-family / color / etc.) from the selection, keeps the\n // text + block tag. `unlink` is intentionally NOT paired here —\n // users remove links via the dedicated Remove Link row so they\n // can keep character formatting without losing the anchor.\n this._applyExecCommand('removeFormat', null, btn);\n }\n }, {\n key: \"_doRemoveLink\",\n value: function _doRemoveLink(btn) {\n if (this._detectRemoveLinkState() !== 'removable') {\n this._flashError(btn);\n return;\n }\n this._applyExecCommand('unlink', null, btn);\n }\n\n /* ── W2.2 helpers ────────────────────────────────────────────── */\n\n /**\n * Resolve the inline-text host's getComputedStyle (range's common\n * ancestor). Returns `null` when the iframe doc is unavailable or\n * the range has no computed-style carrier. Reads the \"what would\n * the user see right now\" rendered style — not the formatter-\n * serialised style — so Copy Format works identically regardless\n * of which element hosts the range.\n */\n }, {\n key: \"_snapshotComputedFormat\",\n value: function _snapshotComputedFormat() {\n var payload = this._currentPayload;\n if (!payload || !payload.range) return null;\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n var iwin = idoc && idoc.defaultView;\n if (!idoc || !iwin) return null;\n var ac = payload.range.commonAncestorContainer;\n var el = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n if (!el) return null;\n var cs;\n try {\n cs = iwin.getComputedStyle(el);\n } catch (_) {\n return null;\n }\n if (!cs) return null;\n return {\n fontFamily: cs.fontFamily || '',\n fontWeight: cs.fontWeight || '',\n fontStyle: cs.fontStyle || '',\n fontSize: cs.fontSize || '',\n color: cs.color || '',\n backgroundColor: cs.backgroundColor || '',\n textDecorationLine: cs.textDecorationLine || cs.textDecoration || '',\n letterSpacing: cs.letterSpacing || '',\n lineHeight: cs.lineHeight || ''\n };\n }\n\n /**\n * Build a semicolon-separated inline CSS string from a format snapshot.\n * Drops \"default / transparent\" values so the emitted `<span>` only\n * carries meaningful overrides — matches what Paste Format should\n * visibly change.\n */\n }, {\n key: \"_cssFromFormat\",\n value: function _cssFromFormat(snap) {\n if (!snap) return '';\n var isDefaultDecoration = function isDefaultDecoration(v) {\n return !v || v === 'none' || v === 'initial' || v === 'inherit';\n };\n var isTransparent = function isTransparent(v) {\n return !v || v === 'rgba(0, 0, 0, 0)' || v === 'transparent';\n };\n var isAutoOrNormal = function isAutoOrNormal(v) {\n return !v || v === 'normal' || v === 'auto';\n };\n var parts = [];\n if (snap.fontFamily && snap.fontFamily !== 'inherit') parts.push(\"font-family: \".concat(snap.fontFamily));\n if (snap.fontWeight && snap.fontWeight !== '400' && snap.fontWeight !== 'normal') parts.push(\"font-weight: \".concat(snap.fontWeight));\n if (snap.fontStyle && snap.fontStyle !== 'normal') parts.push(\"font-style: \".concat(snap.fontStyle));\n if (snap.fontSize) parts.push(\"font-size: \".concat(snap.fontSize));\n if (snap.color) parts.push(\"color: \".concat(snap.color));\n if (!isTransparent(snap.backgroundColor)) parts.push(\"background-color: \".concat(snap.backgroundColor));\n if (!isDefaultDecoration(snap.textDecorationLine)) parts.push(\"text-decoration: \".concat(snap.textDecorationLine));\n if (!isAutoOrNormal(snap.letterSpacing)) parts.push(\"letter-spacing: \".concat(snap.letterSpacing));\n if (!isAutoOrNormal(snap.lineHeight)) parts.push(\"line-height: \".concat(snap.lineHeight));\n return parts.join('; ');\n }\n\n /**\n * Read the current computed color of the selection's common ancestor\n * so the popover can render the existing color as `.is-active`. Falls\n * back to null (no active swatch) on mixed / missing selection.\n * Intentionally conservative — HARD RULE T7 (ambiguity asks, never\n * auto-picks silently).\n */\n }, {\n key: \"_readInitialColor\",\n value: function _readInitialColor(mode) {\n var payload = this._currentPayload;\n if (!payload || !payload.range) return null;\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n if (!idoc) return null;\n var ac = payload.range.commonAncestorContainer;\n var el = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n if (!el) return null;\n var win = idoc.defaultView;\n try {\n var cs = win.getComputedStyle(el);\n var raw = mode === 'foreColor' ? cs.color : cs.backgroundColor;\n return this._rgbToHex(raw);\n } catch (_) {\n return null;\n }\n }\n }, {\n key: \"_rgbToHex\",\n value: function _rgbToHex(raw) {\n if (!raw) return null;\n // computed-style returns \"rgb(R, G, B)\" or \"rgba(R, G, B, A)\".\n // Capture alpha so a fully-transparent backgroundColor (what\n // hiliteColor='transparent' resolves to, or an element with no\n // explicit background) returns null — otherwise we'd treat\n // `rgba(0, 0, 0, 0)` as solid black and set the indicator bar\n // to #000000, which looks like \"black highlight\" to the user.\n var m = String(raw).match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)(?:\\s*,\\s*([\\d.]+))?/);\n if (!m) return null;\n var a = m[4] !== undefined ? parseFloat(m[4]) : 1;\n if (a === 0) return null;\n var r = parseInt(m[1], 10);\n var g = parseInt(m[2], 10);\n var b = parseInt(m[3], 10);\n var hex = '#' + [r, g, b].map(function (v) {\n return v.toString(16).padStart(2, '0');\n }).join('');\n return hex.toLowerCase();\n }\n\n /**\n * Called by `TextColorPopoverOverlay` when the user picks a swatch /\n * commits a hex / picks via eyedropper. Delegates to the toolbar's\n * `_applyExecCommand` pipeline so char-offset save/restore +\n * InlineSanitizer.normalize + tracker refresh all run. Returns `false`\n * when execCommand failed (popover stays open + flashes the button).\n */\n }, {\n key: \"_applyColor\",\n value: function _applyColor(mode, colorValue, btn) {\n var cmd = mode === 'foreColor' ? 'foreColor' : 'hiliteColor';\n // execCommand doesn't accept 'inherit' — emit a bare color that\n // matches the document's default. Easier: for 'inherit' remove\n // color via `removeFormat` scoped to color only (execCommand has\n // no sub-target, so we fall back to writing the element's\n // computed color).\n if (colorValue === 'inherit') {\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n var payload = this._currentPayload;\n if (idoc && payload && payload.range) {\n var ac = payload.range.commonAncestorContainer;\n var el = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(payload.elementUid, \"\\\"]\"));\n var ancestor = host ? host.parentElement || host : el;\n try {\n colorValue = idoc.defaultView.getComputedStyle(ancestor).color || '#000000';\n } catch (_) {\n colorValue = '#000000';\n }\n } else {\n colorValue = '#000000';\n }\n }\n // `execCommand('hiliteColor', 'transparent')` works in all major\n // engines for clearing highlight. `foreColor` doesn't accept\n // 'transparent' in all engines — use the computed fallback above.\n var ok = this._applyExecCommand(cmd, colorValue, btn);\n return ok;\n }\n\n /**\n * W6.1 — Sparkle button. Renders like a wired-up icon button (no\n * .is-stub) and on click opens AIRewritePopoverOverlay anchored to\n * itself. The popover handles its own selection capture (reads\n * builder._textSelectionTracker last range).\n */\n }, {\n key: \"_makeAIRewriteButton\",\n value: function _makeAIRewriteButton(labelKey) {\n var _this8 = this;\n var btn = this._makeIconBtn('ai-rewrite');\n var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n btn.classList.add('bjs-toolbar-ai-btn');\n btn.setAttribute('aria-label', label);\n btn.setAttribute('aria-haspopup', 'dialog');\n btn.setAttribute('aria-expanded', 'false');\n btn.setAttribute('data-tooltip', label);\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this8._toggleAIRewritePopover(btn);\n });\n return btn;\n }\n }, {\n key: \"_toggleAIRewritePopover\",\n value: function _toggleAIRewritePopover(anchorBtn) {\n // Close any sibling popover first (single-popover invariant).\n this._closeColorPopover();\n this._closeLinkPopover();\n this._closeFontPopover();\n this._closeMoreMenu();\n if (this._activePopover && typeof this._activePopover.close === 'function') {\n try {\n this._activePopover.close();\n } catch (_) {}\n this._activePopover = null;\n }\n var popover = new _AIRewritePopoverOverlay_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](this, {\n anchorBtn: anchorBtn,\n builder: this._builder\n });\n this._activePopover = popover;\n popover.open();\n }\n }, {\n key: \"_makeStubButton\",\n value: function _makeStubButton(key, labelKey, shortcutHint) {\n var _this9 = this;\n var btn = this._makeIconBtn(key);\n var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n var wave = STUB_WAVES[key] || '?';\n btn.classList.add('is-stub');\n btn.setAttribute('aria-label', label);\n btn.setAttribute('data-stub-key', key);\n var tooltip = \"\".concat(label, \" \\u2014 \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.coming_in').replace('{wave}', wave)).concat(shortcutHint ? \" (\".concat(shortcutHint, \")\") : '');\n btn.setAttribute('data-tooltip', tooltip);\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n // Fire bus event so future waves wire their popover without\n // re-authoring the chrome. W1.1 ships with no subscribers —\n // the click is a visible \"received but no-op\" to the user\n // via the brief .is-active pulse (CSS handles the feedback).\n _this9._bus.emit('text-inline-toolbar:open-' + key, {\n elementUid: _this9._currentPayload && _this9._currentPayload.elementUid,\n payload: _this9._currentPayload,\n button: btn\n });\n // Ephemeral is-active pulse — confirms the click landed.\n btn.classList.add('is-just-pressed');\n setTimeout(function () {\n return btn.classList.remove('is-just-pressed');\n }, 220);\n });\n return btn;\n }\n }, {\n key: \"_makeParagraphStyleChip\",\n value: function _makeParagraphStyleChip() {\n var _this10 = this;\n var btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'bjs-ovl-pill bjs-toolbar-btn bjs-toolbar-para-style is-stub';\n btn.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.paragraph_style'));\n btn.setAttribute('data-stub-key', 'paragraph-style');\n var label = document.createElement('span');\n label.className = 'bjs-toolbar-para-style-label';\n label.textContent = '—';\n btn.appendChild(label);\n var caret = document.createElement('span');\n caret.className = 'material-symbols-rounded bjs-toolbar-caret';\n caret.setAttribute('aria-hidden', 'true');\n caret.textContent = 'expand_more';\n btn.appendChild(caret);\n btn.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.paragraph_style') + ' — ' + _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.coming_in').replace('{wave}', STUB_WAVES['paragraph-style']));\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this10._bus.emit('text-inline-toolbar:open-paragraph-style', {\n elementUid: _this10._currentPayload && _this10._currentPayload.elementUid,\n payload: _this10._currentPayload,\n button: btn\n });\n btn.classList.add('is-just-pressed');\n setTimeout(function () {\n return btn.classList.remove('is-just-pressed');\n }, 220);\n });\n return btn;\n }\n }, {\n key: \"_makeAlignButton\",\n value: function _makeAlignButton(side, shortcutHint) {\n var _this11 = this;\n var btn = this._makeIconBtn('align-' + side);\n var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.align_' + side);\n btn.setAttribute('aria-label', label);\n btn.setAttribute('aria-pressed', 'false');\n btn.setAttribute('data-align-key', side);\n btn.setAttribute('data-tooltip', shortcutHint ? \"\".concat(label, \" (\").concat(shortcutHint, \")\") : label);\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this11._applyAlign(side, btn);\n });\n return btn;\n }\n\n /* ── Format apply ─────────────────────────────────────────────── */\n }, {\n key: \"_applyToggle\",\n value: function _applyToggle(cmd, btn) {\n this._applyExecCommand(cmd, null, btn);\n }\n\n /**\n * Apply text-align to the current selection's host element via the\n * formatter write path. TEXT_INLINE_PLAN D13 v5 (single write path):\n *\n * 1. `element.formatter.setFormat('text_align', side)` — writes the\n * element's serialised state. Sidebar `AlignControl` also writes\n * through this path via its `setValue` callback, so both surfaces\n * share a single source of truth. No execCommand, no `style=\"...\"`\n * DOM-scribble that bypasses the formatter.\n * 2. `element.applyFormatStyles()` — patches the element's live DOM\n * inline style in place (no full re-render, caret stays put).\n * Elements that don't expose `applyFormatStyles()` yet (Label /\n * Alert / SubmitButton pre-W5.1) fall back to `render()`; caret\n * loss is acceptable on those because they're single-word\n * elements that rarely host selections.\n * 3. `builder.events.emit('formatter:change', { elementUid, key,\n * value, source })` — broadcast so a future sidebar AlignControl\n * (or W4.1 Advanced popover's dual-mounted control) can subscribe\n * and re-read state without polling. `source` field lets\n * subscribers skip their own echoes.\n *\n * Retired 2026-04-20 (9d7df762) as an execCommand-based\n * implementation that raced sidebar formatter writes; restored same\n * day on the formatter path after the D13 decision was refined (v4\n * → v5: the rule is single-write-path, not block-vs-range). See\n * BUILDER.md Lesson 56.\n */\n }, {\n key: \"_applyAlign\",\n value: function _applyAlign(side, btn) {\n var element = this._resolveCurrentElement();\n if (!element || !element.formatter || typeof element.formatter.setFormat !== 'function') {\n this._flashError(btn);\n return;\n }\n try {\n element.formatter.setFormat('text_align', side);\n if (typeof element.applyFormatStyles === 'function') {\n element.applyFormatStyles();\n } else if (typeof element.render === 'function') {\n element.render();\n }\n this._bus.emit('formatter:change', {\n elementUid: element.id,\n key: 'text_align',\n value: side,\n source: 'text-inline-toolbar'\n });\n // Re-read pill state so the segmented group reflects the new\n // active button immediately (no bus round-trip needed for\n // our own write).\n this._updateButtonStates(this._currentPayload);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:applyAlign:' + side, err);\n this._flashError(btn);\n }\n }\n\n /**\n * Resolve the current selection's elementUid to its live Element\n * instance via `builder.uiManager.elements`. Returns null if the\n * tracker has no active payload or the instance has been\n * garbage-collected (e.g. user deleted the element mid-selection).\n */\n }, {\n key: \"_resolveCurrentElement\",\n value: function _resolveCurrentElement() {\n if (!this._currentPayload) return null;\n var uid = this._currentPayload.elementUid;\n var uiMgr = this._builder && this._builder.uiManager;\n if (!uiMgr || !Array.isArray(uiMgr.elements)) return null;\n return uiMgr.elements.find(function (el) {\n return el && el.id === uid;\n }) || null;\n }\n }, {\n key: \"_normalizeAlign\",\n value: function _normalizeAlign(v) {\n if (!v) return null;\n var s = String(v).toLowerCase();\n if (s === 'start' || s === 'left') return 'left';\n if (s === 'center') return 'center';\n if (s === 'end' || s === 'right') return 'right';\n if (s === 'justify') return 'justify';\n return null;\n }\n\n /**\n * Apply an `execCommand` against the iframe document.\n *\n * Two correctness invariants drive this method:\n *\n * (1) PRE-APPLY — the toolbar OWNS its operating range. The toolbar\n * lives in the parent document; clicking its button leaves the\n * iframe selection in an undefined state across browsers (mostly\n * fine on Chromium/macOS, but real-mouse gestures do occasionally\n * leave `iwin.getSelection()` collapsed by the time the click\n * handler runs — a focus/selection race that does NOT fire\n * `selectionchange` so the tracker can't see it). `execCommand`\n * reads the live selection silently and returns `false` when it's\n * collapsed → button red-flashes even though the user's intent\n * (`_currentPayload.range`, captured on the last `text-selection`\n * emit) is well-defined. Fix: SET the live selection to the\n * tracker's saved range immediately before `execCommand`. This is\n * the standard floating-toolbar pattern (TinyMCE / CKEditor /\n * Quill all do it). It makes the apply path deterministic and\n * independent of whatever the live selection happens to be.\n *\n * (2) POST-APPLY — the element's `input` listener mirrors\n * `host.innerHTML` back into `element.text`, which on most\n * elements rewrites `target.innerHTML = text` and detaches the\n * range's text-node refs. We save char offsets BEFORE the apply\n * and restore via TreeWalker AFTER the rewrite (HARD RULE T2 +\n * Lesson 40 / Lesson 56 precedent). Pre-W5.1 caret-stable shim.\n *\n * Failure modes are tagged on `_flashError(...)` so the next surprise\n * red flash points at the exact branch in BJS.warn output instead of\n * forcing another investigation cycle.\n */\n }, {\n key: \"_applyExecCommand\",\n value: function _applyExecCommand(cmd, value, btn) {\n var _this12 = this;\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n var iwin = idoc && idoc.defaultView;\n if (!idoc || !iwin) {\n this._flashError(btn, 'no-iframe-doc:' + cmd);\n return false;\n }\n if (!this._currentPayload) {\n this._flashError(btn, 'no-payload:' + cmd);\n return false;\n }\n var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(this._currentPayload.elementUid, \"\\\"]\"));\n if (!host) {\n this._flashError(btn, 'no-host:' + cmd);\n return false;\n }\n // (1) Sync live iframe selection to the tracker's saved range.\n // The cloned range still references the same text nodes (no DOM\n // rewrite happens between selection-change and click), so addRange\n // is a no-op when the live selection already matches and a real\n // restore when it doesn't. Either way, `execCommand` below sees a\n // valid non-collapsed range inside contenteditable.\n var savedRange = this._currentPayload.range;\n try {\n var sel = iwin.getSelection();\n sel.removeAllRanges();\n sel.addRange(savedRange);\n } catch (err) {\n // Range refs detached (host re-rendered between mount + click,\n // e.g. via a sidebar control write) — fail visibly so the bug\n // surfaces at the source instead of silently no-op'ing.\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].warn('text-inline-toolbar:pre-apply-restore:' + cmd, err);\n this._flashError(btn, 'pre-restore-throw:' + cmd);\n return false;\n }\n // (2) Char-offset snapshot for the post-apply restore.\n var offsets = this._saveSelectionOffsets(host, savedRange);\n var ok = false;\n try {\n ok = idoc.execCommand(cmd, false, value);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:execCommand:' + cmd, err);\n this._flashError(btn, 'exec-throw:' + cmd);\n return false;\n }\n if (!ok) {\n // After (1) we know the live selection is non-collapsed and\n // inside contenteditable, so `false` here means the browser\n // genuinely rejected the command (e.g. `removeFormat` over a\n // span with no inline format, or a vendor-specific edge case).\n // Log enough context to debug without a re-run.\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].warn('text-inline-toolbar:execCommand-rejected:' + cmd, {\n selectionText: iwin.getSelection().toString(),\n hostTag: host.tagName\n });\n this._flashError(btn, 'exec-false:' + cmd);\n return false;\n }\n this._normalizeHost();\n this._notifyContentChanged();\n // Defer selection restore to the next microtask so the native\n // `input` event (+ element.setText → innerHTML rewrite) has\n // finished first. Then the tracker can re-read the restored\n // selection and re-emit change, keeping the toolbar mounted.\n setTimeout(function () {\n _this12._restoreSelectionOffsets(host, offsets);\n _this12._refreshTracker();\n }, 0);\n return true;\n }\n\n /**\n * Save current selection within `host` as `{start,end}` character\n * offsets. Survives any innerHTML rebuild because offsets point to a\n * text index, not a DOM node. Returns null when the range is not\n * contained by host (caller owns the degrade).\n */\n }, {\n key: \"_saveSelectionOffsets\",\n value: function _saveSelectionOffsets(host, range) {\n if (!host || !range) return null;\n try {\n var doc = host.ownerDocument;\n var pre = doc.createRange();\n pre.selectNodeContents(host);\n pre.setEnd(range.startContainer, range.startOffset);\n var start = pre.toString().length;\n var end = start + range.toString().length;\n return {\n start: start,\n end: end\n };\n } catch (_) {\n return null;\n }\n }\n }, {\n key: \"_restoreSelectionOffsets\",\n value: function _restoreSelectionOffsets(host, offsets) {\n if (!host || !offsets) return;\n try {\n var doc = host.ownerDocument;\n var win = doc.defaultView;\n var sel = win.getSelection();\n var range = doc.createRange();\n\n // NodeFilter.SHOW_TEXT = 4\n var walker = doc.createTreeWalker(host, 4, null, false);\n var count = 0;\n var startNode = null,\n startOffset = 0;\n var endNode = null,\n endOffset = 0;\n var node;\n while (node = walker.nextNode()) {\n var len = node.textContent.length;\n var nextCount = count + len;\n if (!startNode && nextCount >= offsets.start) {\n startNode = node;\n startOffset = offsets.start - count;\n }\n if (!endNode && nextCount >= offsets.end) {\n endNode = node;\n endOffset = offsets.end - count;\n break;\n }\n count = nextCount;\n }\n // Fallback — clamp to host extents. Better to end with a\n // valid (even if collapsed) selection than throw.\n if (!startNode) {\n startNode = host;\n startOffset = 0;\n }\n if (!endNode) {\n endNode = startNode;\n endOffset = Math.min(startOffset, (startNode.textContent || '').length);\n }\n range.setStart(startNode, startOffset);\n range.setEnd(endNode, endOffset);\n sel.removeAllRanges();\n sel.addRange(range);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:restore-selection', err);\n }\n }\n }, {\n key: \"_normalizeHost\",\n value: function _normalizeHost() {\n if (!this._currentPayload) return;\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n if (!idoc) return;\n var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(this._currentPayload.elementUid, \"\\\"]\"));\n if (!host) return;\n try {\n _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"].normalize(host);\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:normalize', err);\n }\n }\n }, {\n key: \"_notifyContentChanged\",\n value: function _notifyContentChanged() {\n if (!this._currentPayload) return;\n // Mirrors what BaseElement._wireInlineEdit's `input` listener\n // does for typing — the toolbar edits the same DOM directly so\n // we must give subscribers (HistoryManager, element.text sync)\n // the same signal.\n this._bus.emit('text-inline-toolbar:content-change', {\n elementUid: this._currentPayload.elementUid\n });\n // Fire a native input event on the host so W0.2b's auto-wired\n // listener picks up the new text without the toolbar needing to\n // reach into element internals.\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n if (!idoc) return;\n var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(this._currentPayload.elementUid, \"\\\"]\"));\n if (!host) return;\n try {\n host.dispatchEvent(new idoc.defaultView.Event('input', {\n bubbles: true\n }));\n } catch (err) {\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:input-dispatch', err);\n }\n }\n }, {\n key: \"_refreshTracker\",\n value: function _refreshTracker() {\n var tracker = this._builder.textSelectionTracker;\n if (tracker && typeof tracker.refresh === 'function') {\n tracker.refresh();\n }\n }\n }, {\n key: \"_flashError\",\n value: function _flashError(btn, tag) {\n // Always surface WHY the red flash fired so debugging the next\n // surprise takes seconds. `tag` is a short branch identifier from\n // the caller (e.g. 'exec-false:bold', 'no-host:italic'); falls\n // back to a generic label for older callers without one.\n _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].warn('text-inline-toolbar:flash-error', tag || 'unknown');\n if (!btn) return;\n btn.classList.add('is-error');\n setTimeout(function () {\n return btn.classList.remove('is-error');\n }, 600);\n }\n\n /* ── State sync ───────────────────────────────────────────────── */\n }, {\n key: \"_updateButtonStates\",\n value: function _updateButtonStates(payload) {\n var _this13 = this;\n if (!this.domNode || !payload) return;\n var formats = payload.formats || {};\n\n // Toggle buttons — active + mixed from queryCommandState /\n // queryCommandIndeterm. We read `indeterm` directly from the\n // iframe document because the tracker's payload only reports\n // the start-of-selection state; indeterminate requires a live\n // query at apply time.\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n this.domNode.querySelectorAll('[data-format-key]').forEach(function (btn) {\n var key = btn.getAttribute('data-format-key');\n var active = formats[key] === true;\n var indeterm = false;\n if (idoc && typeof idoc.queryCommandIndeterm === 'function') {\n try {\n indeterm = !!idoc.queryCommandIndeterm(key);\n } catch (_) {\n indeterm = false;\n }\n }\n btn.classList.toggle('is-active', active && !indeterm);\n btn.classList.toggle('is-mixed', indeterm);\n if (indeterm) {\n btn.setAttribute('aria-checked', 'mixed');\n btn.removeAttribute('aria-pressed');\n } else {\n btn.setAttribute('aria-pressed', active ? 'true' : 'false');\n btn.removeAttribute('aria-checked');\n }\n });\n\n // Align segmented — read from element.formatter (single-write-path\n // per D13 v5). We used to query DOM inline style via\n // queryCommandState; that path was retired along with the\n // execCommand-based apply in 9d7df762. Current pill state now\n // reflects what the formatter actually serialises — the same\n // source sidebar AlignControl reads.\n var element = this._resolveCurrentElement();\n var alignVal = element && element.formatter && typeof element.formatter.getFormat === 'function' ? element.formatter.getFormat('text_align') : null;\n var align = this._normalizeAlign(alignVal);\n this.domNode.querySelectorAll('[data-align-key]').forEach(function (btn) {\n var k = btn.getAttribute('data-align-key');\n var on = k === align;\n btn.classList.toggle('is-active', on);\n btn.setAttribute('aria-pressed', on ? 'true' : 'false');\n });\n\n // Color indicators — drive both text-color + highlight-color\n // bars from the current selection's computed color. Runs on\n // every mount + every re-selection via this same code path, so\n // there's exactly one source of truth: `_readInitialColor(mode)`.\n // No separate mount-time read needed in `_makeColorButton` — the\n // first `_updateButtonStates` after mount does it. Theme fallback\n // (light: --bjs-text #111, dark: #e5e7eb) kicks in via CSS when\n // we remove the inline var (null color case, typical for a\n // reset hiliteColor where backgroundColor is transparent).\n this.domNode.querySelectorAll('[data-color-mode]').forEach(function (btn) {\n var mode = btn.getAttribute('data-color-mode');\n var hex = _this13._readInitialColor(mode);\n if (hex) {\n btn.style.setProperty('--bjs-color-current', hex);\n } else {\n btn.style.removeProperty('--bjs-color-current');\n }\n });\n\n // Link button — reflect whether selection sits inside an <a>.\n // Pre-W1.3 shipped as a stub with [data-stub-key]; W1.3 promotes\n // to a wired button with [data-link-btn]. Both kept here for any\n // transition window.\n var linkBtn = this.domNode.querySelector('[data-link-btn], [data-stub-key=\"link\"]');\n if (linkBtn) linkBtn.classList.toggle('is-active', !!formats.link);\n\n // Paragraph-style chip label — only when the chip is rendered (W2.3).\n if (this.domNode.querySelector('.bjs-toolbar-para-style-label')) {\n this._updateParagraphStyleLabel(payload);\n }\n }\n }, {\n key: \"_updateParagraphStyleLabel\",\n value: function _updateParagraphStyleLabel(payload) {\n var label = this.domNode.querySelector('.bjs-toolbar-para-style-label');\n if (!label) return;\n var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n if (!idoc || !payload) {\n label.textContent = '—';\n return;\n }\n var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(payload.elementUid, \"\\\"]\"));\n if (!host) {\n label.textContent = '—';\n return;\n }\n // The inline-edit host is the block tag itself for P / H1-6 /\n // Label / Alert-body / Link. For non-standard tags, fall back\n // to \"Text\".\n var tag = host.tagName.toLowerCase();\n var map = {\n p: 'Paragraph',\n h1: 'Heading 1',\n h2: 'Heading 2',\n h3: 'Heading 3',\n h4: 'Heading 4',\n h5: 'Heading 5',\n h6: 'Heading 6',\n a: 'Link',\n label: 'Label'\n };\n label.textContent = map[tag] || 'Text';\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextInlineToolbarOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/TextInlineToolbarOverlay.js?");
/***/ }),
/***/ "./src/includes/pricingCardIcons.js":
/*!******************************************!*\
!*** ./src/includes/pricingCardIcons.js ***!
\******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ allNames: () => (/* binding */ allNames),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ hasIcon: () => (/* binding */ hasIcon),\n/* harmony export */ render: () => (/* binding */ render)\n/* harmony export */ });\n/**\n * BuilderJS inline SVG icon registry (originally \"pricingCardIcons\").\n *\n * Replaces Material Symbols font (which doesn't load inside the builder iframe\n * theme and is unreliable in exported emails) with inline SVG paths so every\n * icon renders deterministically — builder canvas, preview iframe, exported\n * HTML, sidebar controls, and floating action bars all share one source.\n *\n * Contract:\n * - `render(name, opts)` returns an SVG string (or `<span>` fallback for\n * emoji / non-registry names), or empty string for empty input.\n * - Opts: `{ size: number (px), color: string (CSS color) }`.\n * - Icons are 24×24 viewBox, 1.75 stroke-width so they stay crisp at\n * 16px (chips), 20px (sidebar controls), 24px (overlay pills), 28-56px\n * (pricing preset thumbnails).\n *\n * Scope (2026-04-19 expansion — BUTTON_UPGRADE_PLAN):\n * Registry grew from 18 pricing-card icons to ~40 to cover every icon\n * surface in the Button refactor — overlay pills (close/link/palette/\n * settings), preset picker tick (check_circle), icon-led preset glyphs\n * (arrow_forward, download, shopping_cart, mail, play_arrow, share, add,\n * arrow_back, check, call, send, open_in_new), sidebar chevrons\n * (expand_more / expand_less / chevron_right), widget toggles. Registry\n * is generic — any element can import it.\n *\n * Each SVG is ~0.3-0.8 KB; total stays under 25 KB.\n */\n\nvar ICON_PATHS = {\n // ─── Original pricing icons ───────────────────────────────────────────\n bolt: '<path d=\"M13 3L4 14h6l-1 7 9-11h-6l1-7z\" fill=\"currentColor\" stroke=\"none\"/>',\n diamond: '<path d=\"M12 3l4 4 4-4M12 3L8 7 4 3m4 4l4 14L4 7h16l-4 14z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n workspace_premium: '<circle cx=\"12\" cy=\"10\" r=\"6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M9 15l-2 6 5-2 5 2-2-6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M12 7l1 2 2 .3-1.5 1.4.3 2L12 11.7l-1.8 1 .3-2L9 9.3 11 9z\" fill=\"currentColor\" stroke=\"none\"/>',\n rocket_launch: '<path d=\"M14 4c2 0 4 0 6 2s2 4 2 6l-4 2-6-6 2-4zM8 10l-4 2-2 4 4 4 4-2 2-4-4-4zM10 12l6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n star: '<path d=\"M12 3l2.8 6 6.2.6-4.7 4.3 1.4 6.1L12 16.8 6.3 20l1.4-6.1L3 9.6 9.2 9z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n auto_awesome: '<path d=\"M12 3l1.4 3.6L17 8l-3.6 1.4L12 13l-1.4-3.6L7 8l3.6-1.4z\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M18 14l.8 2.2L21 17l-2.2.8L18 20l-.8-2.2L15 17l2.2-.8zM6 14l.6 1.6L8 16l-1.4.4L6 18l-.6-1.6L4 16l1.4-.4z\" fill=\"currentColor\" stroke=\"none\"/>',\n terminal: '<rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M7 10l3 2-3 2M13 14h4\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n rocket: '<path d=\"M12 3c3 2 5 5 5 9 0 3-2 5-5 7-3-2-5-4-5-7 0-4 2-7 5-9z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"12\" cy=\"10\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M9 16l-2 4 3-1M15 16l2 4-3-1\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n crown: '<path d=\"M3 17l2-9 4 5 3-8 3 8 4-5 2 9z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M3 17h18v2H3z\" fill=\"currentColor\" stroke=\"none\"/>',\n favorite: '<path d=\"M12 20l-7-7a4 4 0 115.7-5.7L12 8.6l1.3-1.3a4 4 0 115.7 5.7z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n bubble_chart: '<circle cx=\"8\" cy=\"14\" r=\"4\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"16\" cy=\"9\" r=\"3\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"17\" cy=\"17\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/>',\n layers: '<path d=\"M12 3l9 5-9 5-9-5z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M3 13l9 5 9-5M3 18l9 5 9-5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n shield: '<path d=\"M12 3l8 3v6c0 5-4 8-8 9-4-1-8-4-8-9V6z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M9 12l2 2 4-4\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n verified: '<path d=\"M12 2l2.5 2 3.5-.5.5 3.5L21 9.5 19 12l2 2.5-2.5 2-.5 3.5-3.5-.5L12 22l-2.5-2-3.5.5L5.5 17 3 14.5 5 12 3 9.5l2.5-2L6 4l3.5.5z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M8 12l3 3 5-5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n flash_on: '<path d=\"M11 3L5 13h5l-1 8 8-12h-5l1-6z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"currentColor\" stroke-linejoin=\"round\"/>',\n flare: '<circle cx=\"12\" cy=\"12\" r=\"4\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M12 2v4M12 18v4M2 12h4M18 12h4M4.6 4.6l2.8 2.8M16.6 16.6l2.8 2.8M19.4 4.6l-2.8 2.8M7.4 16.6l-2.8 2.8\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n emoji_events: '<path d=\"M6 4h12v3a4 4 0 01-4 4h-4a4 4 0 01-4-4zM4 6h2v2a2 2 0 01-2-2zM20 6h-2v2a2 2 0 002-2z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M10 11v4h4v-4M8 19h8v2H8z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n local_fire_department: '<path d=\"M12 3c0 4-5 5-5 10a5 5 0 0010 0c0-2-1-3-2-4 0 2-2 2-2 0s2-4-1-6z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n // ─── Overlay + control UI ────────────────────────────────────────────\n close: '<path d=\"M6 6l12 12M18 6L6 18\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n check: '<path d=\"M5 12l4 4 10-10\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n check_circle: '<circle cx=\"12\" cy=\"12\" r=\"9\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M8 12l3 3 5-6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n link: '<path d=\"M10 14l4-4M9 17H7a4 4 0 010-8h2M15 7h2a4 4 0 010 8h-2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n edit: '<path d=\"M4 20h4L19 9l-4-4L4 16v4z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M14 6l4 4\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n palette: '<path d=\"M12 3a9 9 0 109 9c0-1.5-1-2-2-2h-2a2 2 0 010-4 2 2 0 00-2-2 9 9 0 00-3-1z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><circle cx=\"7.5\" cy=\"10.5\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"11\" cy=\"7\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"15.5\" cy=\"9\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/>',\n settings: '<circle cx=\"12\" cy=\"12\" r=\"3\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M19.4 15a1.7 1.7 0 00.3 1.9l.1.1a2 2 0 11-2.9 2.9l-.1-.1a1.7 1.7 0 00-1.9-.3 1.7 1.7 0 00-1 1.5V21a2 2 0 01-4 0v-.1a1.7 1.7 0 00-1.1-1.5 1.7 1.7 0 00-1.9.3l-.1.1a2 2 0 11-2.9-2.9l.1-.1a1.7 1.7 0 00.3-1.9 1.7 1.7 0 00-1.5-1H3a2 2 0 010-4h.1a1.7 1.7 0 001.5-1.1 1.7 1.7 0 00-.3-1.9l-.1-.1a2 2 0 112.9-2.9l.1.1a1.7 1.7 0 001.9.3H9a1.7 1.7 0 001-1.5V3a2 2 0 014 0v.1a1.7 1.7 0 001 1.5 1.7 1.7 0 001.9-.3l.1-.1a2 2 0 112.9 2.9l-.1.1a1.7 1.7 0 00-.3 1.9V9a1.7 1.7 0 001.5 1H21a2 2 0 010 4h-.1a1.7 1.7 0 00-1.5 1z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n tune: '<path d=\"M3 7h10M17 7h4M3 12h4M11 12h10M3 17h14M19 17h2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/><circle cx=\"15\" cy=\"7\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"9\" cy=\"12\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"17\" cy=\"17\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/>',\n expand_more: '<path d=\"M6 9l6 6 6-6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n expand_less: '<path d=\"M6 15l6-6 6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n chevron_right: '<path d=\"M9 6l6 6-6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n chevron_left: '<path d=\"M15 6l-6 6 6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n // ─── Button presets — icon-led glyphs ────────────────────────────────\n arrow_forward: '<path d=\"M5 12h14M13 6l6 6-6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n arrow_back: '<path d=\"M19 12H5M11 6l-6 6 6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n download: '<path d=\"M12 4v11M7 10l5 5 5-5M4 19h16\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n shopping_cart: '<path d=\"M3 4h2l2 12h12l2-8H6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><circle cx=\"9\" cy=\"20\" r=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"17\" cy=\"20\" r=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/>',\n mail: '<rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M3 7l9 6 9-6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n play_arrow: '<path d=\"M7 4l13 8-13 8z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"currentColor\" stroke-linejoin=\"round\"/>',\n share: '<circle cx=\"6\" cy=\"12\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"18\" cy=\"5\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"18\" cy=\"19\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M8 11l8-4.5M8 13l8 4.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n add: '<path d=\"M12 5v14M5 12h14\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n remove: '<path d=\"M5 12h14\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n call: '<path d=\"M5 4h4l2 5-2.5 1.5a10 10 0 005 5L15 13l5 2v4a2 2 0 01-2 2A15 15 0 013 6a2 2 0 012-2z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n send: '<path d=\"M4 20l17-8L4 4l3 8-3 8z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M7 12h14\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n open_in_new: '<path d=\"M14 4h6v6M10 14L20 4M19 13v6a1 1 0 01-1 1H5a1 1 0 01-1-1V6a1 1 0 011-1h6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n // ─── Common UI glyphs (reserved for future surfaces) ─────────────────\n menu: '<path d=\"M3 6h18M3 12h18M3 18h18\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n more_horiz: '<circle cx=\"5\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"19\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/>',\n more_vert: '<circle cx=\"12\" cy=\"5\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"19\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/>',\n info: '<circle cx=\"12\" cy=\"12\" r=\"9\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M12 10v6M12 7v.01\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n warning: '<path d=\"M12 3l10 18H2z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M12 10v4M12 17v.01\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>'\n};\nfunction render(name) {\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n if (!name || typeof name !== 'string') return '';\n var size = typeof opts.size === 'number' && opts.size > 0 ? opts.size : 24;\n var color = typeof opts.color === 'string' && opts.color ? opts.color : 'currentColor';\n var key = name.trim().toLowerCase();\n\n // Emoji / non-ASCII passthrough\n if (!/^[a-z][a-z0-9_]*$/i.test(key)) {\n return '<span style=\"font-size: ' + size + 'px; line-height: 1; display: inline-block;\">' + name + '</span>';\n }\n var path = ICON_PATHS[key];\n if (!path) {\n // Fallback: first-letter circle (subtle, works for any unknown name).\n var letter = (key.charAt(0) || '?').toUpperCase();\n var r = size / 2 - 1;\n return '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ' + size + ' ' + size + '\" width=\"' + size + '\" height=\"' + size + '\" style=\"display:inline-block;vertical-align:middle;color:' + color + ';\">' + '<circle cx=\"' + size / 2 + '\" cy=\"' + size / 2 + '\" r=\"' + r + '\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/>' + '<text x=\"' + size / 2 + '\" y=\"' + (size / 2 + size * 0.13) + '\" text-anchor=\"middle\" font-size=\"' + size * 0.55 + '\" font-weight=\"700\" font-family=\"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif\" fill=\"currentColor\">' + letter + '</text>' + '</svg>';\n }\n return '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"' + size + '\" height=\"' + size + '\" style=\"display:inline-block;vertical-align:middle;color:' + color + ';\">' + path + '</svg>';\n}\nfunction hasIcon(name) {\n if (!name || typeof name !== 'string') return false;\n var key = name.trim().toLowerCase();\n return Object.prototype.hasOwnProperty.call(ICON_PATHS, key);\n}\nfunction allNames() {\n return Object.keys(ICON_PATHS);\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n render: render,\n hasIcon: hasIcon,\n allNames: allNames\n});\n\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/pricingCardIcons.js?");
/***/ }),
/***/ "./src/includes/ui/ColorPalettePicker.js":
/*!***********************************************!*\
!*** ./src/includes/ui/ColorPalettePicker.js ***!
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * ColorPalettePicker — shared, primitive palette+custom-color picker.\n *\n * Introduced 2026-04-21 as a dedupe primitive between the canvas\n * TextColorPopoverOverlay (W1.2) and the sidebar ColorPickerControl\n * (slated for migration in the W1.2-followup phase — see TEXT_INLINE_PLAN\n * §3 W1.2+). Both surfaces need the SAME rich palette + custom hex +\n * native picker + eyedropper + Reset semantics; diverging them would\n * mean a Google-style update here today that never reaches the sidebar\n * tomorrow.\n *\n * Rendering model: opinionated DOM + BuilderJS chrome (`.bjs-color-*`\n * classes, shared with W1.2 popover). Consumer owns positioning — the\n * picker itself produces a flat `.domNode` that any container can mount.\n *\n * Interaction model: callback pair (`onPick(hex)` + `onReset()`),\n * one-shot per user action. Consumer decides:\n * - the popover closes on pick (canvas: TextColorPopoverOverlay)\n * - the sidebar stays open on pick (future sidebar ColorPickerControl)\n *\n * State model: the picker is *stateless per instance* — it renders the\n * value it was constructed with, and re-renders when `setValue(hex)` is\n * called. No internal history / selection tracking. Recent-LRU state is\n * owned by the consumer (for canvas: `builder._recentTextColors`; for\n * sidebar: future `builder._recentElementColors`), passed in as `recent`.\n *\n * Accessibility: palette grid is `role=\"group\"`; swatches are\n * `role=\"button\"` with `data-tooltip=<hex>` + `aria-label=<hex>`. Custom\n * hex input has `aria-label=\"Hex color\"`. Reset button has its own\n * aria-label. Reduced-motion-safe (no animations that imply commit).\n *\n * Whitelist for future customisation (plan §10 decision pending):\n * - `palette`: replace the default 60-swatch Google-style palette with a\n * theme-provided set. Accepts `{ main, standard, recent }` where\n * `main` is a 2-D array (rows × cols) + `standard` is a 1-D array +\n * `recent` is a 1-D array.\n * - `showEyedropper`: default true (auto-hidden when `EyeDropper`\n * unsupported); pass `false` to force-hide.\n * - `showReset`: default true. Pass `false` when the consumer has its\n * own reset affordance elsewhere.\n */\n\n\n\n// Google-style rich palette — 10 columns × 6 rows = 60 presets. Order:\n// grayscale → saturated → 2 tint rows → 2 shade rows. Mirror of the\n// spec used by Google Docs / Sheets / Slides, rendered in BuilderJS\n// chrome. The default export — consumers may override via `opts.palette`.\nvar DEFAULT_GRAYSCALE = Object.freeze(['#000000', '#434343', '#666666', '#999999', '#B7B7B7', '#CCCCCC', '#D9D9D9', '#EFEFEF', '#F3F3F3', '#FFFFFF']);\nvar DEFAULT_SATURATED = Object.freeze(['#980000', '#FF0000', '#FF9900', '#FFFF00', '#00FF00', '#00FFFF', '#4A86E8', '#0000FF', '#9900FF', '#FF00FF']);\n// Tint-4 (palest) — derived 2026-04-21 by mixing each TINT_3 value with\n// white at 50/50 so the hue column stays consistent (user rule: \"design\n// màu tone chuẩn theo hiện tại nha ko lệch á\"). Use case: background\n// washes where even TINT_3 reads too saturated — e.g., subtle callout\n// fills, disabled surface tints.\nvar DEFAULT_TINT_4 = Object.freeze(['#F3DBD7', '#F9E5E5', '#FDF2E6', '#FFF8E5', '#ECF4E9', '#E7EFF1', '#E4ECFB', '#E7F0F9', '#ECE8F4', '#F4E8EE']);\nvar DEFAULT_TINT_3 = Object.freeze(['#E6B8AF', '#F4CCCC', '#FCE5CD', '#FFF2CC', '#D9EAD3', '#D0E0E3', '#C9DAF8', '#CFE2F3', '#D9D2E9', '#EAD1DC']);\nvar DEFAULT_TINT_2 = Object.freeze(['#DD7E6B', '#EA9999', '#F9CB9C', '#FFE599', '#B6D7A8', '#A2C4C9', '#A4C2F4', '#9FC5E8', '#B4A7D6', '#D5A6BD']);\nvar DEFAULT_SHADE_1 = Object.freeze(['#CC4125', '#E06666', '#F6B26B', '#FFD966', '#93C47D', '#76A5AF', '#6D9EEB', '#6FA8DC', '#8E7CC3', '#C27BA0']);\nvar DEFAULT_SHADE_2 = Object.freeze(['#A61C00', '#CC0000', '#E69138', '#F1C232', '#6AA84F', '#45818E', '#3C78D8', '#3D85C6', '#674EA7', '#A64D79']);\nvar DEFAULT_MAIN_PALETTE = Object.freeze([DEFAULT_GRAYSCALE, DEFAULT_SATURATED, DEFAULT_TINT_4,\n// palest — best for page / callout background washes\nDEFAULT_TINT_3, DEFAULT_TINT_2, DEFAULT_SHADE_1, DEFAULT_SHADE_2]);\n// \"Standard\" row — BuilderJS curated brand hues at Tailwind 500 intensity.\nvar DEFAULT_STANDARD = Object.freeze(['#111827', '#EF4444', '#F59E0B', '#10B981', '#3B82F6', '#6366F1', '#EC4899', '#FFFFFF']);\nvar ColorPalettePicker = /*#__PURE__*/function () {\n /**\n * @param {object} opts\n * @param {string|null} opts.value — current color as `#rrggbb` or null\n * @param {function} opts.onPick(hex) — user picked a color via swatch / hex / eyedropper\n * @param {function?} opts.onReset() — user hit Reset (null-color) — defaults to `onPick(null)`\n * @param {string[]?} opts.recent — recent-LRU colors (caller-owned state)\n * @param {{main?: string[][], standard?: string[]}?} opts.palette — override palette rows\n * @param {string?} opts.title — header title; falls back to \"Palette\"\n * @param {boolean?} opts.showEyedropper — default true (auto-hidden when API missing)\n * @param {boolean?} opts.showReset — default true\n * @param {boolean?} opts.showCustomRow — default true (hex input + native picker)\n */\n function ColorPalettePicker(opts) {\n _classCallCheck(this, ColorPalettePicker);\n if (!opts || typeof opts.onPick !== 'function') {\n throw new Error('ColorPalettePicker: opts.onPick(hex) is required');\n }\n this._value = opts.value || null;\n this._onPick = opts.onPick;\n this._onReset = opts.onReset || function () {\n return opts.onPick(null);\n };\n this._recent = Array.isArray(opts.recent) ? opts.recent.slice() : [];\n var pal = opts.palette || {};\n this._mainRows = Array.isArray(pal.main) ? pal.main : DEFAULT_MAIN_PALETTE;\n this._standard = Array.isArray(pal.standard) ? pal.standard : DEFAULT_STANDARD;\n this._title = opts.title || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.palette');\n this._showEyedropper = opts.showEyedropper !== false;\n this._showReset = opts.showReset !== false;\n this._showCustomRow = opts.showCustomRow !== false;\n this.domNode = document.createElement('div');\n this.domNode.className = 'bjs-color-palette-picker';\n this._render();\n }\n\n /** Public entry — update the custom-row inputs to reflect the current\n * value. Does NOT change `.is-active` markers on the palette swatches\n * (the black swatch is the stable anchor — see `_makeSwatch`). */\n return _createClass(ColorPalettePicker, [{\n key: \"setValue\",\n value: function setValue(hex) {\n var normalized = this._parseHex(hex);\n this._value = normalized || hex || null;\n if (this._hexInput) this._hexInput.value = this._value || '';\n if (this._nativePicker && this._value && /^#[0-9a-f]{6}$/i.test(this._value)) {\n this._nativePicker.value = this._value;\n }\n }\n\n /** Public entry — update recent-LRU row (consumer pushes, picker re-renders). */\n }, {\n key: \"setRecent\",\n value: function setRecent(arr) {\n this._recent = Array.isArray(arr) ? arr.slice() : [];\n // Re-render whole domNode — recent section may appear/disappear\n // between 0 and 1 entries, which is a structural change.\n this.domNode.innerHTML = '';\n this._render();\n }\n\n /* ── private render ─────────────────────────────────────────────── */\n }, {\n key: \"_render\",\n value: function _render() {\n this.domNode.appendChild(this._buildHeader());\n if (this._recent.length) {\n this.domNode.appendChild(this._buildSection(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.recent'), [this._recent.slice(0, 10)], 'bjs-color-popover-recent'));\n }\n this.domNode.appendChild(this._buildSection(this._title, this._mainRows, 'bjs-color-popover-palette bjs-color-popover-palette-rich'));\n this.domNode.appendChild(this._buildSection(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.standard'), [this._standard], 'bjs-color-popover-standard'));\n if (this._showCustomRow) {\n this.domNode.appendChild(this._buildCustomRow());\n }\n if (this._showEyedropper && typeof window !== 'undefined' && 'EyeDropper' in window) {\n this.domNode.appendChild(this._buildEyedropperRow());\n }\n }\n }, {\n key: \"_buildHeader\",\n value: function _buildHeader() {\n var _this = this;\n var header = document.createElement('div');\n header.className = 'bjs-color-popover-header';\n\n // Title-LEFT, Reset-RIGHT. DOM order must match visual order so\n // CSS's `margin-left: auto` on Reset cleanly pushes it to the\n // right edge. Do NOT swap back to Reset-first — the layout would\n // break in the reverse.\n var title = document.createElement('span');\n title.className = 'bjs-color-popover-title';\n title.textContent = this._title;\n header.appendChild(title);\n if (this._showReset) {\n var reset = document.createElement('button');\n reset.type = 'button';\n reset.className = 'bjs-color-popover-reset';\n reset.setAttribute('data-role', 'reset');\n reset.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.remove'));\n reset.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.remove'));\n var resetIcon = document.createElement('span');\n resetIcon.className = 'material-symbols-rounded';\n resetIcon.setAttribute('aria-hidden', 'true');\n resetIcon.textContent = 'format_color_reset';\n reset.appendChild(resetIcon);\n var resetLabel = document.createElement('span');\n resetLabel.className = 'bjs-color-popover-reset-label';\n resetLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.reset');\n reset.appendChild(resetLabel);\n reset.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this._onReset();\n });\n header.appendChild(reset);\n }\n return header;\n }\n }, {\n key: \"_buildSection\",\n value: function _buildSection(label, rows, extraClass) {\n var _this2 = this;\n var wrap = document.createElement('div');\n wrap.className = 'bjs-color-popover-section ' + (extraClass || '');\n var head = document.createElement('div');\n head.className = 'bjs-color-popover-section-label';\n head.textContent = label;\n wrap.appendChild(head);\n var colCount = rows[0] && rows[0].length ? rows[0].length : 8;\n var grid = document.createElement('div');\n grid.className = 'bjs-color-popover-grid';\n grid.setAttribute('role', 'group');\n grid.style.setProperty('--bjs-color-grid-cols', String(colCount));\n rows.forEach(function (row) {\n row.forEach(function (hex) {\n return grid.appendChild(_this2._makeSwatch(hex));\n });\n });\n wrap.appendChild(grid);\n return wrap;\n }\n }, {\n key: \"_makeSwatch\",\n value: function _makeSwatch(hex) {\n var _this3 = this;\n var btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'bjs-color-swatch-btn';\n btn.setAttribute('data-role', 'swatch');\n btn.setAttribute('data-color', hex);\n btn.setAttribute('aria-label', hex);\n btn.setAttribute('data-tooltip', hex);\n btn.style.setProperty('--bjs-color-swatch', hex);\n // Stable visual anchor — always mark the black swatch active\n // regardless of the currently-applied color (per user UX rule —\n // \"ko highlight current color chọn, cứ highlight node màu đen\").\n // Rationale: users scanning a 60-swatch palette want a stable\n // visual starting point, not a marker that jumps around with\n // whatever they picked last. The \"current color\" state is\n // surfaced on the toolbar button's underline bar instead.\n if (hex.toLowerCase() === '#000000') {\n btn.classList.add('is-active');\n }\n btn.addEventListener('click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n _this3._onPick(hex);\n });\n return btn;\n }\n }, {\n key: \"_buildCustomRow\",\n value: function _buildCustomRow() {\n var _this4 = this;\n var wrap = document.createElement('div');\n wrap.className = 'bjs-color-popover-section bjs-color-popover-custom';\n var head = document.createElement('div');\n head.className = 'bjs-color-popover-section-label';\n head.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.custom');\n wrap.appendChild(head);\n var row = document.createElement('div');\n row.className = 'bjs-color-popover-custom-row';\n var nativePicker = document.createElement('input');\n nativePicker.type = 'color';\n nativePicker.className = 'bjs-color-popover-native';\n nativePicker.value = this._value && /^#[0-9a-f]{6}$/i.test(this._value) ? this._value : '#000000';\n nativePicker.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.custom'));\n nativePicker.addEventListener('change', function (e) {\n _this4._onPick(e.target.value);\n });\n this._nativePicker = nativePicker;\n var hexInput = document.createElement('input');\n hexInput.type = 'text';\n hexInput.className = 'bjs-color-popover-hex';\n hexInput.value = this._value || '';\n hexInput.placeholder = '#RRGGBB';\n hexInput.setAttribute('aria-label', 'Hex color');\n hexInput.setAttribute('spellcheck', 'false');\n hexInput.setAttribute('autocomplete', 'off');\n var commitHex = function commitHex() {\n var v = _this4._parseHex(hexInput.value);\n if (v) {\n _this4._onPick(v);\n } else if (hexInput.value && hexInput.value.trim() !== '') {\n hexInput.classList.add('is-error');\n setTimeout(function () {\n return hexInput.classList.remove('is-error');\n }, 600);\n }\n };\n hexInput.addEventListener('keydown', function (e) {\n if (e.key === 'Enter') {\n e.preventDefault();\n commitHex();\n }\n });\n hexInput.addEventListener('blur', commitHex);\n this._hexInput = hexInput;\n row.appendChild(nativePicker);\n row.appendChild(hexInput);\n wrap.appendChild(row);\n return wrap;\n }\n }, {\n key: \"_buildEyedropperRow\",\n value: function _buildEyedropperRow() {\n var _this5 = this;\n var foot = document.createElement('div');\n foot.className = 'bjs-color-popover-footer';\n var eye = document.createElement('button');\n eye.type = 'button';\n eye.className = 'bjs-color-popover-eyedropper';\n eye.setAttribute('data-role', 'eyedropper');\n eye.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.eyedropper'));\n eye.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.eyedropper'));\n var icon = document.createElement('span');\n icon.className = 'material-symbols-rounded';\n icon.setAttribute('aria-hidden', 'true');\n icon.textContent = 'colorize';\n eye.appendChild(icon);\n var eyeLabel = document.createElement('span');\n eyeLabel.className = 'bjs-color-popover-eyedropper-label';\n eyeLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.eyedropper');\n eye.appendChild(eyeLabel);\n eye.addEventListener('click', /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(e) {\n var dropper, res;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n e.preventDefault();\n _context.prev = 1;\n // eslint-disable-next-line no-undef\n dropper = new window.EyeDropper();\n _context.next = 5;\n return dropper.open();\n case 5:\n res = _context.sent;\n if (res && res.sRGBHex) _this5._onPick(res.sRGBHex);\n _context.next = 12;\n break;\n case 9:\n _context.prev = 9;\n _context.t0 = _context[\"catch\"](1);\n if (_context.t0 && _context.t0.name !== 'AbortError') {\n eye.classList.add('is-error');\n setTimeout(function () {\n return eye.classList.remove('is-error');\n }, 600);\n }\n case 12:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[1, 9]]);\n }));\n return function (_x) {\n return _ref.apply(this, arguments);\n };\n }());\n foot.appendChild(eye);\n return foot;\n }\n\n /** Parse hex into canonical lowercase `#rrggbb`. */\n }, {\n key: \"_parseHex\",\n value: function _parseHex(raw) {\n if (!raw) return null;\n var s = String(raw).trim();\n if (s.charAt(0) === '#') s = s.slice(1);\n if (/^[0-9a-f]{3}$/i.test(s)) {\n s = s.split('').map(function (c) {\n return c + c;\n }).join('');\n }\n if (!/^[0-9a-f]{6}$/i.test(s)) return null;\n return '#' + s.toLowerCase();\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ColorPalettePicker);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ui/ColorPalettePicker.js?");
/***/ }),
/***/ "./src/includes/ui/holedBoxClipPath.js":
/*!*********************************************!*\
!*** ./src/includes/ui/holedBoxClipPath.js ***!
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ holedBoxClipPath: () => (/* binding */ holedBoxClipPath)\n/* harmony export */ });\n/*\n * holedBoxClipPath — 2026-04-19.\n *\n * Build a `clip-path: polygon(...)` string for a \"holed box\" — an outer\n * rectangle with a rectangular hole carved out. All measurements in px.\n *\n * Winding (CSS non-zero rule):\n * outer rect CW → +1 winding inside outer\n * inner rect CCW → -1 winding inside inner\n * sum = 0 inside inner → HOLE\n *\n * Slit from (L,0) straight down to (L,B) is traversed twice (once going\n * into the hole, once coming back up the same line) so it renders as a\n * zero-width seam → visually invisible.\n *\n * Historical gotcha: the first implementation had both loops going CW\n * → winding +2 inside the hole → hole was FILLED → the overlay covered\n * the child element (\"ăn vào luôn cả element\"). Reversing the inner\n * loop order to CCW fixed it. Keep the ordering below as-is — the inner\n * corner sequence is: (L,0) → (L,B) → (R,B) → (R,T) → (L,T) → (L,0).\n *\n * The background painted on the holed box can be ANY CSS paint —\n * stripes, image, gradient, conic, emoji, whatever — because clip-path\n * is a purely geometric operation applied AFTER the browser renders\n * the background. See docs/plans/HOLED_BOX.md for the full primer + use cases.\n *\n * @param {{width: number, height: number}} outer — outer rect dims in px\n * @param {{left: number, top: number, right: number, bottom: number}}\n * hole — hole bounds in px,\n * right/bottom = absolute\n * coords (NOT widths)\n * @returns {string} CSS `polygon(...)` string ready for `element.style.clipPath`\n */\nfunction holedBoxClipPath(outer, hole) {\n var W = outer.width,\n H = outer.height;\n var L = hole.left,\n T = hole.top;\n var R = hole.right,\n B = hole.bottom;\n return \"polygon(\\n 0 0, \".concat(W, \"px 0, \").concat(W, \"px \").concat(H, \"px, 0 \").concat(H, \"px, 0 0,\\n \").concat(L, \"px 0,\\n \").concat(L, \"px \").concat(B, \"px,\\n \").concat(R, \"px \").concat(B, \"px,\\n \").concat(R, \"px \").concat(T, \"px,\\n \").concat(L, \"px \").concat(T, \"px,\\n \").concat(L, \"px 0\\n )\");\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (holedBoxClipPath);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ui/holedBoxClipPath.js?");
/***/ }),
/***/ "./src/includes/ui/sortable.js":
/*!*************************************!*\
!*** ./src/includes/ui/sortable.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ bjsSortable: () => (/* binding */ bjsSortable),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../PointerCaptureRegistry.js */ \"./src/includes/PointerCaptureRegistry.js\");\n\n\n/**\n * bjsSortable — pointer-driven drag-reorder for any vertical list.\n *\n * Phase-3 W6.1 introduced the same primitive inline on GridControl's\n * horizontal cell strip. W6.2 extracts the shared behavior into a tiny\n * module that ListControl / SocialIconsControl / SelectControl can opt\n * into without each re-inventing the same pointer math.\n *\n * Contract: the caller owns the data model. The mixin just reports a\n * `from → to` index move; the caller's `onReorder(from, to)` callback\n * splices the underlying array and re-renders (or mutates in place).\n *\n * ```js\n * import { bjsSortable } from './ui/sortable.js';\n *\n * bjsSortable(olElement, {\n * itemSelector: '.bjs-list-item',\n * handleSelector: '.bjs-list-item-handle',\n * onReorder: (from, to) => {\n * const [item] = items.splice(from, 1);\n * const adj = to > from ? to - 1 : to;\n * items.splice(adj, 0, item);\n * this.render();\n * this.callback?.setItems(items);\n * },\n * });\n * ```\n *\n * Design notes (why this file exists instead of three copies):\n * 1. **Pointer capture goes through the shared registry** so UIManager's\n * hover-suspend invariant (OVERLAY_PLAN §4.I5) survives a detached\n * mid-drag. A rogue `setPointerCapture` in a leaf control breaks the\n * entire builder's hover state until the next refresh.\n * 2. **The drop indicator is a DOM sibling of the list, not the item**\n * so its absolute position measured against the list's\n * `getBoundingClientRect()` survives item `innerHTML` rebuilds during\n * the drag. If it lived inside an item, a caller that full-renders\n * on every move would orphan it.\n * 3. **Auto-scroll is opt-in via `scrollContainer`** — most sidebar\n * lists already scroll naturally with the panel. Only provide a\n * container when the list sits inside its own scroll clip.\n * 4. **`destroy()` is returned** so the caller can bind fresh sortable\n * behavior after a `render()` without leaking old listeners. Most\n * controls re-`render()` which rebuilds DOM from scratch → old\n * listeners are GC'd with their nodes, so `destroy()` is optional in\n * that flow. Provided for the controls that patch DOM in place.\n */\n\nvar DROP_INDICATOR_CLASS = 'bjs-sortable-drop-indicator';\nvar GHOST_CLASS = 'bjs-sortable-ghost';\nvar DRAGGING_CLASS = 'is-sortable-dragging';\nvar DRAG_OVER_CLASS = 'is-sortable-drag-over';\nfunction bjsSortable(listEl) {\n var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n if (!listEl || listEl.nodeType !== 1) {\n throw new TypeError('bjsSortable: listEl must be a DOM element');\n }\n var _opts$itemSelector = opts.itemSelector,\n itemSelector = _opts$itemSelector === void 0 ? '.bjs-list-item' : _opts$itemSelector,\n _opts$handleSelector = opts.handleSelector,\n handleSelector = _opts$handleSelector === void 0 ? '.bjs-list-item-handle' : _opts$handleSelector,\n onReorder = opts.onReorder,\n _opts$scrollContainer = opts.scrollContainer,\n scrollContainer = _opts$scrollContainer === void 0 ? null : _opts$scrollContainer,\n _opts$dragClass = opts.dragClass,\n dragClass = _opts$dragClass === void 0 ? DRAGGING_CLASS : _opts$dragClass,\n _opts$onDragStart = opts.onDragStart,\n onDragStart = _opts$onDragStart === void 0 ? null : _opts$onDragStart,\n _opts$onDragEnd = opts.onDragEnd,\n onDragEnd = _opts$onDragEnd === void 0 ? null : _opts$onDragEnd;\n if (typeof onReorder !== 'function') {\n throw new TypeError('bjsSortable: opts.onReorder is required');\n }\n\n // Find or create the drop indicator inside the list's parent. Reuse across\n // drags so we don't churn the DOM. The indicator is styled as an absolute\n // vertical-gap line; caller's CSS owns its appearance.\n var indicator = listEl.parentElement ? listEl.parentElement.querySelector(\":scope > .\".concat(DROP_INDICATOR_CLASS)) : null;\n if (!indicator && listEl.parentElement) {\n indicator = document.createElement('div');\n indicator.className = DROP_INDICATOR_CLASS;\n // Relative containment — the indicator lives OUTSIDE the ol (as a sibling)\n // so sliding between <li>s doesn't disturb flex/grid math.\n indicator.setAttribute('aria-hidden', 'true');\n listEl.parentElement.appendChild(indicator);\n if (getComputedStyle(listEl.parentElement).position === 'static') {\n listEl.parentElement.style.position = 'relative';\n }\n }\n var state = null;\n function getItems() {\n return Array.from(listEl.querySelectorAll(\":scope > \".concat(itemSelector)));\n }\n function hitTestSlot(clientY) {\n var items = getItems();\n if (!items.length) return 0;\n var midpoints = items.map(function (it) {\n var r = it.getBoundingClientRect();\n return (r.top + r.bottom) / 2;\n });\n for (var i = 0; i < midpoints.length; i++) {\n if (clientY < midpoints[i]) return i;\n }\n return items.length;\n }\n function paintIndicator(slot) {\n if (!indicator) return;\n var items = getItems();\n if (slot === null || slot === undefined) {\n indicator.classList.remove('is-visible');\n return;\n }\n var parentRect = listEl.parentElement.getBoundingClientRect();\n var yPx;\n if (!items.length) {\n yPx = listEl.getBoundingClientRect().top - parentRect.top;\n } else if (slot === 0) {\n yPx = items[0].getBoundingClientRect().top - parentRect.top - 2;\n } else if (slot >= items.length) {\n yPx = items[items.length - 1].getBoundingClientRect().bottom - parentRect.top + 2;\n } else {\n var prev = items[slot - 1].getBoundingClientRect();\n var next = items[slot].getBoundingClientRect();\n yPx = (prev.bottom + next.top) / 2 - parentRect.top;\n }\n var listRect = listEl.getBoundingClientRect();\n indicator.style.left = \"\".concat(listRect.left - parentRect.left, \"px\");\n indicator.style.width = \"\".concat(listRect.width, \"px\");\n indicator.style.top = \"\".concat(yPx, \"px\");\n indicator.classList.add('is-visible');\n }\n function autoScroll(clientY) {\n var sc = scrollContainer;\n if (!sc) return;\n var rect = sc.getBoundingClientRect();\n var EDGE = 32;\n var SPEED = 8;\n if (clientY < rect.top + EDGE) {\n sc.scrollTop -= SPEED;\n } else if (clientY > rect.bottom - EDGE) {\n sc.scrollTop += SPEED;\n }\n }\n function onHandlePointerDown(e) {\n if (e.button !== undefined && e.button !== 0) return;\n var handle = e.currentTarget;\n var item = handle.closest(itemSelector);\n if (!item || !listEl.contains(item)) return;\n var items = getItems();\n var sourceIdx = items.indexOf(item);\n if (sourceIdx < 0) return;\n e.preventDefault();\n e.stopPropagation();\n _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].acquire(handle, e.pointerId);\n item.classList.add(dragClass);\n listEl.classList.add(DRAGGING_CLASS);\n\n // Create a floating ghost clone positioned with the pointer. Gives\n // users the Figma-style \"piece follows cursor\" affordance without\n // needing HTML5 DnD (which fights with our PointerCaptureRegistry).\n var ghost = item.cloneNode(true);\n ghost.classList.add(GHOST_CLASS);\n ghost.classList.remove(dragClass);\n // Strip interactive children so ghost can't be focused / clicked.\n ghost.querySelectorAll('button, input, select, textarea').forEach(function (el) {\n el.setAttribute('tabindex', '-1');\n el.style.pointerEvents = 'none';\n });\n var rect = item.getBoundingClientRect();\n ghost.style.width = \"\".concat(rect.width, \"px\");\n ghost.style.height = \"\".concat(rect.height, \"px\");\n document.body.appendChild(ghost);\n state = {\n handle: handle,\n pointerId: e.pointerId,\n sourceIdx: sourceIdx,\n item: item,\n ghost: ghost,\n dropSlot: null,\n offsetX: e.clientX - rect.left,\n offsetY: e.clientY - rect.top\n };\n positionGhost(e.clientX, e.clientY);\n var slot0 = hitTestSlot(e.clientY);\n state.dropSlot = normaliseSlot(slot0, sourceIdx);\n paintIndicator(state.dropSlot);\n handle.addEventListener('pointermove', onMove);\n handle.addEventListener('pointerup', onUp);\n handle.addEventListener('pointercancel', onCancel);\n handle.addEventListener('lostpointercapture', onCancel);\n if (typeof onDragStart === 'function') {\n try {\n onDragStart(sourceIdx);\n } catch (_e) {}\n }\n }\n function positionGhost(x, y) {\n if (!state || !state.ghost) return;\n state.ghost.style.left = \"\".concat(x - state.offsetX, \"px\");\n state.ghost.style.top = \"\".concat(y - state.offsetY, \"px\");\n }\n\n /** Drop slot indices adjacent to the source (`from` or `from + 1`) both\n * resolve back to the same position → treat as no-op and return null so\n * the indicator vanishes. */\n function normaliseSlot(slot, sourceIdx) {\n if (slot === sourceIdx || slot === sourceIdx + 1) return null;\n return slot;\n }\n function onMove(e) {\n if (!state) return;\n positionGhost(e.clientX, e.clientY);\n var slot = hitTestSlot(e.clientY);\n state.dropSlot = normaliseSlot(slot, state.sourceIdx);\n paintIndicator(state.dropSlot);\n autoScroll(e.clientY);\n }\n function cleanup() {\n if (!state) return;\n var _state = state,\n handle = _state.handle,\n item = _state.item,\n ghost = _state.ghost,\n pointerId = _state.pointerId;\n try {\n handle.removeEventListener('pointermove', onMove);\n } catch (_e) {}\n try {\n handle.removeEventListener('pointerup', onUp);\n } catch (_e) {}\n try {\n handle.removeEventListener('pointercancel', onCancel);\n } catch (_e) {}\n try {\n handle.removeEventListener('lostpointercapture', onCancel);\n } catch (_e) {}\n try {\n _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].release(handle, pointerId);\n } catch (_e) {}\n if (ghost && ghost.parentNode) ghost.parentNode.removeChild(ghost);\n if (item) item.classList.remove(dragClass);\n listEl.classList.remove(DRAGGING_CLASS);\n paintIndicator(null);\n state = null;\n }\n function onUp() {\n var st = state;\n var dest = st ? st.dropSlot : null;\n var src = st ? st.sourceIdx : -1;\n cleanup();\n if (dest !== null && src >= 0) {\n try {\n onReorder(src, dest);\n } catch (err) {\n console.error('bjsSortable.onReorder threw', err);\n }\n }\n if (typeof onDragEnd === 'function') {\n try {\n onDragEnd(src, dest);\n } catch (_e) {}\n }\n }\n function onCancel() {\n var st = state;\n var src = st ? st.sourceIdx : -1;\n cleanup();\n if (typeof onDragEnd === 'function') {\n try {\n onDragEnd(src, null);\n } catch (_e) {}\n }\n }\n\n // Wire every handle. Re-running bjsSortable on the same list rebinds\n // cleanly because listeners were attached to the OLD DOM nodes which no\n // longer exist (render() rebuilds innerHTML). Idempotence is a caller\n // property in the render-every-change pattern.\n var handles = Array.from(listEl.querySelectorAll(\"\".concat(itemSelector, \" \").concat(handleSelector)));\n handles.forEach(function (h) {\n h.addEventListener('dragstart', function (e) {\n return e.preventDefault();\n }); // block native DnD\n h.addEventListener('pointerdown', onHandlePointerDown);\n });\n return {\n destroy: function destroy() {\n handles.forEach(function (h) {\n try {\n h.removeEventListener('pointerdown', onHandlePointerDown);\n } catch (_e) {}\n });\n cleanup();\n if (indicator && indicator.parentNode) {\n indicator.parentNode.removeChild(indicator);\n }\n }\n };\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (bjsSortable);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ui/sortable.js?");
/***/ }),
/***/ "./src/lang/en.json":
/*!**************************!*\
!*** ./src/lang/en.json ***!
\**************************/
/***/ ((module) => {
eval("module.exports = /*#__PURE__*/JSON.parse('{\"widgets.heading\":\"Heading\",\"widgets.paragraph\":\"Paragraph\",\"widgets.button\":\"Button\",\"widgets.image\":\"Image\",\"widgets.video\":\"Video Widget\",\"widgets.grid\":\"Grid\",\"widgets.list\":\"List\",\"widgets.menu\":\"Menu Bar\",\"widgets.pricing_cards\":\"Pricing Cards\",\"widgets.divider\":\"Divider\",\"widgets.alert\":\"Alert\",\"widgets.youtube\":\"Youtube\",\"widgets.rss\":\"RSS\",\"widgets.select\":\"Select\",\"widgets.radio\":\"Radio\",\"widgets.checkbox\":\"Checkbox\",\"widgets.checkout\":\"Checkout\",\"widgets.checkout_simple\":\"Checkout Simple\",\"widgets.welcome\":\"Welcome\",\"widgets.image_text_left\":\"Image Left & Text\",\"widgets.image_text_right\":\"Image Right & Text\",\"widgets.image_text_top\":\"Image Top & Text\",\"widgets.image_text_bottom\":\"Image Bottom & Text\",\"widgets.image_text_double\":\"Image Top & Text\",\"widgets.text_center\":\"Text Center\",\"widgets.text_left\":\"Text Left\",\"widgets.text_double\":\"Text Left\",\"widgets.terms_of_service\":\"Terms of Service\",\"elements.page\":\"Page\",\"elements.block\":\"Block\",\"elements.cell\":\"Cell\",\"elements.button\":\"Button\",\"elements.image\":\"Image\",\"elements.heading\":\"Heading\",\"elements.link\":\"Link\",\"elements.video\":\"Video\",\"elements.alert\":\"Alert\",\"elements.menu\":\"Menu\",\"elements.list\":\"List\",\"elements.label\":\"Label\",\"elements.text_input\":\"Text Input\",\"elements.select\":\"Select\",\"elements.radio\":\"Radio\",\"elements.checkbox\":\"Checkbox\",\"elements.social_icons\":\"Social Icons\",\"elements.divider\":\"Divider\",\"elements.html\":\"HTML\",\"elements.rss\":\"RSS\",\"elements.youtube\":\"YouTube\",\"elements.pricing_cards\":\"Pricing Cards\",\"elements.pricing_card\":\"Card\",\"elements.checkout\":\"Checkout\",\"elements.checkout_simple\":\"Checkout Simple\",\"elements.heading_1\":\"Heading 1\",\"elements.heading_2\":\"Heading 2\",\"elements.heading_3\":\"Heading 3\",\"elements.heading_4\":\"Heading 4\",\"elements.heading_5\":\"Heading 5\",\"elements.paragraph\":\"Paragraph\",\"elements.submit_button\":\"Submit Button\",\"elements.field\":\"Field\",\"elements.terms_of_service\":\"Terms of Service\",\"actions.copy\":\"Copy\",\"actions.remove\":\"Remove\",\"actions.select_parent\":\"Select Parent\",\"actions.unselect\":\"Unselect\",\"controls.text\":\"Text\",\"controls.url\":\"URL\",\"controls.font_family\":\"Font Family\",\"controls.font_weight\":\"Font Weight\",\"controls.font_size\":\"Font Size\",\"controls.text_color\":\"Text Color\",\"controls.link_color\":\"Link Color\",\"controls.alignment\":\"Alignment\",\"controls.background_settings\":\"Background Settings\",\"controls.border_settings\":\"Border Settings\",\"controls.radius\":\"Radius\",\"controls.padding\":\"Padding\",\"controls.margin\":\"Margin\",\"controls.block_padding\":\"Block Padding\",\"controls.page_padding\":\"Page Padding\",\"controls.width\":\"Width\",\"controls.height\":\"Height\",\"controls.max_width\":\"Max Width\",\"controls.max_height\":\"Max Height\",\"controls.min_width\":\"Min Width\",\"controls.min_height\":\"Min Height\",\"controls.display\":\"Display\",\"controls.direction\":\"Direction\",\"controls.justify\":\"Justify\",\"controls.align_items\":\"Align Items\",\"controls.gap\":\"Gap\",\"controls.content_gap\":\"Content Gap\",\"controls.line_height\":\"Line Height\",\"controls.letter_spacing\":\"Letter Spacing\",\"controls.paragraph_spacing\":\"Paragraph Spacing\",\"controls.text_direction\":\"Text Direction\",\"controls.color\":\"Color\",\"controls.size_pct\":\"Size (%)\",\"controls.default_block_background\":\"Default Block Background\",\"controls.block_gap\":\"Block Gap\",\"controls.container_width\":\"Container Width\",\"controls.cell_background\":\"Cell Background\",\"controls.cell_border\":\"Cell Border\",\"controls.cell_radius\":\"Cell Radius\",\"controls.cell_padding\":\"Cell Padding\",\"controls.cell_height\":\"Cell Height\",\"controls.optimized_mobile\":\"Optimized for mobile\",\"controls.optimized_mobile_desc\":\"Allow the element to display correctly on mobile devices\",\"controls.compat_mode\":\"Compatibility mode for legacy browser\",\"controls.compat_mode_desc\":\"Render compatible HTML for older browser like IE, Opera notice that in certain cases, it might generate JS and make sure your browser supports JS\",\"controls.social_icons\":\"Social Icons\",\"controls.items\":\"Items\",\"controls.plans\":\"Plans\",\"pricing.section_style\":\"Card style\",\"pricing.section_style_desc\":\"Pick one of 10 presets — applies to every card in this set.\",\"pricing.style_label\":\"Style\",\"pricing_style.minimal_label\":\"Minimal\",\"pricing_style.highlighted_label\":\"Highlighted\",\"pricing_style.featured_label\":\"Featured\",\"pricing_style.compact_label\":\"Compact\",\"pricing_style.glass_label\":\"Glass\",\"pricing_style.pill_label\":\"Pill\",\"pricing_style.neon_label\":\"Neon\",\"pricing_style.brutalist_label\":\"Brutalist\",\"pricing_style.editorial_label\":\"Editorial\",\"pricing_style.gradient_label\":\"Gradient\",\"pricing_style.banded_label\":\"Banded\",\"pricing_style.tier_label\":\"Tier\",\"pricing_style.neo_label\":\"Soft\",\"pricing.section_card_meta\":\"This card\",\"pricing.section_card_meta_desc\":\"Per-card accent — pick the one you want to stand out.\",\"pricing.highlighted_label\":\"Highlight this card\",\"pricing.highlighted_desc\":\"Apply the accent border + subtle lift so this plan stands out.\",\"pricing.badge_label\":\"Badge text\",\"pricing.badge_placeholder\":\"e.g. Most Popular\",\"pricing.icon_label\":\"Icon\",\"pricing.icon_placeholder\":\"e.g. bolt or 💎\",\"pricing.icon_help\":\"Use a Material Symbols name (bolt, diamond…) or any emoji.\",\"pricing.accent_label\":\"Accent color\",\"pricing.accent_placeholder\":\"#ffcc2a\",\"pricing.card_empty_title\":\"Empty plan\",\"pricing.card_empty_hint\":\"Drop a heading, price, or button to start this plan.\",\"pricing.highlight_label\":\"Recommended plan\",\"pricing.highlight_none\":\"None — no card highlighted\",\"pricing.highlight_card_n\":\"Card {n}\",\"pricing.show_icons_label\":\"Show card icons\",\"pricing.show_icons_desc\":\"Hide icons on every card without clearing the icon field.\",\"pricing.show_badges_label\":\"Show card badges\",\"pricing.show_badges_desc\":\"Hide badges (“Most Popular” pills) without clearing the badge text.\",\"pricing.style_switch_hint\":\"Switching style replaces every card’s accent, button, and text colors with the new style’s defaults. Your badge, icon, and highlight choices are preserved.\",\"pricing.card_style_hint\":\"This card inherits the {style} style defaults. Colors you pick here override the style.\",\"pricing.reset_all_label\":\"Reset all cards\",\"pricing.reset_all_hint\":\"Clears accent, badge, icon, and highlight on every card, then re-applies {style} defaults.\",\"pricing.reset_all_button\":\"Reset\",\"pricing.reset_card_label\":\"Reset this card\",\"pricing.reset_card_hint\":\"Clears this card’s accent, badge, icon, highlight, and re-applies {style} defaults.\",\"pricing.reset_card_button\":\"Reset\",\"icon_picker.none\":\"None\",\"icon_picker.custom\":\"Custom emoji\",\"icon_picker.custom_label\":\"Enter an emoji or glyph\",\"icon_picker.custom_placeholder\":\"e.g. 💎 or ✨\",\"controls.columns\":\"Columns\",\"controls.heading\":\"Heading\",\"controls.divider_style\":\"Divider Style\",\"controls.image_padding\":\"Image Padding\",\"controls.image_effects\":\"Image Effects\",\"controls.button_padding\":\"Button Padding\",\"controls.custom_block_padding\":\"Custom Block Padding\",\"controls.alert_padding\":\"Alert Padding\",\"controls.grid_background\":\"Grid Background\",\"controls.grid_padding\":\"Grid Padding\",\"controls.grid_height\":\"Grid Height\",\"controls.cells\":\"Cells\",\"controls.cell_gap\":\"Cell Gap\",\"controls.name\":\"Name\",\"controls.value\":\"Value\",\"controls.placeholder\":\"Placeholder\",\"controls.orientation\":\"Orientation\",\"controls.separator\":\"Separator\",\"controls.separator_gap\":\"Separator Gap\",\"separator.none\":\"No separator\",\"separator.custom\":\"Custom\",\"separator.placeholder\":\"e.g. ::\",\"controls.items_gap\":\"Items Gap\",\"controls.youtube_url\":\"Youtube URL\",\"controls.video_url\":\"Video URL\",\"video.url_placeholder\":\"https://example.com/video.mp4\",\"video.url_banner\":\"Paste a direct <b>.mp4</b>, <b>.webm</b>, or <b>.ogg</b> URL. YouTube / Vimeo links need the <b>YouTube</b> widget instead — they won\\'t play inside a native <video> tag.\",\"video.invalid_url\":\"Enter a valid URL (http://, https://, or /path).\",\"video.load_error\":\"This URL didn\\'t return a playable video. Check the link or use the YouTube widget for YouTube/Vimeo.\",\"video.load_ok\":\"Video loaded successfully.\",\"video.load_pending\":\"Checking video…\",\"video.err_aborted\":\"Loading was cancelled before the video finished downloading.\",\"video.err_network\":\"Network error — the video server didn\\'t respond. Check the URL, the server\\'s availability, and that it returns 200 OK.\",\"video.err_decode\":\"The video file is corrupted or uses a codec this browser can\\'t decode.\",\"video.err_src_unsupported\":\"The URL returned, but the content isn\\'t a supported video (wrong Content-Type, blocked by CORS, or a format this browser can\\'t play). YouTube / Vimeo links need the YouTube widget instead.\",\"video.clear\":\"Clear video URL\",\"video.empty_title\":\"No video yet\",\"video.empty_desc\":\"Paste a direct video URL in the right panel (Video URL field) to preview it here.\",\"video.fallback_error\":\"The video URL couldn\\'t be played. The file may be missing, blocked by CORS, or not a supported format (mp4/webm/ogg).\",\"controls.pricing_cards_padding\":\"Pricing Cards Padding\",\"controls.icons_items_list\":\"Icons/Items List\",\"controls.icon_gap\":\"Icon Gap\",\"controls.icon_size\":\"Icon Size\",\"controls.social_icons_padding\":\"Social Icons Padding\",\"controls.list_items\":\"List Items\",\"list.add\":\"Add\",\"list.edit\":\"Edit\",\"list.delete\":\"Delete\",\"list.reorder\":\"Drag to reorder\",\"list.label\":\"Label\",\"list.url\":\"URL\",\"list.item_fallback\":\"Item\",\"list.insert_here\":\"Insert here\",\"list.bulk_selected\":\"{n} selected\",\"list.bulk_delete\":\"Delete\",\"list.bulk_clear\":\"Clear\",\"select.reorder\":\"Drag to reorder\",\"controls.text_alignment\":\"Text alignment\",\"controls.block_alignment\":\"Block alignment\",\"controls.item_alignment\":\"Item alignment\",\"menu.banner\":\"List items become clickable links. Pick an <b>orientation</b> — horizontal rows or vertical stacks — and a per-item separator if you want dividers between labels. Item alignment appears for vertical stacks only.\",\"controls.heading_type\":\"Heading Type\",\"controls.field_label\":\"Field label\",\"controls.field_settings\":\"Field settings\",\"controls.field_settings_help\":\"Label visibility, placeholder, default value, required flag with indicator, and validation messages.\",\"controls.field_show_label\":\"Show field label\",\"controls.field_show_label_help\":\"When off, the input renders without a visible label. The required indicator hides too.\",\"controls.field_default\":\"Default value\",\"controls.field_required\":\"Required\",\"controls.field_required_help\":\"When on, the visitor must fill the field. Server-side validation always runs as a safety net.\",\"controls.field_required_indicator\":\"Required indicator\",\"controls.field_required_indicator_help\":\"Shown next to the label when the field is required. Pick a preset or type your own.\",\"controls.field_required_indicator_preset_none\":\"None\",\"controls.field_required_indicator_preset_star\":\"★\",\"controls.field_required_indicator_preset_asterisk\":\"*\",\"controls.field_required_indicator_preset_text\":\"(required)\",\"controls.field_required_indicator_preset_text_value\":\"(required)\",\"controls.field_required_indicator_preset_custom\":\"Custom\",\"controls.field_required_indicator_custom_placeholder\":\"e.g. (required)\",\"controls.field_required_indicator_color\":\"Indicator color\",\"controls.field_msg_required\":\"Required validation message\",\"controls.field_msg_required_help\":\"Custom message shown when the visitor leaves this field blank. Empty falls through to the default.\",\"controls.field_msg_required_placeholder\":\"This field is required.\",\"controls.field_msg_email\":\"Email format message\",\"controls.field_msg_email_help\":\"Shown when the value isn\\'t a valid email address. Empty falls through to the default.\",\"controls.field_msg_email_placeholder\":\"Please enter a valid email address.\",\"controls.field_inline_hint\":\"Tip: client-side validation gates submit; server-side rejects tampered POSTs.\",\"controls.checkbox_label\":\"Checkbox label\",\"controls.terms_required\":\"Block submit if unchecked\",\"controls.terms_required_help\":\"When on, the form rejects submission unless the visitor checks the box.\",\"controls.terms_settings\":\"Compliance settings\",\"controls.terms_settings_help\":\"Pick a preset or customise the legal copy and consent toggle.\",\"controls.terms_preset_label\":\"Preset\",\"controls.terms_preset_tos\":\"Terms\",\"controls.terms_preset_privacy\":\"Privacy\",\"controls.terms_preset_marketing\":\"Marketing\",\"controls.terms_preset_gdpr\":\"GDPR\",\"controls.terms_inline_hint\":\"Tip: click the legal text on the canvas to edit links and rich formatting inline.\",\"controls.terms_position_label\":\"Checkbox position\",\"controls.terms_position_below\":\"Below\",\"controls.terms_position_above\":\"Above\",\"controls.terms_position_inline_left\":\"Inline ←\",\"controls.terms_position_inline_right\":\"Inline →\",\"controls.terms_error_message\":\"Validation message\",\"controls.terms_error_message_help\":\"Custom message shown when the visitor submits without checking. Leave empty to use the default.\",\"controls.terms_error_message_placeholder\":\"Please accept the terms before submitting.\",\"elements.terms_preset_tos_text\":\"By submitting this form, you agree to our <a href=\\\\\"#\\\\\">Terms of Service</a> and <a href=\\\\\"#\\\\\">Privacy Policy</a>.\",\"elements.terms_preset_tos_label\":\"I agree to the terms above.\",\"elements.terms_preset_privacy_text\":\"We respect your privacy. See our <a href=\\\\\"#\\\\\">Privacy Policy</a> for how we handle your data.\",\"elements.terms_preset_privacy_label\":\"I have read and agree to the privacy policy.\",\"elements.terms_preset_marketing_text\":\"Want to receive product updates and offers? Tick the box to opt in (optional).\",\"elements.terms_preset_marketing_label\":\"Yes, send me marketing emails.\",\"elements.terms_preset_gdpr_text\":\"By checking this box, I consent to the processing of my personal data as described in our <a href=\\\\\"#\\\\\">Data Policy</a>.\",\"elements.terms_preset_gdpr_label\":\"I consent to data processing.\",\"controls.select_options\":\"Select Options\",\"controls.select_padding\":\"Select Padding\",\"controls.radio_options\":\"Radio Options\",\"controls.checkbox_options\":\"Checkbox Options\",\"controls.action_url\":\"Action URL\",\"controls.method\":\"Method\",\"controls.rss_url\":\"RSS URL\",\"controls.fixed\":\"Fixed\",\"controls.auto\":\"Auto\",\"controls.h1_main_title\":\"H1 - Main Title\",\"controls.h2_section_title\":\"H2 - Section Title\",\"controls.h3_subsection_title\":\"H3 - Subsection Title\",\"controls.h4_smaller_title\":\"H4 - Smaller Title\",\"controls.h5_even_smaller_title\":\"H5 - Even Smaller Title\",\"controls.h6_smallest_title\":\"H6 - Smallest Title\",\"section.configurations\":\"CONFIGURATIONS\",\"section.image_size\":\"IMAGE SIZE\",\"section.image_size_desc\":\"Adjust width, height and bounds.\",\"section.page_settings\":\"PAGE SETTINGS\",\"section.cell_settings\":\"CELL SETTINGS\",\"section.grid_settings\":\"GRID SETTINGS\",\"section.cells_width_settings\":\"CELLS WIDTH SETTINGS\",\"section.parent_grid\":\"PARENT GRID\",\"section.parent_grid_desc\":\"Settings below apply to the whole grid row (all cells).\",\"section.cell_widths\":\"CELL WIDTHS\",\"section.cell_widths_desc\":\"px, %, em, vw … or Auto (grow-share). Cells sum with gap to fill the row.\",\"section.grid_spacing\":\"GRID SPACING & ALIGNMENT\",\"section.grid_spacing_desc\":\"Horizontal gap between cells and vertical cell alignment.\",\"section.grid_background\":\"GRID BACKGROUND\",\"section.grid_background_desc\":\"Color, image, or filter applied to the whole grid row.\",\"controls.cell_n\":\"Cell\",\"controls.cell_alignment\":\"Cell alignment\",\"controls.cell_gap_desc\":\"Use 0 for flush cells or 8 / 16 / 24 for common gutters.\",\"align.stretch\":\"Stretch\",\"align.top\":\"Top\",\"align.center\":\"Center\",\"align.bottom\":\"Bottom\",\"grid.add_cell\":\"Add cell\",\"grid.remove_cell\":\"Remove cell\",\"grid.drag_cell\":\"Drag to reorder\",\"grid.insert_cell_at\":\"Insert cell at\",\"grid.cells\":\"Cells\",\"grid.layout_presets\":\"Layout presets\",\"grid.manager_hint\":\"Card widths mirror the live grid layout. Click a card to edit its width below.\",\"grid.preset_1col\":\"1 column\",\"grid.preset_1_1\":\"50 / 50\",\"grid.preset_1_1_1\":\"Three equal columns\",\"grid.preset_1_2\":\"33 / 67 — sidebar left\",\"grid.preset_2_1\":\"67 / 33 — sidebar right\",\"grid.preset_1_2_1\":\"25 / 50 / 25 — magazine\",\"grid.alert_overflow\":\"Cells sum to more than 100% — the row will overflow. Rebalance to fit, or equalize?\",\"grid.alert_underfill\":\"Cells don’t fill the row — empty space remaining. Rebalance to fill, or equalize?\",\"grid.alert_rebalance\":\"Rebalance\",\"grid.alert_rebalance_title\":\"Scale existing percents proportionally so the row sums to 100%\",\"grid.alert_equalize\":\"Equalize\",\"grid.alert_equalize_title\":\"Set every cell to 100 ∕ N percent\",\"grid.alert_dismiss\":\"Dismiss\",\"grid.ruler\":\"Row ruler\",\"grid.resize_between\":\"Resize between cells\",\"grid.bulk_selected\":\"{n} selected\",\"grid.bulk_delete\":\"Delete\",\"grid.bulk_clear\":\"Clear\",\"dropdown.auto_full\":\"Auto (Full)\",\"dropdown.narrow\":\"Narrow (600px)\",\"dropdown.medium\":\"Medium (800px)\",\"dropdown.wide\":\"Wide (1024px)\",\"dropdown.xl\":\"XL (1200px)\",\"dropdown.full_bleed\":\"Full Bleed (100%)\",\"dropdown.default\":\"Default\",\"dropdown.block\":\"Block\",\"dropdown.flex\":\"Flex\",\"dropdown.row\":\"Row\",\"dropdown.column\":\"Column\",\"dropdown.start\":\"Start\",\"dropdown.center\":\"Center\",\"dropdown.end\":\"End\",\"dropdown.space_between\":\"Space Between\",\"dropdown.space_around\":\"Space Around\",\"dropdown.space_evenly\":\"Space Evenly\",\"dropdown.stretch\":\"Stretch\",\"image.mode\":\"Image Mode\",\"image.upload_image\":\"Upload Image\",\"image.paste_url\":\"Paste Url\",\"image.loading\":\"Loading...\",\"image.upload\":\"Upload\",\"image.browse\":\"Browse\",\"image.replace\":\"Replace\",\"image.remove\":\"Remove\",\"image.url\":\"Image URL\",\"image.enter_url\":\"Enter image URL\",\"image.alt_text\":\"Alternate Text\",\"image.enter_alt\":\"Enter alternate text\",\"image.no_image\":\"No image selected\",\"image.image_selected\":\"Image selected\",\"image.invalid_image\":\"Invalid image\",\"image.embedded\":\"Embedded image\",\"image.uploaded_file\":\"(uploaded file)\",\"background.desc\":\"Color, image, gradient, size, position, repeat, and effects.\",\"background.repeat\":\"Repeat background\",\"background.repeat_desc\":\"Enable to repeat the background image\",\"background.position_h\":\"Position (Horizontal)\",\"background.position_v\":\"Position (Vertical)\",\"bbg.image\":\"Image\",\"bbg.no_image\":\"No image\",\"bbg.no_image_hint\":\"Upload or paste a URL\",\"bbg.preview_hint\":\"Drag inside the preview to set focus · Scroll to zoom\",\"bbg.upload\":\"Upload\",\"bbg.paste_url\":\"Paste URL\",\"bbg.url\":\"URL\",\"bbg.image_read_failed\":\"Could not read the file. Check format and try again.\",\"bbg.size\":\"Size\",\"bbg.size_cover\":\"Cover\",\"bbg.size_contain\":\"Contain\",\"bbg.size_custom\":\"Scale\",\"bbg.focus\":\"Focus point\",\"bbg.focus_x\":\"Focus X\",\"bbg.focus_y\":\"Focus Y\",\"bbg.repeat\":\"Repeat\",\"bbg.repeat_none\":\"None\",\"bbg.repeat_tile\":\"Tile\",\"bbg.repeat_x\":\"Row\",\"bbg.repeat_y\":\"Column\",\"bbg.gradient\":\"Gradient\",\"bbg.gradient_hint\":\"Enable CSS gradient overlay\",\"bbg.gradient_type\":\"Type\",\"bbg.gradient_linear\":\"Linear\",\"bbg.gradient_radial\":\"Radial\",\"bbg.gradient_angle\":\"Angle\",\"bbg.gradient_color_1\":\"Start color\",\"bbg.gradient_color_2\":\"End color\",\"bbg.gradient_presets\":\"Presets\",\"bbg.effects\":\"Effects\",\"bbg.effects_active\":\"Effects are applied\",\"bbg.active\":\"Active\",\"bbg.effects_email_warning\":\"Blend modes and CSS filters render in modern clients. Outlook and some legacy clients may drop these effects.\",\"bbg.opacity\":\"Opacity\",\"bbg.blend_mode\":\"Blend\",\"bbg.blend_normal\":\"Normal\",\"bbg.blend_multiply\":\"Multiply\",\"bbg.blend_screen\":\"Screen\",\"bbg.blend_overlay\":\"Overlay\",\"bbg.blend_darken\":\"Darken\",\"bbg.blend_lighten\":\"Lighten\",\"bbg.blend_color_dodge\":\"Color dodge\",\"bbg.blend_color_burn\":\"Color burn\",\"bbg.blend_soft_light\":\"Soft light\",\"bbg.blend_hard_light\":\"Hard light\",\"bbg.blend_difference\":\"Difference\",\"bbg.blend_exclusion\":\"Exclusion\",\"bbg.blend_hue\":\"Hue\",\"bbg.blend_saturation\":\"Saturation\",\"bbg.blend_color\":\"Color\",\"bbg.blend_luminosity\":\"Luminosity\",\"bbg.filter_blur\":\"Blur\",\"bbg.filter_brightness\":\"Brightness\",\"bbg.filter_contrast\":\"Contrast\",\"bbg.filter_saturate\":\"Saturation\",\"bbg.filter_grayscale\":\"Grayscale\",\"bbg.reset_effects\":\"Reset effects\",\"bbg.reset_all\":\"Reset all\",\"controls.link\":\"Link\",\"link.target_self\":\"Same tab\",\"link.target_blank\":\"New tab\",\"link.invalid_url\":\"Enter a valid URL (http://, https://, or /path)\",\"link.clear\":\"Clear link\",\"link_config.banner\":\"Pick where this link goes. Email / Phone / Anchor links use the right scheme automatically.\",\"link_config.type\":\"Type\",\"link_config.type_web\":\"Web URL\",\"link_config.type_email\":\"Email\",\"link_config.type_phone\":\"Phone\",\"link_config.type_anchor\":\"Anchor (in this email)\",\"link_config.url\":\"URL\",\"link_config.url_placeholder\":\"https://example.com\",\"link_config.clear\":\"Clear URL\",\"link_config.target\":\"Open\",\"link_config.target_self\":\"Same tab\",\"link_config.target_blank\":\"New tab\",\"link_config.email_to\":\"Email address\",\"link_config.email_to_placeholder\":\"[email protected]\",\"link_config.email_subject\":\"Subject (optional)\",\"link_config.email_body\":\"Body (optional)\",\"link_config.phone_number\":\"Phone number\",\"link_config.phone_placeholder\":\"+1 555 123 4567\",\"link_config.anchor_id\":\"Section ID\",\"link_config.anchor_placeholder\":\"section-name\",\"link_config.title\":\"Title (tooltip)\",\"link_config.title_placeholder\":\"Shown on hover; helps screen readers\",\"link_config.auto_rel_notice\":\"rel=\\\\\"noopener noreferrer\\\\\" will be added automatically (protects recipients against tab-hijacking when opening in a new tab).\",\"link_config.advanced\":\"ADVANCED\",\"link_config.advanced_desc\":\"rel attributes · aria-label · UTM · download filename\",\"link_config.rel\":\"Link relationship (rel)\",\"link_config.aria_label\":\"Screen-reader label (aria-label)\",\"link_config.aria_label_placeholder\":\"E.g. \\\\\"Download our 2025 report\\\\\" — overrides visible text for assistive tech\",\"link_config.download\":\"Download filename\",\"link_config.download_placeholder\":\"e.g. invoice.pdf (leave empty for normal links)\",\"link_config.utm\":\"UTM tracking parameters\",\"link_config.utm_clear\":\"Clear UTM\",\"link_config.utm_source_placeholder\":\"utm_source — e.g. newsletter\",\"link_config.utm_medium_placeholder\":\"utm_medium — e.g. email\",\"link_config.utm_campaign_placeholder\":\"utm_campaign — e.g. spring_sale\",\"link_config.utm_term_placeholder\":\"utm_term — e.g. paid_keyword\",\"link_config.utm_content_placeholder\":\"utm_content — e.g. cta_button_v2\",\"link_config.err_web_url\":\"Enter a valid URL (https://, /, ./, blob:, data:)\",\"link_config.err_email\":\"Enter a valid email address\",\"link_config.err_phone\":\"Use digits, spaces, +, -, (, ) only\",\"link_config.err_anchor\":\"ID must start with a letter; use letters, digits, -, _\",\"image.effects\":\"Image Effects\",\"border.settings\":\"Border Settings\",\"border.radius\":\"Radius\",\"richtext.bold\":\"Bold\",\"richtext.italic\":\"Italic\",\"richtext.underline\":\"Underline\",\"richtext.strikethrough\":\"Strikethrough\",\"richtext.superscript\":\"Superscript\",\"richtext.subscript\":\"Subscript\",\"richtext.text_color\":\"Text Color\",\"richtext.highlight\":\"Highlight\",\"richtext.clear_formatting\":\"Clear Formatting\",\"richtext.horizontal_rule\":\"Horizontal Line\",\"richtext.unlink\":\"Remove Link\",\"richtext.unselect\":\"Deselect\",\"richtext.select_all\":\"Select All\",\"richtext.undo\":\"Undo\",\"richtext.redo\":\"Redo\",\"richtext.bullet_list\":\"Bullet List\",\"richtext.numbered_list\":\"Numbered List\",\"richtext.indent\":\"Increase Indent\",\"richtext.outdent\":\"Decrease Indent\",\"richtext.link\":\"Insert Link (Ctrl+K)\",\"richtext.link_url_placeholder\":\"https://example.com\",\"richtext.link_apply\":\"Apply link\",\"richtext.link_remove\":\"Remove link\",\"ai.optimize\":\"Optimize content\",\"ai.rewrite_formal\":\"Rewrite formally\",\"ai.rewrite_casual\":\"Rewrite more casually\",\"ai.thinking\":\"Thinking...\",\"ai.failed\":\"Failed to connect to AI service. Please try again later.\",\"youtube.enter_url\":\"Enter YouTube URL\",\"youtube.invalid_url\":\"Enter a valid URL (http://, https://, or /path).\",\"youtube.url_banner\":\"Paste a YouTube <b>watch</b>, <b>embed</b>, <b>shorts</b>, or <b>youtu.be</b> URL. Direct video files belong in the <b>Video</b> widget instead.\",\"youtube.url_placeholder\":\"https://www.youtube.com/watch?v=…\",\"youtube.clear\":\"Clear YouTube URL\",\"youtube.extract_ok\":\"Valid YouTube URL — video embed is ready.\",\"youtube.extract_failed\":\"This URL doesn\\'t look like a YouTube link. Expected youtube.com/watch?v=…, youtu.be/…, youtube.com/embed/…, or youtube.com/shorts/…\",\"youtube.empty_title\":\"No YouTube video yet\",\"youtube.empty_desc\":\"Paste a YouTube URL in the right panel to embed it here.\",\"rss.enter_url\":\"Enter RSS URL\",\"rss.max_items\":\"Max Items\",\"rss.url_required\":\"URL is required.\",\"rss.invalid_url\":\"Please enter a valid RSS URL.\",\"rss.invalid_limit\":\"Please enter a valid limit.\",\"rss.fetch_failed\":\"Failed to fetch RSS feed.\",\"rss.invalid_format\":\"Invalid RSS feed format.\",\"rss.load_failed\":\"Failed to load RSS feed. Please check the URL.\",\"rss.see_more\":\"See more info\",\"rss.style\":\"Style\",\"rss.style_modern\":\"Modern (Cards)\",\"rss.style_classic\":\"Classic (List)\",\"rss.show_title\":\"Show Title\",\"rss.show_desc\":\"Show Description\",\"rss.show_date\":\"Show Date\",\"rss.show_image\":\"Show Image\",\"rss.show_link\":\"Show Read More Link\",\"rss.show_author\":\"Show Author\",\"rss.content_length\":\"Content Length\",\"rss.content_length_desc\":\"Max characters for description (0 = full)\",\"rss.fetch\":\"Fetch\",\"rss.apply\":\"Apply\",\"rss.fetching\":\"Fetching...\",\"rss.items_found\":\"items found\",\"rss.decrease\":\"Decrease\",\"rss.increase\":\"Increase\",\"rss.handler_missing\":\"RSS handler not configured.\",\"rss.no_items\":\"No items found in this feed.\",\"rss.configure_feed\":\"RSS Feed\",\"rss.configure_feed_desc\":\"Add an RSS URL in the settings panel to display your feed here.\",\"rss.loading\":\"Loading feed...\",\"rss.network_error\":\"Could not reach the feed URL. Please check the URL and try again.\",\"rss.parse_error\":\"The URL does not contain a valid RSS feed.\",\"rss.read_more\":\"Read more\",\"rss.by\":\"by\",\"section.rss_feed\":\"RSS FEED\",\"section.rss_display\":\"DISPLAY OPTIONS\",\"dialog.ok\":\"OK\",\"dialog.error\":\"Error\",\"dialog.success\":\"Success\",\"dialog.info\":\"Info\",\"dialog.close\":\"Close\",\"dialog.save\":\"Save\",\"dimension.preset_sm\":\"Small\",\"dimension.preset_md\":\"Medium\",\"dimension.preset_lg\":\"Large\",\"dimension.preset_full\":\"Full\",\"dimension.placeholder\":\"auto\",\"dimension.placeholder_fill\":\"fill\",\"dimension.help_fill\":\"Grows to absorb any remaining row space\",\"dimension.clear\":\"Clear value\",\"dimension.exact_value\":\"Exact value\",\"dimension.auto_active\":\"Using natural image size\",\"dimension.menu_unit\":\"Unit\",\"dimension.menu_quick\":\"Quick size\",\"dimension.banner\":\"Use <b>px</b> for fixed sizing (best for email), <b>%</b> for responsive layouts. Leave one side on <b>auto</b> to preserve aspect ratio.\",\"padding.help\":\"Use the controls below to set values for each side (Top, Left, Right, Bottom). All values are in pixels (px). Click ✕ to clear a value.\",\"padding.top\":\"Top\",\"padding.left\":\"Left\",\"padding.right\":\"Right\",\"padding.bottom\":\"Bottom\",\"padding.clear\":\"Clear value\",\"padding.pin_on\":\"Keep padding guides visible on canvas\",\"padding.pin_off\":\"Stop keeping padding guides visible\",\"padding.pin_label_off\":\"Pin preview\",\"padding.pin_label_on\":\"Pinned\",\"inner_padding.help\":\"Adjust inner spacing to shape this element — larger values make it bigger, smaller values make it more compact.\",\"social.add\":\"Add\",\"social.add_facebook\":\"Add Facebook\",\"social.add_instagram\":\"Add Instagram\",\"social.add_linkedin\":\"Add LinkedIn\",\"social.add_twitter\":\"Add Twitter (X)\",\"social.add_youtube\":\"Add YouTube\",\"social.add_tiktok\":\"Add TikTok\",\"social.add_pinterest\":\"Add Pinterest\",\"social.choose_platform\":\"Choose platform\",\"social.label\":\"Label\",\"social.url_label\":\"URL\",\"social.move_up\":\"Move up\",\"social.move_down\":\"Move down\",\"social.delete_item\":\"Delete item\",\"color.not_set\":\"not set\",\"page.untitled\":\"Untitled Page\",\"widgets_box.drag_hint\":\"Just drag & drop the widget into the page content to insert!\",\"widgets_box.field_required\":\"Required\",\"widgets_box.field_optional\":\"Optional\",\"widgets_box.field_visible\":\"Visible on form\",\"widgets_box.field_hidden\":\"Hidden field\",\"widgets_box.field_type_action\":\"action\",\"widgets_box.field_type_compliance\":\"compliance\",\"widgets_box.field_type_required_for_form\":\"Required for form\",\"widgets_box.submit_button\":\"Submit button\",\"widgets_box.list_subscribers\":\"subscribers\",\"widgets_box.list_fields\":\"fields\",\"widgets.ad_headline\":\"Ad Headline\",\"widgets.ad_primary_text\":\"Primary Text\",\"widgets.ad_description\":\"Description\",\"widgets.ad_cta\":\"Call to Action\",\"widgets.ad_image\":\"Ad Image\",\"widgets.ad_logo\":\"Brand Logo\",\"widgets.ad_carousel_card\":\"Carousel Card\",\"elements.ad_headline_default\":\"Your attention-grabbing headline\",\"elements.ad_primary_text_default\":\"Your body copy here. Keep it short, clear, and actionable — under 125 characters works best on most platforms.\",\"elements.ad_description_default\":\"One-line sub-text\",\"elements.ad_cta_default\":\"Learn More\",\"elements.ad_carousel_headline_default\":\"Card headline\",\"elements.ad_carousel_desc_default\":\"Short sub-text\",\"validation.url_required\":\"URL is required.\",\"font.system_inherit\":\"System (inherit)\",\"form_container.name\":\"Form Area\",\"form_container.empty_title\":\"Drop form fields here\",\"form_container.empty_hint\":\"Or click ← Load list defaults in the sidebar\",\"image_effects.grayscale\":\"Grayscale\",\"image_effects.sepia\":\"Sepia\",\"image_effects.invert\":\"Invert\",\"image_effects.blur\":\"Blur\",\"image_effects.brightness\":\"Brightness\",\"image_effects.contrast\":\"Contrast\",\"image_effects.saturation\":\"Saturation\",\"image_effects.hue_rotate\":\"Hue Rotate\",\"image_effects.opacity\":\"Opacity\",\"image_effects.grayscale_desc\":\"🖌️ Converts the image to black and white, with values from 0% (normal) to 100% (completely grayscale).\",\"image_effects.sepia_desc\":\"🏺 Adds a warm, yellowish-brown tone to create a vintage or antique look.\",\"image_effects.invert_desc\":\"🔄 Reverses all colors in the image, like a photo negative effect.\",\"image_effects.blur_desc\":\"🌫️ Creates a soft focus effect, higher values increase the blurriness.\",\"image_effects.brightness_desc\":\"☀️ Adjusts how bright the image appears, 100% is normal, higher values increase brightness.\",\"image_effects.contrast_desc\":\"⚖️ Controls the difference between dark and light areas, 100% is normal.\",\"image_effects.saturation_desc\":\"🌈 Changes color intensity, 100% is normal, higher values make colors more vivid.\",\"image_effects.hue_rotate_desc\":\"🎨 Shifts all colors in the image by rotating them around the color wheel.\",\"image_effects.opacity_desc\":\"👻 Controls how transparent the image is, 100% is fully visible, 0% is invisible.\",\"image_effects.preview\":\"Preview\",\"image_effects.reset\":\"Reset Effects\",\"image_effects.effects\":\"Effects\",\"image_crop.title\":\"Crop & Focus\",\"image_crop.toggle_hint\":\"Enable CSS crop & focus point\",\"image_crop.email_warning\":\"CSS-based crop. Modern email clients render correctly. Outlook 2007–2013 and a few legacy clients fall back to the original full image.\",\"image_crop.aspect_ratio\":\"Aspect ratio\",\"image_crop.preset_original\":\"Original\",\"image_crop.custom_ratio\":\"Custom ratio\",\"image_crop.ratio_x\":\"Ratio X (width)\",\"image_crop.ratio_y\":\"Ratio Y (height)\",\"image_crop.swap_hint\":\"Swap X ↔ Y (rotate 90°)\",\"image_crop.zoom\":\"Zoom\",\"image_crop.focus_x\":\"Focus X\",\"image_crop.focus_y\":\"Focus Y\",\"image_crop.preview_hint\":\"Drag inside the preview to set focus · Scroll wheel to zoom\",\"image_crop.reset\":\"Reset crop\",\"border.title\":\"BORDERS\",\"border.description\":\"Adjust border style, width, and color.\",\"border.content_area\":\"Content area border\",\"border.more_options\":\"More options\",\"border.all_sides\":\"All sides\",\"border.top\":\"Top\",\"border.right\":\"Right\",\"border.bottom\":\"Bottom\",\"border.left\":\"Left\",\"border.style_solid\":\"Solid\",\"border.style_dashed\":\"Dashed\",\"border.style_dotted\":\"Dotted\",\"border.style_double\":\"Double\",\"border.style_none\":\"None\",\"border.transparent\":\"transparent\",\"border.style_label\":\"Border style\",\"border.width_label\":\"Border width (px)\",\"border.width_unit\":\"px\",\"border.color_label\":\"Border color\",\"border.mode_label\":\"Mode\",\"border.mode_all\":\"All\",\"border.mode_split\":\"Split\",\"border.preset_label\":\"Preset\",\"border.preset_none\":\"None\",\"border.preset_thin\":\"Thin\",\"border.preset_medium\":\"Medium\",\"border.preset_thick\":\"Thick\",\"border.copy_to_all\":\"Copy this side to all sides\",\"border.reset\":\"Reset borders\",\"border.preview_aria\":\"Preview\",\"border.preview_announce\":\"Border: {style} {width}px {color}\",\"number.decrement\":\"Decrease\",\"number.increment\":\"Increase\",\"select.element_name\":\"Element Name\",\"select.element_name_ph\":\"field_name\",\"select.add_item\":\"Add item\",\"select.remove_item\":\"Remove item\",\"select.label\":\"Label\",\"select.value\":\"Value\",\"line_height.line_1_2\":\"Line 1.2\",\"line_height.line_1_5\":\"Line 1.5\",\"line_height.line_1_8\":\"Line 1.8\",\"line_height.line_2\":\"Line 2\",\"line_height.select\":\"Select\",\"line_height.custom\":\"Custom\",\"font_weight.not_set\":\"not set\",\"font.not_set\":\"not set\",\"social.social_item\":\"Social item\",\"social.item_number\":\"Item #\",\"overlay.drag\":\"Drag\",\"overlay.drag_block\":\"Drag block\",\"overlay.resize\":\"Resize\",\"overlay.resize_corner\":\"Resize corner\",\"overlay.action_bar\":\"Element actions\",\"overlay.upload\":\"Upload\",\"overlay.replace\":\"Replace\",\"overlay.effects\":\"Effects\",\"overlay.crop\":\"Crop\",\"overlay.crop_title\":\"Crop image\",\"overlay.crop_enable\":\"Enable crop\",\"overlay.crop_enable_hint\":\"Off keeps the original image.\",\"overlay.crop_sidebar_hint\":\"Need zoom, focus point, or email compatibility? Open the sidebar panel.\",\"overlay.crop_confirm\":\"Done\",\"overlay.crop_cancel\":\"Cancel\",\"overlay.resize_title\":\"Resize image\",\"overlay.resize_width\":\"Width\",\"overlay.resize_height\":\"Height\",\"overlay.resize_aspect_lock\":\"Lock aspect ratio\",\"overlay.resize_aspect_hint\":\"Editing one dimension updates the other proportionally.\",\"overlay.resize_advanced\":\"Advanced — max / min\",\"overlay.resize_crop_hint\":\"Crop is on. Resizing keeps the crop frame; the cropped area re-fits to your new dimensions.\",\"overlay.link\":\"Link\",\"overlay.insert_column_before\":\"Insert column before\",\"overlay.insert_column_after\":\"Insert column after\",\"overlay.cell_resize\":\"Resize cell\",\"overlay.edit_text\":\"Edit text\",\"overlay.style\":\"Style\",\"overlay.settings\":\"Settings\",\"overlay.close\":\"Close\",\"overlay.link_url_prompt\":\"Link URL\",\"overlay.link_done\":\"Done\",\"button.settings.title\":\"Button settings\",\"button.settings.hint\":\"Esc to cancel · Click outside to apply\",\"button.settings.reset\":\"Reset\",\"button.section.shape\":\"Shape & size\",\"button.section.shape_desc\":\"Baseline size and corner radius.\",\"button.section.style\":\"Style Settings\",\"button.section.style_desc\":\"Preset look, size, shape & modifiers.\",\"button.section.effects\":\"Effects\",\"button.section.effects_desc\":\"Depth and micro-interactions. Page mode only.\",\"button.section.icon\":\"Icon\",\"button.section.icon_desc\":\"Optional pictogram beside, before, or instead of the label.\",\"button.section.layout\":\"Layout\",\"button.section.layout_desc\":\"Width within the block row.\",\"button.section.advanced\":\"Advanced\",\"button.section.advanced_desc\":\"Color, border, padding, font, spacing overrides.\",\"button.style.label\":\"Style\",\"button.style.custom_name\":\"Custom\",\"button.style.custom_summary\":\"Custom · advanced\",\"button.style.change_tooltip\":\"Browse all styles\",\"button.size.label\":\"Size\",\"button.size.xs\":\"Extra small\",\"button.size.sm\":\"Small\",\"button.size.md\":\"Medium\",\"button.size.lg\":\"Large\",\"button.size.xl\":\"Extra large\",\"button.radius.label\":\"Radius\",\"button.radius.sharp\":\"Sharp\",\"button.radius.sm\":\"SM\",\"button.radius.md\":\"MD\",\"button.radius.lg\":\"LG\",\"button.radius.pill\":\"Pill\",\"button.shadow.label\":\"Shadow\",\"button.shadow.none\":\"None\",\"button.shadow.sm\":\"SM\",\"button.shadow.md\":\"MD\",\"button.shadow.lg\":\"LG\",\"button.shadow.xl\":\"XL\",\"button.shadow.inner\":\"Inner\",\"button.hover.label\":\"Hover effect\",\"button.hover.none\":\"None\",\"button.hover.lift\":\"Lift\",\"button.hover.glow\":\"Glow\",\"button.hover.scale\":\"Scale\",\"button.hover.sweep\":\"Sweep\",\"button.hover.push\":\"Push\",\"button.icon.label\":\"Icon\",\"button.icon_pos.label\":\"Position\",\"button.icon_pos.left\":\"Left\",\"button.icon_pos.right\":\"Right\",\"button.icon_pos.only\":\"Only\",\"button.icon_pos.none\":\"None\",\"button.width.label\":\"Width\",\"button.width.auto\":\"Auto\",\"button.width.half\":\"50%\",\"button.width.full\":\"Full\",\"button.picker.title\":\"Pick a button style\",\"button.picker.cat_solid\":\"Solid\",\"button.picker.cat_outline\":\"Outline\",\"button.picker.cat_tonal\":\"Tonal\",\"button.picker.cat_ghost\":\"Ghost\",\"button.picker.cat_gradient\":\"Gradient\",\"button.picker.cat_elevated\":\"Elevated\",\"button.picker.cat_glass\":\"Glass & Glow\",\"button.picker.cat_brutalist\":\"Brutalist\",\"button.picker.cat_icon\":\"Icon-Led\",\"button.picker.page_only_short\":\"Page\",\"button.picker.vml_short\":\"VML\",\"button.picker.empty\":\"No presets in this category yet.\",\"button.picker.sample_text\":\"Action\",\"button.picker.footer_hint\":\"Esc to cancel · Click outside to apply\",\"button.picker.reset\":\"Reset\",\"errors.template_not_found_title\":\"Template not found\",\"errors.template_not_found_msg\":\"Template \\\\\"{name}\\\\\" could not be located in the current theme.\",\"errors.unused_ejs_keys_title\":\"Unused EJS keys\",\"errors.unused_ejs_keys_msg\":\"The following template keys were not used during render:\",\"history.undo\":\"Undo\",\"history.redo\":\"Redo\",\"history.title\":\"History\",\"history.clear\":\"Clear\",\"history.tx\":\"transaction\",\"history.entries_count\":\":n entries\",\"history.entries_count_one\":\":n entry\",\"history.default_label\":\"Edit\",\"history.edit\":\"Edit\",\"history.edit_type\":\"Edit :type\",\"history.edit_type_region\":\"Edit :region on :type\",\"history.initial\":\"Initial state\",\"history.edit_text\":\"Edit text\",\"history.paste\":\"Paste\",\"history.empty_title\":\"Nothing to undo yet\",\"history.empty_note\":\"Your edits will appear here. Undo with\",\"history.format_text_color\":\"Change text color\",\"history.format_link_color\":\"Change link color\",\"history.format_background\":\"Change background\",\"history.format_background_color\":\"Change background color\",\"history.format_padding_top\":\"Adjust padding\",\"history.format_padding_bottom\":\"Adjust padding\",\"history.format_padding_left\":\"Adjust padding\",\"history.format_padding_right\":\"Adjust padding\",\"history.format_margin_top\":\"Adjust margin\",\"history.format_margin_bottom\":\"Adjust margin\",\"history.format_margin_left\":\"Adjust margin\",\"history.format_margin_right\":\"Adjust margin\",\"history.format_font_size\":\"Change font size\",\"history.format_font_family\":\"Change font\",\"history.format_font_weight\":\"Change font weight\",\"history.format_line_height\":\"Change line height\",\"history.format_letter_spacing\":\"Change letter spacing\",\"history.format_border\":\"Change border\",\"history.format_border_radius\":\"Change border radius\",\"history.format_align\":\"Change alignment\",\"history.format_size\":\"Resize\",\"history.format_width\":\"Change width\",\"history.format_height\":\"Change height\",\"history.format_filter_brightness\":\"Adjust brightness\",\"history.format_filter_contrast\":\"Adjust contrast\",\"history.format_aspect_lock\":\"Toggle aspect lock\",\"history.format_generic\":\"Change style\",\"history.content_text\":\"Edit text\",\"history.content_src\":\"Change image\",\"history.content_url\":\"Change link\",\"history.content_html\":\"Edit HTML\",\"history.content_alt\":\"Edit alt text\",\"history.structure_add\":\"Add :type\",\"history.structure_remove\":\"Delete :type\",\"history.structure_move\":\"Move :type\",\"history.structure_duplicate\":\"Duplicate :type\",\"history.page_title\":\"Change page title\",\"history.page_theme\":\"Change theme\",\"history.page_block_gap\":\"Change spacing\",\"history.page_clear\":\"Clear page\",\"history.ai_generate\":\"AI: :prompt\",\"history.ai_rewrite\":\"AI rewrite\",\"history.ai_translate\":\"AI translate\",\"history.ai_inline_rewrite\":\"AI :prompt\",\"history.ai_action_rewrite\":\"rewrite\",\"history.ai_action_improve\":\"improve\",\"history.ai_action_shorten\":\"shorten\",\"history.ai_action_expand\":\"expand\",\"history.ai_action_simplify\":\"simplify\",\"history.ai_action_fix_grammar\":\"fix grammar\",\"history.ai_action_cta_ify\":\"CTA-ify\",\"history.ai_action_translate\":\"translate\",\"history.ai_action_rewrite_on_brand\":\"rewrite on brand\",\"history.external\":\"External change\",\"history.relative_time.just_now\":\"just now\",\"history.relative_time.seconds_ago\":\":ns ago\",\"history.relative_time.minutes_ago\":\":nm ago\",\"history.relative_time.hours_ago\":\":nh ago\",\"history.element_type.PageElement\":\"Page\",\"history.element_type.BlockElement\":\"Block\",\"history.element_type.CellElement\":\"Cell\",\"history.element_type.HeadingElement\":\"Heading\",\"history.element_type.TextElement\":\"Text\",\"history.element_type.ParagraphElement\":\"Paragraph\",\"history.element_type.ImageElement\":\"Image\",\"history.element_type.ButtonElement\":\"Button\",\"history.element_type.DividerElement\":\"Divider\",\"history.element_type.SpacerElement\":\"Spacer\",\"history.element_type.VideoElement\":\"Video\",\"history.element_type.YoutubeElement\":\"YouTube\",\"history.element_type.AlertElement\":\"Alert\",\"history.element_type.HtmlElement\":\"HTML\",\"history.element_type.ListElement\":\"List\",\"history.element_type.TableElement\":\"Table\",\"history.element_type.CheckoutElement\":\"Checkout\",\"history.element_type.CheckoutSimpleElement\":\"Checkout\",\"history.element_type.FormElement\":\"Form\",\"history.element_type.FieldElement\":\"Field\",\"inline_toolbar.aria_label\":\"Text formatting\",\"inline_toolbar.bold\":\"Bold\",\"inline_toolbar.italic\":\"Italic\",\"inline_toolbar.underline\":\"Underline\",\"inline_toolbar.strikethrough\":\"Strikethrough\",\"inline_toolbar.text_color\":\"Text color\",\"inline_toolbar.highlight_color\":\"Highlight color\",\"inline_toolbar.link\":\"Link\",\"inline_toolbar.alignment\":\"Alignment\",\"inline_toolbar.align_left\":\"Align left\",\"inline_toolbar.align_center\":\"Align center\",\"inline_toolbar.align_right\":\"Align right\",\"inline_toolbar.align_justify\":\"Justify\",\"inline_toolbar.more\":\"More options\",\"inline_toolbar.font\":\"Font\",\"inline_toolbar.advanced\":\"Advanced text\",\"inline_toolbar.ai_rewrite\":\"AI rewrite\",\"inline_toolbar.paragraph_style\":\"Paragraph style\",\"inline_toolbar.coming_in\":\"ships in {wave}\",\"color_popover.recent\":\"Recent\",\"color_popover.palette\":\"Palette\",\"color_popover.standard\":\"Standard\",\"color_popover.custom\":\"Custom\",\"color_popover.reset\":\"Reset\",\"color_popover.remove\":\"Remove color\",\"color_popover.eyedropper\":\"Pick color from page\",\"link_popover.title\":\"Link\",\"link_popover.apply\":\"Apply\",\"link_popover.cancel\":\"Cancel\",\"link_popover.remove\":\"Remove link\",\"link_popover.remove_disabled_host_anchor\":\"This element is already a link — edit in the sidebar or delete the element to remove.\",\"link_popover.err_empty_url\":\"Enter a URL before applying.\",\"link_popover.err_remove_failed\":\"Couldn\\'t remove the link. Try selecting just the linked text and retry.\",\"font_popover.title\":\"Font\",\"font_popover.preview_text\":\"The quick brown fox\",\"font_popover.scope_note\":\"Font changes apply to the whole text block — not just the highlighted range.\",\"rich_menu.aria_label\":\"Menu\",\"more_menu.heading_clipboard\":\"Clipboard\",\"more_menu.heading_format\":\"Format\",\"more_menu.cut\":\"Cut\",\"more_menu.copy\":\"Copy\",\"more_menu.copy_format\":\"Copy format\",\"more_menu.paste_format\":\"Paste format\",\"more_menu.clear_format\":\"Clear format\",\"more_menu.remove_link\":\"Remove link\",\"ai_rewrite.dialog_title\":\"AI rewrite\",\"ai_rewrite.close\":\"Close\",\"ai_rewrite.cancel\":\"Cancel\",\"ai_rewrite.back\":\"Back\",\"ai_rewrite.rewrite\":\"Rewrite\",\"ai_rewrite.try_again\":\"Try again\",\"ai_rewrite.apply\":\"Apply\",\"ai_rewrite.loading\":\"Generating with AI…\",\"ai_rewrite.applied_toast\":\"Rewritten — ⌘Z to undo\",\"ai_rewrite.disabled_title\":\"AI features disabled\",\"ai_rewrite.disabled_msg\":\"Set AI_ENABLED=true on the server to enable inline AI rewrites.\",\"ai_rewrite.quick_actions\":\"Quick actions\",\"ai_rewrite.tone\":\"Tone\",\"ai_rewrite.length\":\"Length\",\"ai_rewrite.custom_prompt\":\"Custom instruction\",\"ai_rewrite.custom_placeholder\":\"Describe exactly what you want — e.g. \\\\\"more confident, fewer adjectives\\\\\"\",\"ai_rewrite.action_improve\":\"Improve\",\"ai_rewrite.action_shorten\":\"Shorten\",\"ai_rewrite.action_expand\":\"Expand\",\"ai_rewrite.action_simplify\":\"Simplify\",\"ai_rewrite.action_fix_grammar\":\"Fix grammar\",\"ai_rewrite.action_cta_ify\":\"CTA-ify\",\"ai_rewrite.action_translate\":\"Translate\",\"ai_rewrite.action_custom\":\"Rewrite\",\"ai_rewrite.tone_formal\":\"Formal\",\"ai_rewrite.tone_casual\":\"Casual\",\"ai_rewrite.tone_playful\":\"Playful\",\"ai_rewrite.tone_persuasive\":\"Persuasive\",\"ai_rewrite.tone_friendly\":\"Friendly\",\"ai_rewrite.tone_urgent\":\"Urgent\",\"ai_rewrite.length_shorter\":\"Shorter\",\"ai_rewrite.length_same\":\"Same\",\"ai_rewrite.length_longer\":\"Longer\",\"ai_rewrite.error_rate_limit\":\"Rate limited\",\"ai_rewrite.error_disabled\":\"AI disabled\",\"ai_rewrite.error_timeout\":\"Timeout\",\"ai_rewrite.error_engine\":\"AI engine error\",\"ai_rewrite.error_configuration\":\"Configuration error\",\"ai_rewrite.error_validation\":\"Validation error\",\"ai_rewrite.error_internal\":\"Server error\",\"ai_rewrite.error_task_not_found\":\"Feature not registered\",\"ai_rewrite.error_unknown\":\"Error\",\"ai_rewrite.error_no_variants\":\"AI returned no variants. Try again with different settings.\",\"ai_rewrite.error_empty_selection\":\"Select some text first to use AI rewrite.\"}');\n\n//# sourceURL=webpack://BuilderBundle/./src/lang/en.json?");
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module can't be inlined because the eval devtool is used.
/******/ var __webpack_exports__ = __webpack_require__("./src/builder.js");
/******/ BuilderBundle = __webpack_exports__;
/******/
/******/ })()
;