@bensitu/image-editor 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/image-editor.js"],
4
- "sourcesContent": ["function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = \"function\" == typeof Symbol ? Symbol : {}, n = r.iterator || \"@@iterator\", o = r.toStringTag || \"@@toStringTag\"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, \"_invoke\", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError(\"Generator is already running\"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = \"next\"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError(\"iterator result is not an object\"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError(\"The iterator does not provide a '\" + o + \"' method\"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, \"GeneratorFunction\")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, \"constructor\", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, \"constructor\", GeneratorFunction), GeneratorFunction.displayName = \"GeneratorFunction\", _regeneratorDefine2(GeneratorFunctionPrototype, o, \"GeneratorFunction\"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, \"Generator\"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, \"toString\", function () { return \"[object Generator]\"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }\nfunction _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, \"\", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o(\"next\", 0), o(\"throw\", 1), o(\"return\", 2)); }, _regeneratorDefine2(e, r, n, t); }\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); }\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); }\n/**\n * @file image-editor.js\n * @module image-editor\n * @version 1.2.0\n * @author Ben Situ\n * @license MIT\n * @description Lightweight canvas-based image editor with masking/transform/export support.\n *\n * This source file is free software, available under the MIT license.\n * It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;\n * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n * See the license files for details.\n */\n\n(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD / RequireJS\n define([], factory);\n } else if ((typeof module === \"undefined\" ? \"undefined\" : _typeof(module)) === 'object' && module.exports) {\n // CommonJS / Node / webpack (target=commonjs)\n module.exports = factory();\n } else {\n // Browser normal <script> method, hanging to the global\n root.ImageEditor = factory();\n }\n})(typeof self !== 'undefined' ? self : this, function () {\n 'use strict';\n\n /**\n * ImageEditor\n * \n * A lightweight wrapper around fabric.js providing masking, scaling, rotation,\n * merging/export helpers, and UI integrations for image editing.\n *\n * <b>Note:</b> Requires fabric.js (v5.x) to be loaded on the page before use.\n *\n * <pre>\n * Example usage:\n * const editor = new ImageEditor({ canvasWidth: 1024, canvasHeight: 768 });\n * editor.init();\n * </pre>\n *\n * @class ImageEditor\n * @classdesc Fabric.js-based image editor with simple mask, transform, export and UI features.\n *\n * @param {Object} [options={}] - Customization options to override defaults.\n * @param {number} [options.canvasWidth=800] - The initial canvas width in pixels.\n * @param {number} [options.canvasHeight=600] - The initial canvas height in pixels.\n * @param {string} [options.backgroundColor='transparent'] - The canvas background color.\n * @param {number} [options.animationDuration=300] - Duration in ms for scale/rotate animations.\n * @param {number} [options.minScale=0.1] - Minimum image scaling factor.\n * @param {number} [options.maxScale=5.0] - Maximum image scaling factor.\n * @param {number} [options.scaleStep=0.05] - Scale increment/decrement per step.\n * @param {number} [options.rotationStep=90] - Rotation step in degrees.\n * @param {boolean} [options.expandCanvasToImage=true] - If true, expands the canvas to fit image/mask.\n * @param {boolean} [options.fitImageToCanvas=false] - If true, fits loaded image inside canvas.\n * @param {boolean} [options.coverImageToCanvas=false] - If true, scales image to cover canvas (at least one side fits, allowing overflow).\n * @param {boolean} [options.downsampleOnLoad=true] - Whether to downsample very large images on load.\n * @param {number} [options.downsampleMaxWidth=4000] - Max width for downsampling.\n * @param {number} [options.downsampleMaxHeight=3000] - Max height for downsampling.\n * @param {number} [options.downsampleQuality=0.92] - JPEG quality for downsampling/export.\n * @param {number} [options.exportMultiplier=1] - Scale output image by this multiplier on export.\n * @param {boolean} [options.exportImageAreaByDefault=true] - Export only the image area (clipped to masks).\n * @param {number} [options.defaultMaskWidth=50] - Default width of new mask rectangles.\n * @param {number} [options.defaultMaskHeight=80] - Default height of new masks.\n * @param {boolean} [options.maskRotatable=false] - If true, masks can be rotated.\n * @param {boolean} [options.maskLabelOnSelect=true] - Show label on selected mask.\n * @param {number} [options.maskLabelOffset=3] - Offset for mask labels from top-left corner.\n * @param {string} [options.maskName='mask'] - Prefix for mask names/labels.\n * @param {boolean} [options.showPlaceholder=true] - If true, shows placeholder when no image is loaded.\n * @param {string|null} [options.initialImageBase64=null] - Base64 string to auto-load as initial image, if any.\n * @param {string} [options.defaultDownloadFileName='edited_image.jpg'] - Default file name for downloads.\n * @param {function} [options.onImageLoaded] - Optional callback to invoke after an image loads.\n * \n * @constructor\n */\n var ImageEditor = /*#__PURE__*/function () {\n function ImageEditor() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _classCallCheck(this, ImageEditor);\n // Verify that fabric.js is present\n this._fabricLoaded = typeof fabric !== 'undefined';\n if (!this._fabricLoaded) {\n console.error('fabric.js is not loaded. Please include fabric.js first. Initialization will be aborted.');\n }\n // Default options (can be overridden via ctor param)\n this.options = _objectSpread({\n canvasWidth: 800,\n canvasHeight: 600,\n backgroundColor: 'transparent',\n animationDuration: 300,\n minScale: 0.1,\n maxScale: 5.0,\n scaleStep: 0.05,\n rotationStep: 90,\n expandCanvasToImage: true,\n fitImageToCanvas: false,\n coverImageToCanvas: false,\n downsampleOnLoad: true,\n downsampleMaxWidth: 4000,\n downsampleMaxHeight: 3000,\n downsampleQuality: 0.92,\n exportMultiplier: 1,\n exportImageAreaByDefault: true,\n defaultMaskWidth: 50,\n defaultMaskHeight: 80,\n maskRotatable: false,\n maskLabelOnSelect: true,\n maskLabelOffset: 3,\n maskName: 'mask',\n groupSelection: false,\n showPlaceholder: true,\n initialImageBase64: null,\n // Provide a base64 'data:image/...' string here if you want auto-load\n\n defaultDownloadFileName: 'edited_image.jpg'\n }, options);\n this.options.label = {\n getText: function getText(mask, maskIndex) {\n return mask.maskName;\n },\n textOptions: {\n fontSize: 12,\n fill: '#fff',\n backgroundColor: 'rgba(0,0,0,0.7)',\n padding: 2,\n fontFamily: \"monospace\",\n fontWeight: \"bold\",\n selectable: false,\n evented: false,\n originX: 'left',\n originY: 'top'\n }\n };\n this.options.crop = {\n minWidth: 100,\n minHeight: 100,\n padding: 10,\n hideMasksDuringCrop: true,\n preserveMasksAfterCrop: true,\n allowRotationOfCropRect: false\n };\n\n // Runtime state\n this.canvas = null;\n this.canvasEl = null;\n this.containerEl = null;\n this.placeholderEl = null;\n this.originalImage = null; // fabric.Image\n this.baseImageScale = 1;\n this.currentScale = 1;\n this.currentRotation = 0;\n this.maskCounter = 0;\n this.isAnimating = false;\n this.elements = {};\n this.isImageLoadedToCanvas = false;\n this.maxHistorySize = 50;\n this._boundHandlers = {};\n this._lastMaskInitialLeft = null;\n this._lastMaskInitialTop = null;\n this._lastMaskInitialWidth = null;\n this._cropMode = false;\n this._cropRect = null;\n this._cropHandlers = [];\n this.onImageLoaded = typeof options.onImageLoaded === 'function' ? options.onImageLoaded : null;\n this.animQueue = new AnimationQueue();\n this.historyManager = new HistoryManager(this.maxHistorySize);\n }\n\n /**\n * Initializes the editor, binds to DOM elements, sets up event handlers,\n * and (optionally) loads an initial image.\n * Use this method to set up the editor UI before interacting with it.\n *\n * @param {Object} [idMap={}] - Optional mapping from logical element names to actual DOM element IDs.\n * Supported keys include: canvas, canvasContainer, imgPlaceholder, scaleRate, rotationLeftInput, rotationRightInput,\n * rotateLeftBtn, rotateRightBtn, addMaskBtn, removeMaskBtn, removeAllMasksBtn, mergeBtn, downloadBtn, maskList,\n * zoomInBtn, zoomOutBtn, resetBtn, imageInput. Unknown keys are ignored.\n *\n * @returns {void}\n *\n * @public\n *\n * @example\n * editor.init({\n * canvas: 'myFabricCanvasId',\n * downloadBtn: 'myDownloadButtonId'\n * });\n */\n return _createClass(ImageEditor, [{\n key: \"init\",\n value: function init() {\n var idMap = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (!this._fabricLoaded) return;\n var defaults = {\n canvas: 'fabricCanvas',\n canvasContainer: null,\n // Pass an ID here if you have a scrollable viewport container\n imgPlaceholder: 'imgPlaceholder',\n scaleRate: 'scaleRate',\n rotationLeftInput: 'rotationLeftInput',\n rotationRightInput: 'rotationRightInput',\n rotateLeftBtn: 'rotateLeftBtn',\n rotateRightBtn: 'rotateRightBtn',\n addMaskBtn: 'addMaskBtn',\n removeMaskBtn: 'removeMaskBtn',\n removeAllMasksBtn: 'removeAllMasksBtn',\n mergeBtn: 'mergeBtn',\n downloadBtn: 'downloadBtn',\n maskList: 'maskList',\n zoomInBtn: 'zoomInBtn',\n zoomOutBtn: 'zoomOutBtn',\n resetBtn: 'resetBtn',\n undoBtn: 'undoBtn',\n redoBtn: 'redoBtn',\n imageInput: 'imageInput',\n cropBtn: 'cropBtn',\n applyCropBtn: 'applyCropBtn',\n cancelCropBtn: 'cancelCropBtn'\n };\n this.elements = _objectSpread(_objectSpread({}, defaults), idMap);\n this._initCanvas();\n this._bindEvents();\n this._updateInputs();\n this._updateMaskList();\n this._updateUI();\n\n // Auto-load initial image if provided\n if (this.options.initialImageBase64) {\n this.loadImage(this.options.initialImageBase64);\n } else {\n this._updatePlaceholderStatus();\n }\n }\n\n /**\n * Canvas setup helpers\n * @private\n */\n }, {\n key: \"_initCanvas\",\n value: function _initCanvas() {\n var _this = this;\n var canvasEl = document.getElementById(this.elements.canvas);\n if (!canvasEl) throw new Error('Canvas is not found: ' + this.elements.canvas);\n this.canvasEl = canvasEl;\n\n // Decide which element acts as \"viewport\" (for width/height fallback)\n if (this.elements.canvasContainer) {\n var ce = document.getElementById(this.elements.canvasContainer);\n this.containerEl = ce || canvasEl.parentElement;\n } else {\n this.containerEl = canvasEl.parentElement;\n }\n this.placeholderEl = document.getElementById(this.elements.imgPlaceholder) || null;\n\n // Initial size \u2014 take container size if available\n var initialW = this.options.canvasWidth;\n var initialH = this.options.canvasHeight;\n if (this.containerEl) {\n var cw = Math.floor(this.containerEl.clientWidth);\n var ch = Math.floor(this.containerEl.clientHeight);\n if (cw > 0 && ch > 0) {\n initialW = cw;\n initialH = ch;\n }\n }\n this.canvas = new fabric.Canvas(canvasEl, {\n width: initialW,\n height: initialH,\n backgroundColor: this.options.backgroundColor,\n selection: this.options.groupSelection,\n preserveObjectStacking: true\n });\n\n // Fabric event wiring\n this.canvas.on('selection:created', function (e) {\n return _this._onSelectionChanged(e.selected);\n });\n this.canvas.on('selection:updated', function (e) {\n return _this._onSelectionChanged(e.selected);\n });\n this.canvas.on('selection:cleared', function () {\n return _this._onSelectionChanged([]);\n });\n this.canvas.on('object:moving', function (e) {\n if (e.target && e.target.maskId) _this._syncMaskLabel(e.target);\n });\n this.canvas.on('object:scaling', function (e) {\n if (e.target && e.target.maskId) _this._syncMaskLabel(e.target);\n });\n this.canvas.on('object:rotating', function (e) {\n if (e.target && e.target.maskId) _this._syncMaskLabel(e.target);\n });\n this.canvas.on('object:modified', function (e) {\n if (e.target && e.target.maskId) _this._syncMaskLabel(e.target);\n });\n\n // Avoid inline-element whitespace artefacts\n this.canvasEl.style.display = 'block';\n }\n\n /** \n * DOM / UI bindings\n * @private\n */\n }, {\n key: \"_bindEvents\",\n value: function _bindEvents() {\n var _this2 = this;\n // Click anywhere on the upload area opens the native file dialog\n this._bindIfExists('uploadArea', 'click', function () {\n var _document$getElementB;\n return (_document$getElementB = document.getElementById(_this2.elements.imageInput)) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.click();\n });\n // File-input change\n var inputEl = document.getElementById(this.elements.imageInput);\n if (inputEl) {\n inputEl.addEventListener('change', function (e) {\n var f = e.target.files && e.target.files[0];\n if (f) _this2._loadImageFile(f);\n });\n }\n // Zoom & reset\n this._bindIfExists('zoomInBtn', 'click', function () {\n return _this2.scaleImage(_this2.currentScale + _this2.options.scaleStep);\n });\n this._bindIfExists('zoomOutBtn', 'click', function () {\n return _this2.scaleImage(_this2.currentScale - _this2.options.scaleStep);\n });\n this._bindIfExists('resetBtn', 'click', function () {\n _this2.reset();\n });\n // Mask management\n this._bindIfExists('addMaskBtn', 'click', function () {\n return _this2.addMask();\n });\n this._bindIfExists('removeMaskBtn', 'click', function () {\n return _this2.removeSelectedMask();\n });\n this._bindIfExists('removeAllMasksBtn', 'click', function () {\n return _this2.removeAllMasks();\n });\n // Merge + download\n this._bindIfExists('mergeBtn', 'click', function () {\n return _this2.merge();\n });\n this._bindIfExists('downloadBtn', 'click', function () {\n return _this2.downloadImage();\n });\n // Undo + Redo\n this._bindIfExists('undoBtn', 'click', function () {\n return _this2.undo();\n });\n this._bindIfExists('redoBtn', 'click', function () {\n return _this2.redo();\n });\n\n // Rotation buttons (step can be overridden by two input fields)\n var rotLeftBtn = document.getElementById(this.elements.rotateLeftBtn);\n var rotRightBtn = document.getElementById(this.elements.rotateRightBtn);\n if (rotLeftBtn) rotLeftBtn.addEventListener('click', function () {\n var el = document.getElementById(_this2.elements.rotationLeftInput);\n var step = _this2.options.rotationStep;\n if (el) {\n var p = parseFloat(el.value);\n if (!isNaN(p)) step = p;\n }\n _this2.rotateImage(_this2.currentRotation - step);\n });\n if (rotRightBtn) rotRightBtn.addEventListener('click', function () {\n var el = document.getElementById(_this2.elements.rotationRightInput);\n var step = _this2.options.rotationStep;\n if (el) {\n var p = parseFloat(el.value);\n if (!isNaN(p)) step = p;\n }\n _this2.rotateImage(_this2.currentRotation + step);\n });\n\n // Crop bindings (optional: bound only if element IDs exist in elements)\n this._bindIfExists('cropBtn', 'click', function () {\n return _this2.enterCropMode();\n });\n this._bindIfExists('applyCropBtn', 'click', function () {\n _this2.applyCrop().catch(function (e) {\n return console.error('applyCrop failed', e);\n });\n });\n this._bindIfExists('cancelCropBtn', 'click', function () {\n return _this2.cancelCrop();\n });\n }\n\n /** \n * Event binding element check\n * \n * @param {*} event \n * @param {*} handler \n * @param {*} key \n * @private\n */\n }, {\n key: \"_bindIfExists\",\n value: function _bindIfExists(key, event, handler) {\n var el = document.getElementById(this.elements[key]);\n if (el) {\n el.addEventListener(event, handler);\n this._boundHandlers = this._boundHandlers || {};\n if (!this._boundHandlers[key]) this._boundHandlers[key] = [];\n this._boundHandlers[key].push({\n event: event,\n handler: handler\n });\n }\n }\n\n /** \n * Image loading helpers\n * \n * @param {File} file \n * @private\n */\n }, {\n key: \"_loadImageFile\",\n value: function _loadImageFile(file) {\n var _this3 = this;\n if (!file || !file.type.startsWith('image/')) return;\n var reader = new FileReader();\n reader.onload = function (e) {\n return _this3.loadImage(e.target.result);\n };\n reader.onerror = function (e) {\n console.error(\"[ImageEditor: fileReadError]\", e);\n };\n reader.readAsDataURL(file);\n }\n\n /**\n * Load a base64 encoded image string into fabric.\n * @async\n * @param {String} base64 \n */\n }, {\n key: \"loadImage\",\n value: (function () {\n var _loadImage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(base64) {\n var _this4 = this;\n var imgEl, loadSrc, needResize, ratio, tw, th;\n return _regenerator().w(function (_context) {\n while (1) switch (_context.n) {\n case 0:\n if (this._fabricLoaded) {\n _context.n = 1;\n break;\n }\n return _context.a(2);\n case 1:\n if (!(!base64 || typeof base64 !== 'string' || !base64.startsWith('data:image/'))) {\n _context.n = 2;\n break;\n }\n return _context.a(2);\n case 2:\n this._setPlaceholderVisible(false);\n _context.n = 3;\n return this._createImageElement(base64);\n case 3:\n imgEl = _context.v;\n loadSrc = base64;\n if (this.options.downsampleOnLoad) {\n needResize = imgEl.naturalWidth > this.options.downsampleMaxWidth || imgEl.naturalHeight > this.options.downsampleMaxHeight;\n if (needResize) {\n ratio = Math.min(this.options.downsampleMaxWidth / imgEl.naturalWidth, this.options.downsampleMaxHeight / imgEl.naturalHeight);\n tw = Math.round(imgEl.naturalWidth * ratio);\n th = Math.round(imgEl.naturalHeight * ratio);\n loadSrc = this._resampleImageToDataURL(imgEl, tw, th, this.options.downsampleQuality);\n }\n }\n\n // Create fabric.Image from URL\n fabric.Image.fromURL(loadSrc, function (fimg) {\n _this4.canvas.discardActiveObject();\n _this4._hideAllMaskLabels();\n _this4.canvas.clear();\n _this4.canvas.setBackgroundColor(_this4.options.backgroundColor, _this4.canvas.renderAll.bind(_this4.canvas));\n fimg.set({\n originX: 'left',\n originY: 'top',\n selectable: false,\n evented: false\n });\n var imgW = fimg.width;\n var imgH = fimg.height;\n var minW = _this4.containerEl ? Math.floor(_this4.containerEl.clientWidth || _this4.options.canvasWidth) : _this4.options.canvasWidth;\n var minH = _this4.containerEl ? Math.floor(_this4.containerEl.clientHeight || _this4.options.canvasHeight) : _this4.options.canvasHeight;\n if (_this4.options.fitImageToCanvas) {\n // Fit into current canvas (shrink only) and ensure canvas does not exceed container\n var cw = Math.max(1, Math.min(_this4.options.canvasWidth, minW) - 1);\n var ch = Math.max(1, Math.min(_this4.options.canvasHeight, minH) - 1);\n _this4._setCanvasSizeInt(cw, ch);\n var fitScale = Math.min(cw / imgW, ch / imgH, 1);\n fimg.set({\n left: 0,\n top: 0\n });\n fimg.scale(fitScale);\n _this4.baseImageScale = fimg.scaleX || 1;\n } else if (_this4.options.coverImageToCanvas) {\n // Cover canvas: scale to cover, allowing overflow (at least one side fits)\n var _cw = Math.max(_this4.options.canvasWidth, minW);\n var _ch = Math.max(_this4.options.canvasHeight, minH);\n _this4._setCanvasSizeInt(_cw, _ch);\n var coverScale = Math.min(1, Math.max(_cw / imgW, _ch / imgH));\n fimg.set({\n left: 0,\n top: 0\n });\n fimg.scale(coverScale);\n _this4.baseImageScale = fimg.scaleX || 1;\n } else if (_this4.options.expandCanvasToImage) {\n // Expand canvas so that it fully contains the image\n var _cw2 = Math.max(minW, Math.floor(imgW));\n var _ch2 = Math.max(minH, Math.floor(imgH));\n _this4._setCanvasSizeInt(_cw2, _ch2);\n fimg.set({\n left: 0,\n top: 0\n });\n fimg.scale(1);\n _this4.baseImageScale = 1;\n } else {\n // Keep existing canvas size and center the image\n var _cw3 = Math.max(_this4.options.canvasWidth, minW);\n var _ch3 = Math.max(_this4.options.canvasHeight, minH);\n _this4._setCanvasSizeInt(_cw3, _ch3);\n var _fitScale = Math.min(_cw3 / imgW, _ch3 / imgH, 1);\n fimg.set({\n left: 0,\n top: 0\n });\n fimg.scale(_fitScale);\n _this4.baseImageScale = fimg.scaleX || 1;\n }\n // Put the image onto the canvas\n _this4.originalImage = fimg;\n _this4.canvas.add(fimg);\n _this4.canvas.sendToBack(fimg);\n\n // Reset mask placement memory\n _this4._lastMaskInitialLeft = null;\n _this4._lastMaskInitialTop = null;\n _this4._lastMaskInitialWidth = null;\n _this4.maskCounter = 0;\n _this4.currentScale = 1;\n _this4.currentRotation = 0;\n _this4._updateInputs();\n _this4._updateMaskList();\n _this4._updateUI();\n _this4.canvas.renderAll();\n _this4.isImageLoadedToCanvas = true;\n if (typeof _this4.onImageLoaded === 'function') {\n _this4.onImageLoaded();\n }\n }, {\n crossOrigin: 'anonymous'\n });\n case 4:\n return _context.a(2);\n }\n }, _callee, this);\n }));\n function loadImage(_x) {\n return _loadImage.apply(this, arguments);\n }\n return loadImage;\n }()\n /**\n * Checks whether there is a loaded image on the current canvas.\n * @returns {boolean} true if loaded, false if not\n */\n )\n }, {\n key: \"isImageLoaded\",\n value: function isImageLoaded() {\n return !!(this.originalImage && this.originalImage instanceof fabric.Image && this.originalImage.width > 0 && this.originalImage.height > 0);\n }\n\n /**\n * Creates an HTMLImageElement from a given data URL.\n * \n * @param {string} dataURL - A data URL representing the image (e.g., \"data:image/png;base64,...\").\n * @returns {Promise<HTMLImageElement>} A promise that resolves to the created image element when loaded, or rejects on error.\n * @private\n */\n }, {\n key: \"_createImageElement\",\n value: function _createImageElement(dataURL) {\n return new Promise(function (res, rej) {\n var img = new Image();\n img.onload = function () {\n img.onload = null;\n img.onerror = null;\n res(img);\n };\n img.onerror = function (e) {\n img.onload = null;\n img.onerror = null;\n rej(e);\n };\n img.src = dataURL;\n });\n }\n\n /**\n * Resamples the given image element to a new width and height and returns the result as a JPEG data URL.\n * \n * @param {HTMLImageElement} imgEl - The image element to resample.\n * @param {number} w - Target width (in pixels) for the resampled image.\n * @param {number} h - Target height (in pixels) for the resampled image.\n * @param {number} [quality=0.92] - JPEG image quality between 0 and 1 (optional, default 0.92).\n * @returns {string} A data URL representing the resampled image as JPEG.\n * @private\n */\n }, {\n key: \"_resampleImageToDataURL\",\n value: function _resampleImageToDataURL(imgEl, w, h) {\n var quality = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0.92;\n var oc = document.createElement('canvas');\n oc.width = w;\n oc.height = h;\n var ctx = oc.getContext('2d');\n ctx.drawImage(imgEl, 0, 0, imgEl.naturalWidth, imgEl.naturalHeight, 0, 0, w, h);\n return oc.toDataURL('image/jpeg', quality);\n }\n\n /** \n * Sets canvas size to integer width and height values to prevent scrollbars due to sub-pixel rendering.\n * Also updates the corresponding style attributes.\n * \n * @param {number} w - Canvas width (in pixels).\n * @param {number} h - Canvas height (in pixels).\n * @private\n */\n }, {\n key: \"_setCanvasSizeInt\",\n value: function _setCanvasSizeInt(w, h) {\n var iw = Math.max(1, Math.round(Number(w) || 1));\n var ih = Math.max(1, Math.round(Number(h) || 1));\n // Set fabric internal and also style attributes to keep DOM consistent\n this.canvas.setWidth(iw);\n this.canvas.setHeight(ih);\n if (typeof this.canvas.calcOffset === 'function') this.canvas.calcOffset();\n // Keep DOM element in sync (avoid fractional CSS pixels)\n if (this.canvasEl) {\n this.canvasEl.style.width = iw + 'px';\n this.canvasEl.style.height = ih + 'px';\n this.canvasEl.style.maxWidth = 'none';\n }\n }\n\n /** \n * Gets the top-left corner coordinates of the given object.\n * Used for geometry calculations (e.g., scale, rotate).\n * \n * @param {Object} obj - The object for which to get the top-left coordinates. Should support setCoords and getCoords/getBoundingRect methods.\n * @returns {{x: number, y: number}} The top-left corner point as an object with x and y properties.\n * @private\n */\n }, {\n key: \"_getObjectTopLeftPoint\",\n value: function _getObjectTopLeftPoint(obj) {\n if (!obj) return {\n x: 0,\n y: 0\n };\n obj.setCoords();\n var coords = typeof obj.getCoords === 'function' ? obj.getCoords() : null;\n if (coords && coords.length) return coords[0];\n var br = obj.getBoundingRect(true, true);\n return {\n x: br.left,\n y: br.top\n };\n }\n\n /**\n * Sets the object's origin at the specified origin point, keeping a reference point fixed in position.\n * \n * @param {Object} obj - The object to modify. Should support set, setPositionByOrigin, and setCoords.\n * @param {string} originX - The new originX (\"left\", \"center\", \"right\", etc.).\n * @param {string} originY - The new originY (\"top\", \"center\", \"bottom\", etc.).\n * @param {{x: number, y: number}} refPoint - The point to keep fixed while setting the new origins.\n * @private\n */\n }, {\n key: \"_setObjectOriginKeepingPosition\",\n value: function _setObjectOriginKeepingPosition(obj, originX, originY, refPoint) {\n if (!obj || !refPoint || !obj.setPositionByOrigin) return;\n obj.set({\n originX: originX,\n originY: originY\n });\n obj.setPositionByOrigin(refPoint, originX, originY);\n obj.setCoords();\n }\n\n /**\n * Moves the object so its bounding box aligns with the canvas's top-left corner (0, 0).\n * \n * @param {Object} obj - The object to align.\n * @private\n */\n }, {\n key: \"_alignObjectBoundingBoxToCanvasTopLeft\",\n value: function _alignObjectBoundingBoxToCanvasTopLeft(obj) {\n if (!obj) return;\n obj.setCoords();\n var br = obj.getBoundingRect(true, true);\n var dx = br.left;\n var dy = br.top;\n obj.set({\n left: (obj.left || 0) - dx,\n top: (obj.top || 0) - dy\n });\n obj.setCoords();\n this.canvas.renderAll();\n }\n\n /**\n * Updates the canvas size to match the bounding box of the original image,\n * ensuring that the canvas is always at least as large as its container.\n * @private\n */\n }, {\n key: \"_updateCanvasSizeToImageBounds\",\n value: function _updateCanvasSizeToImageBounds() {\n if (!this.originalImage) return;\n this.originalImage.setCoords();\n var br = this.originalImage.getBoundingRect(true, true);\n\n // Container integer sizes\n var containerW = this.containerEl ? Math.ceil(this.containerEl.clientWidth || 0) : 0;\n var containerH = this.containerEl ? Math.ceil(this.containerEl.clientHeight || 0) : 0;\n\n // If image smaller or equal than container in BOTH dims => keep canvas equal to container\n if (containerW > 0 && containerH > 0 && br.width <= containerW && br.height <= containerH) {\n this._setCanvasSizeInt(containerW, containerH);\n return;\n }\n\n // Else canvas follows image bounding box but not smaller than container dims individually\n var newW = Math.max(containerW || 0, Math.floor(br.width));\n var newH = Math.max(containerH || 0, Math.floor(br.height));\n this._setCanvasSizeInt(newW, newH);\n }\n\n /** \n * Scales the original image by a given factor, with animation.\n * Returns a promise that resolves when the scale animation is complete.\n * @param {number} factor - The scaling factor (will be clamped between `options.minScale` and `options.maxScale`).\n * @returns {Promise<void>} Promise that resolves once the scaling animation finishes.\n * @public\n */\n }, {\n key: \"scaleImage\",\n value: function scaleImage(factor) {\n var _this5 = this;\n return this.animQueue.add(function () {\n return _this5._scaleImageImpl(factor);\n });\n }\n\n /** \n * Scales the original image by a given factor, with animation.\n * Returns a promise that resolves when the scale animation is complete.\n * @param {number} factor - The scaling factor (will be clamped between `options.minScale` and `options.maxScale`).\n * @returns {Promise<void>} Promise that resolves once the scaling animation finishes.\n * @private\n */\n }, {\n key: \"_scaleImageImpl\",\n value: function _scaleImageImpl(factor) {\n var _this6 = this;\n if (!this.originalImage) return Promise.resolve();\n if (this.isAnimating) return Promise.resolve();\n factor = Math.max(this.options.minScale, Math.min(this.options.maxScale, factor));\n this.currentScale = factor;\n this.isAnimating = true;\n this._updateUI();\n var targetAbs = this.baseImageScale * factor;\n\n // Scale around current top-left (recompute)\n var topLeft = this._getObjectTopLeftPoint(this.originalImage);\n this._setObjectOriginKeepingPosition(this.originalImage, 'left', 'top', topLeft);\n var p1 = new Promise(function (res) {\n _this6.originalImage.animate('scaleX', targetAbs, {\n duration: _this6.options.animationDuration,\n onChange: _this6.canvas.renderAll.bind(_this6.canvas),\n onComplete: res\n });\n });\n var p2 = new Promise(function (res) {\n _this6.originalImage.animate('scaleY', targetAbs, {\n duration: _this6.options.animationDuration,\n onChange: _this6.canvas.renderAll.bind(_this6.canvas),\n onComplete: res\n });\n });\n return Promise.all([p1, p2]).then(function () {\n _this6.originalImage.set({\n scaleX: targetAbs,\n scaleY: targetAbs\n });\n _this6.originalImage.setCoords();\n if (_this6.options.expandCanvasToImage) _this6._updateCanvasSizeToImageBounds();\n _this6._alignObjectBoundingBoxToCanvasTopLeft(_this6.originalImage);\n\n // Sync mask labels\n _this6.canvas.getObjects().forEach(function (o) {\n if (o.maskId) _this6._syncMaskLabel(o);\n });\n _this6.isAnimating = false;\n _this6._updateInputs();\n _this6._updateUI();\n _this6.saveState();\n }).catch(function () {\n _this6.isAnimating = false;\n _this6._updateUI();\n });\n }\n\n /** \n * Rotates the original image by a given number of degrees, with animation.\n * Returns a promise that resolves when the rotation animation is complete.\n * @param {number} degrees - The angle in degrees to rotate the image.\n * @returns {Promise<void>} Promise that resolves once the rotation animation finishes.\n * @public\n */\n }, {\n key: \"rotateImage\",\n value: function rotateImage(deg) {\n var _this7 = this;\n return this.animQueue.add(function () {\n return _this7._rotateImageImpl(deg);\n });\n }\n\n /** \n * Rotates the original image by a given number of degrees, with animation.\n * Returns a promise that resolves when the rotation animation is complete.\n * @param {number} degrees - The angle in degrees to rotate the image.\n * @returns {Promise<void>} Promise that resolves once the rotation animation finishes.\n * @private\n */\n }, {\n key: \"_rotateImageImpl\",\n value: function _rotateImageImpl(degrees) {\n var _this8 = this;\n if (!this.originalImage) return Promise.resolve();\n if (this.isAnimating) return Promise.resolve();\n if (isNaN(degrees)) return Promise.resolve();\n this.currentRotation = degrees;\n this.isAnimating = true;\n this._updateUI();\n var center = this.originalImage.getCenterPoint();\n this._setObjectOriginKeepingPosition(this.originalImage, 'center', 'center', center);\n var p = new Promise(function (res) {\n _this8.originalImage.animate('angle', degrees, {\n duration: _this8.options.animationDuration,\n onChange: _this8.canvas.renderAll.bind(_this8.canvas),\n onComplete: res\n });\n });\n return p.then(function () {\n _this8.originalImage.set('angle', degrees);\n _this8.originalImage.setCoords();\n if (_this8.options.expandCanvasToImage) _this8._updateCanvasSizeToImageBounds();\n _this8._alignObjectBoundingBoxToCanvasTopLeft(_this8.originalImage);\n var newTopLeft = _this8._getObjectTopLeftPoint(_this8.originalImage);\n _this8._setObjectOriginKeepingPosition(_this8.originalImage, 'left', 'top', newTopLeft);\n\n // Sync mask labels\n _this8.canvas.getObjects().forEach(function (o) {\n if (o.maskId) _this8._syncMaskLabel(o);\n });\n _this8.isAnimating = false;\n _this8._updateInputs();\n _this8._updateUI();\n _this8.saveState();\n }).catch(function () {\n _this8.isAnimating = false;\n _this8._updateUI();\n });\n }\n\n /**\n * Resets the image: scales to 1 and rotates to 0 degrees.\n * @returns {Promise<void>} Promise that resolves when reset is complete.\n */\n }, {\n key: \"reset\",\n value: function reset() {\n var _this9 = this;\n if (!this.originalImage) return Promise.resolve();\n return this.scaleImage(1).then(function () {\n return _this9.rotateImage(0);\n }).then(function () {\n _this9.saveState();\n }).catch(function (err) {\n console.error('reset() failed', err);\n });\n }\n\n /**\n * Restores a canvas state that was previously stored by saveState().\n * @param {string} jsonString - the JSON string returned by fabric.toJSON().\n */\n }, {\n key: \"loadFromState\",\n value: function loadFromState(jsonString) {\n var _this0 = this;\n if (!jsonString || !this.canvas) return;\n try {\n var json = typeof jsonString === 'string' ? JSON.parse(jsonString) : jsonString;\n this.canvas.loadFromJSON(json, function () {\n _this0._hideAllMaskLabels();\n var objs = _this0.canvas.getObjects();\n _this0.originalImage = objs.find(function (o) {\n return o.type === 'image' && !o.maskId;\n }) || null;\n _this0.originalImage.set({\n originX: 'left',\n originY: 'top',\n selectable: false,\n evented: false,\n hasControls: false,\n hoverCursor: 'default'\n });\n _this0.canvas.sendToBack(_this0.originalImage);\n var masks = objs.filter(function (o) {\n return o.maskId;\n });\n _this0.maskCounter = masks.reduce(function (max, m) {\n return Math.max(max, m.maskId);\n }, 0);\n _this0.canvas.renderAll();\n _this0._updateMaskList();\n _this0._updateUI();\n });\n } catch (e) {\n console.error('loadFromState() failed', e);\n }\n }\n\n /**\n * Saves the current state of the canvas to history, storing any mask/raster label information.\n */\n }, {\n key: \"saveState\",\n value: function saveState() {\n var _this1 = this;\n if (!this.canvas) return;\n var activeObj = this.canvas.getActiveObject();\n this._hideAllMaskLabels();\n try {\n // request JSON including the custom flag 'isCropRect' so we can filter it out\n var jsonObj = this.canvas.toJSON(['maskId', 'maskName', 'isCropRect']);\n if (Array.isArray(jsonObj.objects)) {\n // filter out crop-rect objects before stringifying\n jsonObj.objects = jsonObj.objects.filter(function (o) {\n return !o.isCropRect;\n });\n }\n var after = JSON.stringify(jsonObj);\n var before = this._lastSnapshot || after;\n var executedOnce = false;\n var cmd = new Command(function () {\n if (executedOnce) {\n _this1.loadFromState(after);\n }\n executedOnce = true;\n }, function () {\n _this1.loadFromState(before);\n });\n this.historyManager.execute(cmd);\n this._lastSnapshot = after;\n if (activeObj && activeObj.maskId) {\n this._showLabelForMask(activeObj);\n }\n this._updateUI();\n } catch (err) {\n console.warn('saveState: failed to save canvas snapshot', err);\n }\n }\n\n /**\n * Undo the last state change, if possible.\n */\n }, {\n key: \"undo\",\n value: function undo() {\n this.historyManager.undo();\n }\n\n /**\n * Redo the next state change, if possible.\n */\n }, {\n key: \"redo\",\n value: function redo() {\n this.historyManager.redo();\n }\n\n /** \n * Adds a rectangular mask to the canvas.\n * Mask placement and properties are determined by the provided config and instance options.\n * Canvas and list UI are updated accordingly.\n * @param {Object} [config={}] - Optional mask configuration overrides:\n * @param {string} [config.shape='rect'] - 'rect', 'circle', 'ellipse', 'polygon', ...\n * @param {Object|Array} [config.points] - Required for polygon: [{x, y}, ...] or [[x, y], ...]\n * @param {number|function} [config.width/height/rx/ry/radius] - Can be number or function(canvas, options) \n * @param {number|string|function} [config.left/top] - Absolute, %, or function\n * @param {number|string} [config.angle] - Rotation angle (degree)\n * @param {string} [config.color] - Fill color in CSS color format (default 'rgba(0,0,0,0.5)')\n * @param {number} [config.alpha] - Opacity, from 0 to 1 (default 0.5)\n * @param {boolean} [config.selectable=true]\n * @param {Object} [config.styles] - Custom styles (stroke, dashArray, etc)\n * @param {function} [config.onCreate] - Callback after mask created (receives Fabric object)\n * @param {function} [config.fabricGenerator] - (cfg) => new FabricObj\n * @returns {fabric.Rect|null} The created mask object, or null if canvas is not available.\n * @public\n */\n }, {\n key: \"addMask\",\n value: function addMask() {\n var _this10 = this;\n var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (!this.canvas) return null;\n var shapeType = config.shape || 'rect';\n // Default config\n var cfg = _objectSpread({\n shape: shapeType,\n width: this.options.defaultMaskWidth,\n height: this.options.defaultMaskHeight,\n color: 'rgba(0,0,0,0.5)',\n alpha: 0.5,\n gap: 5,\n left: undefined,\n top: undefined,\n angle: 0,\n selectable: true\n }, config);\n\n // Always start placement relative to canvas left/top.\n var firstOffset = 10;\n var left = firstOffset;\n var top = firstOffset;\n var resolveValue = function resolveValue(val, fallback) {\n if (typeof val === 'function') return val(_this10.canvas, _this10.options); // This context is this of addMask\n if (typeof val === 'string' && val.endsWith('%')) {\n var percent = parseFloat(val) / 100;\n return Math.floor((_this10.canvas ? _this10.canvas.getWidth() : 0) * percent);\n }\n return val != null ? val : fallback;\n };\n if (cfg.left === undefined && this._lastMask) {\n var _prev$top;\n var prev = this._lastMask;\n var prevRight = prev.left;\n if (prev.getScaledWidth) {\n prevRight += prev.getScaledWidth();\n } else if (prev.width) {\n var _prev$scaleX;\n prevRight += prev.width * ((_prev$scaleX = prev.scaleX) !== null && _prev$scaleX !== void 0 ? _prev$scaleX : 1);\n }\n left = Math.round(prevRight + cfg.gap);\n top = (_prev$top = prev.top) !== null && _prev$top !== void 0 ? _prev$top : firstOffset;\n } else {\n left = resolveValue(cfg.left, firstOffset);\n top = resolveValue(cfg.top, firstOffset);\n }\n cfg.width = resolveValue(cfg.width, this.options.defaultMaskWidth);\n cfg.height = resolveValue(cfg.height, this.options.defaultMaskHeight);\n\n // If expandCanvasToImage mode, ensure canvas large enough to hold mask initial placement\n if (this.options.expandCanvasToImage && shapeType === 'rect') {\n var requiredW = Math.ceil(left + cfg.width + 10);\n var requiredH = Math.ceil(top + cfg.height + 10);\n var minW = this.containerEl ? Math.floor(this.containerEl.clientWidth || 0) : 0;\n var minH = this.containerEl ? Math.floor(this.containerEl.clientHeight || 0) : 0;\n var newW = Math.max(this.canvas.getWidth(), minW, requiredW);\n var newH = Math.max(this.canvas.getHeight(), minH, requiredH);\n this._setCanvasSizeInt(newW, newH);\n }\n var mask;\n if (typeof cfg.fabricGenerator === 'function') {\n mask = cfg.fabricGenerator(cfg, this.canvas, this.options);\n } else {\n switch (shapeType) {\n case 'circle':\n mask = new fabric.Circle(_objectSpread({\n left: left,\n top: top,\n radius: resolveValue(cfg.radius, Math.min(cfg.width, cfg.height) / 2),\n fill: cfg.color,\n opacity: cfg.alpha,\n angle: cfg.angle\n }, cfg.styles));\n break;\n case 'ellipse':\n mask = new fabric.Ellipse(_objectSpread({\n left: left,\n top: top,\n rx: resolveValue(cfg.rx, cfg.width / 2),\n ry: resolveValue(cfg.ry, cfg.height / 2),\n fill: cfg.color,\n opacity: cfg.alpha,\n angle: cfg.angle\n }, cfg.styles));\n break;\n case 'polygon':\n var polyPoints = cfg.points || [];\n if (Array.isArray(polyPoints) && polyPoints.length && _typeof(polyPoints[0]) === 'object') {\n // Ensure numeric {x,y} objects for fabric.Polygon\n polyPoints = polyPoints.map(function (pt) {\n return {\n x: Number(pt.x),\n y: Number(pt.y)\n };\n });\n }\n mask = new fabric.Polygon(polyPoints, _objectSpread({\n left: left,\n top: top,\n fill: cfg.color,\n opacity: cfg.alpha,\n angle: cfg.angle\n }, cfg.styles));\n break;\n case 'rect':\n default:\n mask = new fabric.Rect(_objectSpread({\n left: left,\n top: top,\n width: resolveValue(cfg.width, this.options.defaultMaskWidth),\n height: resolveValue(cfg.height, this.options.defaultMaskHeight),\n fill: cfg.color,\n opacity: cfg.alpha,\n angle: cfg.angle,\n rx: cfg.rx,\n // Rounded Corners\n ry: cfg.ry\n }, cfg.styles));\n }\n }\n mask.selectable = cfg.selectable !== false;\n mask.hasControls = 'hasControls' in cfg ? cfg.hasControls : true;\n mask.lockRotation = !this.options.maskRotatable;\n mask.borderColor = cfg.borderColor || 'red';\n mask.cornerColor = cfg.cornerColor || 'black';\n mask.cornerSize = cfg.cornerSize || 8;\n mask.transparentCorners = 'transparentCorners' in cfg ? cfg.transparentCorners : false;\n mask.stroke = cfg.styles && cfg.styles.stroke || '#ccc';\n mask.strokeWidth = cfg.styles && cfg.styles.strokeWidth || 1;\n mask.strokeUniform = 'strokeUniform' in cfg ? cfg.strokeUniform : true;\n if (cfg.styles && cfg.styles.strokeDashArray) mask.strokeDashArray = cfg.styles.strokeDashArray;\n mask.originalAlpha = cfg.alpha;\n var normalStyle = {\n stroke: mask.stroke,\n strokeWidth: mask.strokeWidth,\n opacity: mask.originalAlpha\n };\n var hoverStyle = {\n stroke: '#ff5500',\n strokeWidth: 2,\n opacity: Math.min(mask.originalAlpha + 0.2, 1)\n };\n mask.on('mouseover', function () {\n mask.set(hoverStyle);\n mask.canvas.requestRenderAll();\n });\n mask.on('mouseout', function () {\n mask.set(normalStyle);\n mask.canvas.requestRenderAll();\n });\n\n // Remember initial for next one\n this._lastMaskInitialLeft = left;\n this._lastMaskInitialTop = top;\n this._lastMaskInitialWidth = resolveValue(cfg.width, this.options.defaultMaskWidth);\n mask.maskId = ++this.maskCounter;\n mask.maskName = \"\".concat(this.options.maskName).concat(mask.maskId);\n this._lastMask = mask;\n this.canvas.add(mask);\n this.canvas.bringToFront(mask);\n if (cfg.selectable) this.canvas.setActiveObject(mask);\n this._onSelectionChanged([mask]);\n this._updateMaskList();\n this._updateUI();\n this.canvas.renderAll();\n this.saveState();\n if (typeof cfg.onCreate === 'function') cfg.onCreate(mask, this.canvas);\n return mask;\n }\n\n /**\n * Removes the currently selected mask from the canvas, if any.\n * The associated label is also removed. UI and mask list are updated.\n */\n }, {\n key: \"removeSelectedMask\",\n value: function removeSelectedMask() {\n var active = this.canvas.getActiveObject();\n if (!active || !active.maskId) return;\n this._removeLabelForMask(active);\n this.canvas.remove(active);\n this.canvas.discardActiveObject();\n this._updateMaskList();\n this._updateUI();\n this.canvas.renderAll();\n this.saveState();\n }\n\n /**\n * Removes all masks from the canvas, including their labels.\n * UI and internal mask placement memory are reset.\n */\n }, {\n key: \"removeAllMasks\",\n value: function removeAllMasks() {\n var _this11 = this;\n var masks = this.canvas.getObjects().filter(function (o) {\n return o.maskId;\n });\n masks.forEach(function (m) {\n return _this11._removeLabelForMask(m);\n });\n masks.forEach(function (m) {\n return _this11.canvas.remove(m);\n });\n this.canvas.discardActiveObject();\n this._lastMaskInitialLeft = null;\n this._lastMaskInitialTop = null;\n this._lastMaskInitialWidth = null;\n this._updateMaskList();\n this._updateUI();\n this.canvas.renderAll();\n this.saveState();\n }\n\n /**\n * Removes the label associated with the specified mask object, if it exists.\n * \n * @param {fabric.Object} mask - The mask object whose label should be removed.\n * @private\n */\n }, {\n key: \"_removeLabelForMask\",\n value: function _removeLabelForMask(mask) {\n if (!mask || !this.canvas) return;\n if (mask.__label) {\n try {\n var objs = this.canvas.getObjects();\n if (objs.includes(mask.__label)) {\n this.canvas.remove(mask.__label);\n }\n } catch (e) {/* ignore */}\n try {\n delete mask.__label;\n } catch (e) {}\n }\n }\n\n /**\n * Creates and adds a custom label (fabric.Text or fabric.IText) for the mask.\n * The label is default bound to the top-left of the mask and managed as a non-interactive overlay.\n * \n * @param {fabric.Object} mask - The mask to create a label for.\n * @private\n */\n }, {\n key: \"_createLabelForMask\",\n value: function _createLabelForMask(mask) {\n if (!mask || !this.options.maskLabelOnSelect) return;\n this._removeLabelForMask(mask);\n var textObj = null;\n if (this.options.label && typeof this.options.label.create === 'function') {\n textObj = this.options.label.create(mask, fabric);\n }\n if (!textObj) {\n var txt = mask.maskName; // Default\n var textOptions = {\n left: 0,\n top: 0,\n fontSize: 12,\n fill: '#fff',\n backgroundColor: 'rgba(0,0,0,0.7)',\n selectable: false,\n evented: false,\n padding: 2,\n originX: 'left',\n originY: 'top'\n };\n if (this.options.label) {\n if (typeof this.options.label.getText === 'function') {\n txt = this.options.label.getText(mask, this.maskCounter);\n }\n // Merge external styles\n if (this.options.label.textOptions) {\n Object.assign(textOptions, this.options.label.textOptions);\n }\n }\n textObj = new fabric.Text(txt, textOptions);\n }\n textObj.maskLabel = true;\n mask.__label = textObj;\n this.canvas.add(textObj);\n this.canvas.bringToFront(textObj);\n this._syncMaskLabel(mask);\n }\n\n /**\n * Hides (removes) all mask labels from the canvas.\n * Internal label references on mask objects are also deleted.\n * @private\n */\n }, {\n key: \"_hideAllMaskLabels\",\n value: function _hideAllMaskLabels() {\n var _this12 = this;\n if (!this.canvas) return;\n var objs = this.canvas.getObjects();\n var labels = objs.filter(function (o) {\n return o.maskLabel;\n });\n labels.forEach(function (l) {\n try {\n if (objs.includes(l)) _this12.canvas.remove(l);\n } catch (e) {}\n });\n objs.forEach(function (o) {\n if (o.maskId && o.__label) {\n try {\n delete o.__label;\n } catch (e) {}\n }\n });\n }\n\n /**\n * Synchronizes the position, angle, and visibility of the mask's label so that it appears properly above the mask.\n * \n * @param {fabric.Object} mask - The mask whose label should be repositioned.\n * @private\n */\n }, {\n key: \"_syncMaskLabel\",\n value: function _syncMaskLabel(mask) {\n var _this$options$maskLab;\n if (!mask) return;\n if (!this.options.maskLabelOnSelect) return;\n if (!mask.__label) return;\n var coords = mask.getCoords ? mask.getCoords() : null;\n if (!coords || coords.length < 4) return;\n var tl = coords[0];\n var center = mask.getCenterPoint();\n var vx = center.x - tl.x;\n var vy = center.y - tl.y;\n var dist = Math.sqrt(vx * vx + vy * vy) || 1;\n var ux = vx / dist;\n var uy = vy / dist;\n var offset = Math.max(0, (_this$options$maskLab = this.options.maskLabelOffset) !== null && _this$options$maskLab !== void 0 ? _this$options$maskLab : 3);\n var px = tl.x + ux * offset;\n var py = tl.y + uy * offset;\n mask.__label.set({\n left: Math.round(px),\n top: Math.round(py),\n angle: mask.angle || 0,\n originX: 'left',\n originY: 'top',\n visible: true\n });\n mask.__label.setCoords();\n this.canvas.renderAll();\n }\n\n /**\n * Shows the label for the given mask, creating it if necessary and synchronizing its position.\n * \n * @param {fabric.Object} mask - The mask whose label should be shown.\n * @private\n */\n }, {\n key: \"_showLabelForMask\",\n value: function _showLabelForMask(mask) {\n if (!mask) return;\n if (!this.options.maskLabelOnSelect) return;\n if (!mask.__label) this._createLabelForMask(mask);\n mask.__label.visible = true;\n this._syncMaskLabel(mask);\n }\n\n /**\n * Handles changes to the selection of canvas objects (masks),\n * updates mask stroke and label display, and syncs mask list selection.\n *\n * @param {Array<Object>} selected - The currently selected objects (e.g. [mask] or []).\n * @private\n */\n }, {\n key: \"_onSelectionChanged\",\n value: function _onSelectionChanged(selected) {\n var _this13 = this;\n var selectedMask = (selected || []).find(function (o) {\n return o.maskId;\n });\n var masks = this.canvas.getObjects().filter(function (o) {\n return o.maskId;\n });\n masks.forEach(function (m) {\n if (m !== selectedMask) {\n if (m.__label) {\n try {\n _this13.canvas.remove(m.__label);\n } catch (e) {}\n delete m.__label;\n }\n m.set({\n stroke: '#ccc',\n strokeWidth: 1\n });\n } else {\n m.set({\n stroke: '#ff0000',\n strokeWidth: 1\n });\n }\n });\n if (selectedMask) this._showLabelForMask(selectedMask);\n this._updateMaskListSelection(selectedMask);\n this.canvas.renderAll();\n this._updateUI();\n }\n\n /**\n * Updates the mask list in the DOM to reflect the current masks on the canvas.\n * Each list entry becomes a clickable element for mask selection.\n * @private\n */\n }, {\n key: \"_updateMaskList\",\n value: function _updateMaskList() {\n var _this14 = this;\n var listEl = document.getElementById(this.elements.maskList);\n if (!listEl) return;\n listEl.innerHTML = '';\n var masks = this.canvas.getObjects().filter(function (o) {\n return o.maskId;\n });\n masks.forEach(function (mask) {\n var li = document.createElement('li');\n li.className = 'list-group-item mask-item';\n li.textContent = mask.maskName;\n li.onclick = function () {\n _this14.canvas.setActiveObject(mask);\n _this14._onSelectionChanged([mask]);\n };\n listEl.appendChild(li);\n });\n }\n\n /**\n * Updates the visual selection (CSS 'active') state for the mask list in the DOM.\n * \n * @param {Object|null} selectedMask - The currently selected mask, or null if none selected.\n * @private\n */\n }, {\n key: \"_updateMaskListSelection\",\n value: function _updateMaskListSelection(selectedMask) {\n var listEl = document.getElementById(this.elements.maskList);\n if (!listEl) return;\n var items = listEl.querySelectorAll('.mask-item');\n items.forEach(function (item) {\n var isSelected = !!selectedMask && item.textContent === selectedMask.maskName;\n item.classList.toggle('active', isSelected);\n });\n }\n\n /**\n * Merges current masks into the image: exports a masked/cropped image, removes all masks, and re-imports the merged image.\n * Will not run if no original image or no masks exist.\n * @async\n * @returns {Promise<void>} Resolves when merge and load are complete.\n */\n }, {\n key: \"merge\",\n value: (function () {\n var _merge = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {\n var masks, merged, _t;\n return _regenerator().w(function (_context2) {\n while (1) switch (_context2.p = _context2.n) {\n case 0:\n if (this.originalImage) {\n _context2.n = 1;\n break;\n }\n return _context2.a(2);\n case 1:\n masks = this.canvas.getObjects().filter(function (o) {\n return o.maskId;\n });\n if (masks.length) {\n _context2.n = 2;\n break;\n }\n return _context2.a(2);\n case 2:\n this.canvas.discardActiveObject();\n this.canvas.renderAll();\n _context2.p = 3;\n _context2.n = 4;\n return this.getImageBase64({\n exportImageArea: true,\n multiplier: this.options.exportMultiplier\n });\n case 4:\n merged = _context2.v;\n this.removeAllMasks();\n _context2.n = 5;\n return this.loadImage(merged);\n case 5:\n this.saveState();\n _context2.n = 7;\n break;\n case 6:\n _context2.p = 6;\n _t = _context2.v;\n console.error('merge error', _t);\n if (this.canvasEl) this.canvasEl.style.visibility = '';\n case 7:\n return _context2.a(2);\n }\n }, _callee2, this, [[3, 6]]);\n }));\n function merge() {\n return _merge.apply(this, arguments);\n }\n return merge;\n }()\n /**\n * Triggers a JPEG image download of the current canvas (image plus masks if configured).\n * The image area and multiplier are controlled by options.\n * @param {string} [fileName=this.options.defaultDownloadFileName] - Desired download file name.\n */\n )\n }, {\n key: \"downloadImage\",\n value: function downloadImage() {\n var fileName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.options.defaultDownloadFileName;\n if (!this.originalImage) return;\n var exportImageArea = this.options.exportImageAreaByDefault;\n this.getImageBase64({\n exportImageArea: exportImageArea,\n multiplier: this.options.exportMultiplier\n }).then(function (base64) {\n var link = document.createElement('a');\n link.download = fileName;\n link.href = base64;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n }).catch(function (err) {\n return console.error('download error', err);\n });\n }\n\n /**\n * Exports the image as a Base64-encoded JPEG.\n * Can export either the original, or the current view including masks (clipped/cropped).\n * Will restore masks' state after temporary modifications for export.\n * @async\n * @param {Object} [opts={}] - Export options.\n * @param {boolean} [opts.exportImageArea] - If true, exports only the image bounding area with masks cropped and blended.\n * @param {number} [opts.multiplier=1] - Scaling multiplier for output (resolution).\n * @returns {Promise<string>} Promise resolving to a JPEG image data URL.\n * @throws {Error} If there is no image loaded.\n */\n }, {\n key: \"getImageBase64\",\n value: (function () {\n var _getImageBase = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {\n var _this15 = this;\n var opts,\n exportImageArea,\n multiplier,\n imgEl,\n w,\n h,\n oc,\n ctx,\n masks,\n masksBackup,\n imgBr,\n sx,\n sy,\n sw,\n sh,\n finalBase64,\n _args3 = arguments;\n return _regenerator().w(function (_context3) {\n while (1) switch (_context3.n) {\n case 0:\n opts = _args3.length > 0 && _args3[0] !== undefined ? _args3[0] : {};\n if (this.originalImage) {\n _context3.n = 1;\n break;\n }\n throw new Error('No image loaded');\n case 1:\n exportImageArea = typeof opts.exportImageArea === 'boolean' ? opts.exportImageArea : this.options.exportImageAreaByDefault;\n multiplier = opts.multiplier || this.options.exportMultiplier || 1;\n if (exportImageArea) {\n _context3.n = 3;\n break;\n }\n // Export original image pixels\n imgEl = this.originalImage.getElement ? this.originalImage.getElement() : this.originalImage._element || null;\n if (imgEl) {\n _context3.n = 2;\n break;\n }\n return _context3.a(2, this.canvas.toDataURL({\n format: 'jpeg',\n quality: this.options.downsampleQuality,\n multiplier: multiplier\n }));\n case 2:\n w = this.originalImage.width;\n h = this.originalImage.height;\n oc = document.createElement('canvas');\n oc.width = w;\n oc.height = h;\n ctx = oc.getContext('2d');\n ctx.drawImage(imgEl, 0, 0, w, h);\n return _context3.a(2, oc.toDataURL('image/jpeg', this.options.downsampleQuality));\n case 3:\n // Export current scaled image area (masks clipped)\n masks = this.canvas.getObjects().filter(function (o) {\n return o.maskId;\n });\n masksBackup = masks.map(function (m) {\n return {\n obj: m,\n opacity: m.opacity,\n fill: m.fill,\n strokeWidth: m.strokeWidth,\n stroke: m.stroke,\n selectable: m.selectable,\n lockRotation: m.lockRotation\n };\n }); // Remove labels, deselect\n masks.forEach(function (m) {\n return _this15._removeLabelForMask(m);\n });\n this.canvas.discardActiveObject();\n this.canvas.renderAll();\n\n // Set masks to opaque black no border\n masks.forEach(function (m) {\n m.set({\n opacity: 1,\n fill: '#000000',\n strokeWidth: 0,\n stroke: null,\n selectable: false\n });\n m.setCoords();\n });\n this.canvas.renderAll();\n\n // Compute integer bounding box for image\n this.originalImage.setCoords();\n imgBr = this.originalImage.getBoundingRect(true, true);\n sx = Math.max(0, Math.round(imgBr.left));\n sy = Math.max(0, Math.round(imgBr.top));\n sw = Math.max(1, Math.round(imgBr.width));\n sh = Math.max(1, Math.round(imgBr.height)); // Crop precisely in offscreen canvas\n _context3.n = 4;\n return new Promise(function (resolve, reject) {\n try {\n var fullDataUrl = _this15.canvas.toDataURL({\n format: 'jpeg',\n quality: _this15.options.downsampleQuality,\n multiplier: multiplier\n });\n var img = new Image();\n img.onload = function () {\n try {\n var sxM = Math.round(sx * multiplier);\n var syM = Math.round(sy * multiplier);\n var swM = Math.round(sw * multiplier);\n var shM = Math.round(sh * multiplier);\n var _oc = document.createElement('canvas');\n _oc.width = swM;\n _oc.height = shM;\n var _ctx = _oc.getContext('2d');\n _ctx.drawImage(img, sxM, syM, swM, shM, 0, 0, swM, shM);\n var out = _oc.toDataURL('image/jpeg', _this15.options.downsampleQuality);\n resolve(out);\n } catch (e) {\n reject(e);\n }\n };\n img.onerror = reject;\n img.src = fullDataUrl;\n } catch (e) {\n reject(e);\n }\n });\n case 4:\n finalBase64 = _context3.v;\n // Restore masks\n masksBackup.forEach(function (b) {\n try {\n b.obj.set({\n opacity: b.opacity,\n fill: b.fill,\n strokeWidth: b.strokeWidth,\n stroke: b.stroke,\n selectable: b.selectable,\n lockRotation: b.lockRotation\n });\n b.obj.setCoords();\n } catch (e) {}\n });\n this.canvas.renderAll();\n return _context3.a(2, finalBase64);\n }\n }, _callee3, this);\n }));\n function getImageBase64() {\n return _getImageBase.apply(this, arguments);\n }\n return getImageBase64;\n }()\n /**\n * Exports the current canvas (with or without masks) as a File object.\n * Allows you to choose whether to merge masks and specify file type (jpeg/png/webp).\n * \n * @async\n * @param {Object} [opts={}] - Export options.\n * @param {boolean} [opts.mergeMask=true] - If true, export image area with masks merged; if false, export the plain image without masks.\n * @param {string} [opts.fileType='jpeg'] - Output file type ('jpeg' | 'png' | 'webp'). Defaults to 'jpeg' on invalid input.\n * @param {number} [opts.quality=0.92] - Image quality for lossy types (0-1, default based on options.downsampleQuality).\n * @param {number} [opts.multiplier=1] - Output resolution multiplier.\n * @param {string} [opts.fileName] - Optional file name (only used for download).\n * @returns {Promise<File>} Resolves with the exported image as a File object.\n * \n * @example\n * const file = await this.exportImageFile({ mergeMask: false, fileType: 'png' });\n */\n )\n }, {\n key: \"exportImageFile\",\n value: (function () {\n var _exportImageFile = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {\n var _this$options$downsam, _this$options$exportM, _this$options$default;\n var opts,\n _opts$mergeMask,\n mergeMask,\n _opts$fileType,\n fileType,\n _opts$quality,\n quality,\n _opts$multiplier,\n multiplier,\n _opts$fileName,\n fileName,\n typeMapping,\n safeFileType,\n base64,\n imageDataUrl,\n bstr,\n mime,\n n,\n u8arr,\n file,\n _args4 = arguments;\n return _regenerator().w(function (_context4) {\n while (1) switch (_context4.n) {\n case 0:\n opts = _args4.length > 0 && _args4[0] !== undefined ? _args4[0] : {};\n if (this.originalImage) {\n _context4.n = 1;\n break;\n }\n throw new Error('No image loaded');\n case 1:\n _opts$mergeMask = opts.mergeMask, mergeMask = _opts$mergeMask === void 0 ? true : _opts$mergeMask, _opts$fileType = opts.fileType, fileType = _opts$fileType === void 0 ? 'jpeg' : _opts$fileType, _opts$quality = opts.quality, quality = _opts$quality === void 0 ? (_this$options$downsam = this.options.downsampleQuality) !== null && _this$options$downsam !== void 0 ? _this$options$downsam : 0.92 : _opts$quality, _opts$multiplier = opts.multiplier, multiplier = _opts$multiplier === void 0 ? (_this$options$exportM = this.options.exportMultiplier) !== null && _this$options$exportM !== void 0 ? _this$options$exportM : 1 : _opts$multiplier, _opts$fileName = opts.fileName, fileName = _opts$fileName === void 0 ? (_this$options$default = this.options.defaultDownloadFileName) !== null && _this$options$default !== void 0 ? _this$options$default : 'exported_image.jpg' : _opts$fileName;\n typeMapping = {\n 'jpeg': 'jpeg',\n 'jpg': 'jpeg',\n 'image/jpeg': 'jpeg',\n 'png': 'png',\n 'image/png': 'png',\n 'webp': 'webp',\n 'image/webp': 'webp'\n };\n safeFileType = typeMapping[String(fileType).toLowerCase()] || 'jpeg'; // Get Base64\n if (!mergeMask) {\n _context4.n = 3;\n break;\n }\n _context4.n = 2;\n return this.getImageBase64({\n exportImageArea: true,\n multiplier: multiplier\n });\n case 2:\n base64 = _context4.v;\n _context4.n = 5;\n break;\n case 3:\n _context4.n = 4;\n return this.getImageBase64({\n exportImageArea: false,\n multiplier: multiplier\n });\n case 4:\n base64 = _context4.v;\n case 5:\n // Convert to the required image format\n imageDataUrl = base64;\n if (imageDataUrl.startsWith(\"data:image/\".concat(safeFileType))) {\n _context4.n = 7;\n break;\n }\n _context4.n = 6;\n return new Promise(function (resolve, reject) {\n var img = new window.Image();\n img.crossOrigin = \"Anonymous\";\n img.onload = function () {\n try {\n var oc = document.createElement('canvas');\n oc.width = img.width;\n oc.height = img.height;\n var ctx = oc.getContext('2d');\n ctx.drawImage(img, 0, 0);\n var durl = oc.toDataURL(\"image/\".concat(safeFileType), quality);\n resolve(durl);\n } catch (e) {\n reject(e);\n }\n };\n img.onerror = reject;\n img.src = base64;\n });\n case 6:\n imageDataUrl = _context4.v;\n case 7:\n // Convert DataURL to Blob and then to File\n bstr = atob(imageDataUrl.split(',')[1]);\n mime = \"image/\".concat(safeFileType);\n n = bstr.length;\n u8arr = new Uint8Array(n);\n while (n--) {\n u8arr[n] = bstr.charCodeAt(n);\n }\n file = new File([u8arr], fileName, {\n type: mime\n });\n return _context4.a(2, file);\n }\n }, _callee4, this);\n }));\n function exportImageFile() {\n return _exportImageFile.apply(this, arguments);\n }\n return exportImageFile;\n }()\n /**\n * Enter crop mode: create a resizable/movable selection rect on top of the image.\n * @public\n */\n )\n }, {\n key: \"enterCropMode\",\n value: function enterCropMode() {\n var _this16 = this;\n if (!this.canvas || !this.originalImage || this._cropMode) return;\n if (!this.isImageLoaded()) return;\n this._cropMode = true;\n\n // Disable canvas group selection to avoid accidental group selection while cropping\n this._prevSelectionSetting = this.canvas.selection;\n this.canvas.selection = false;\n\n // Make sure no active object\n this.canvas.discardActiveObject();\n\n // Create initial crop rect centered on the image bounding box\n this.originalImage.setCoords();\n var imgBr = this.originalImage.getBoundingRect(true, true);\n // Provide small inset so user can see a margin\n var padding = this.options.crop && this.options.crop.padding ? this.options.crop.padding : 10;\n var left = Math.max(0, Math.floor(imgBr.left + padding));\n var top = Math.max(0, Math.floor(imgBr.top + padding));\n var width = Math.min(this.options.crop.minWidth || 50, Math.floor(imgBr.width - padding * 2));\n var height = Math.min(this.options.crop.minHeight || 50, Math.floor(imgBr.height - padding * 2));\n\n // Visual style: translucent fill + dashed stroke\n var cropRect = new fabric.Rect({\n left: left,\n top: top,\n width: width,\n height: height,\n fill: 'rgba(0,0,0,0.12)',\n stroke: '#00aaff',\n strokeDashArray: [6, 4],\n strokeWidth: 1,\n strokeUniform: true,\n selectable: true,\n hasRotatingPoint: !!(this.options.crop && this.options.crop.allowRotationOfCropRect),\n lockRotation: !(this.options.crop && this.options.crop.allowRotationOfCropRect),\n cornerSize: 8,\n objectCaching: false,\n originX: 'left',\n originY: 'top'\n });\n\n // Ensure the crop rect is above everything\n this.canvas.add(cropRect);\n cropRect.isCropRect = true;\n this.canvas.bringToFront(cropRect);\n this.canvas.setActiveObject(cropRect);\n\n // Keep reference\n this._cropRect = cropRect;\n\n // While in crop mode: we want only the cropRect to be interactive\n // but still allow moving/scaling it. To be safe, set other objects evented=false temporarily.\n this._cropPrevEvented = [];\n this.canvas.getObjects().forEach(function (o) {\n if (o !== cropRect) {\n _this16._cropPrevEvented.push({\n obj: o,\n evented: o.evented,\n selectable: o.selectable\n });\n try {\n o.evented = false;\n o.selectable = false;\n } catch (e) {/* ignore */}\n }\n });\n\n // When the crop rect changes, re-render\n var onModified = function onModified() {\n try {\n cropRect.setCoords();\n _this16.canvas.requestRenderAll();\n } catch (e) {}\n };\n cropRect.on('modified', onModified);\n cropRect.on('moving', onModified);\n cropRect.on('scaling', onModified);\n\n // Keep handlers to remove later\n this._cropHandlers.push({\n target: cropRect,\n handlers: [{\n evt: 'modified',\n fn: onModified\n }, {\n evt: 'moving',\n fn: onModified\n }, {\n evt: 'scaling',\n fn: onModified\n }]\n });\n this._updateUI();\n this.canvas.renderAll();\n }\n\n /**\n * Cancel crop mode and remove the temporary selection rect.\n * @public\n */\n }, {\n key: \"cancelCrop\",\n value: function cancelCrop() {\n if (!this.canvas || !this._cropMode) return;\n // Remove handlers if any and remove object\n if (this._cropRect) {\n try {\n if (this._cropHandlers && this._cropHandlers.length) {\n this._cropHandlers.forEach(function (h) {\n h.handlers.forEach(function (rec) {\n return h.target.off(rec.evt, rec.fn);\n });\n });\n }\n } catch (e) {/* ignore */}\n try {\n this.canvas.remove(this._cropRect);\n } catch (e) {}\n this._cropRect = null;\n }\n // restore evented/selectable flags\n if (Array.isArray(this._cropPrevEvented)) {\n this._cropPrevEvented.forEach(function (i) {\n try {\n i.obj.evented = i.evented;\n i.obj.selectable = i.selectable;\n } catch (e) {}\n });\n }\n this._cropPrevEvented = null;\n this._cropHandlers = [];\n this._cropMode = false;\n // restore selection setting\n this.canvas.selection = !!this._prevSelectionSetting;\n this._prevSelectionSetting = undefined;\n this.canvas.discardActiveObject();\n this._updateUI();\n this.canvas.renderAll();\n }\n\n /**\n * Apply the current crop rectangle.\n * remove all masks and export canvas snapshot and crop via offscreen canvas\n * @public\n */\n }, {\n key: \"applyCrop\",\n value: (function () {\n var _applyCrop = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {\n var _this17 = this;\n var rectBounds, sx, sy, sw, sh, beforeJson, jsonObj, masks, croppedBase64, fullDataUrl, afterJson, jsonObj2, _self, cmd, _t2, _t3;\n return _regenerator().w(function (_context5) {\n while (1) switch (_context5.p = _context5.n) {\n case 0:\n if (!(!this.canvas || !this._cropMode || !this._cropRect)) {\n _context5.n = 1;\n break;\n }\n return _context5.a(2);\n case 1:\n // Ensure crop rect coords are fresh\n this._cropRect.setCoords();\n rectBounds = this._cropRect.getBoundingRect(true, true); // Compute integer crop region clamped to canvas\n sx = Math.max(0, Math.round(rectBounds.left));\n sy = Math.max(0, Math.round(rectBounds.top));\n sw = Math.max(1, Math.round(Math.min(rectBounds.width, this.canvas.getWidth() - sx)));\n sh = Math.max(1, Math.round(Math.min(rectBounds.height, this.canvas.getHeight() - sy))); // Include isCropRect in toJSON whitelist so we can detect and filter them out.\n beforeJson = null;\n try {\n jsonObj = this.canvas.toJSON(['maskId', 'maskName', 'isCropRect']);\n if (Array.isArray(jsonObj.objects)) {\n jsonObj.objects = jsonObj.objects.filter(function (o) {\n return !o.isCropRect;\n });\n }\n beforeJson = JSON.stringify(jsonObj);\n } catch (e) {\n console.warn('applyCrop: could not serialize before state', e);\n beforeJson = null;\n }\n\n // Remove ALL un-merged masks so they won't be baked into exported pixels\n try {\n masks = this.canvas.getObjects().filter(function (o) {\n return o.maskId;\n });\n if (masks && masks.length) {\n masks.forEach(function (m) {\n try {\n _this17._removeLabelForMask(m);\n _this17.canvas.remove(m);\n } catch (err) {\n console.warn('applyCrop: failed to remove mask', err);\n }\n });\n this.canvas.discardActiveObject();\n this.canvas.renderAll();\n }\n } catch (e) {\n console.warn('applyCrop: error while removing masks', e);\n }\n try {\n if (this._cropRect) {\n try {\n if (this._cropHandlers && this._cropHandlers.length) {\n this._cropHandlers.forEach(function (h) {\n h.handlers.forEach(function (rec) {\n return h.target.off(rec.evt, rec.fn);\n });\n });\n }\n } catch (e) {/* ignore */}\n try {\n this.canvas.remove(this._cropRect);\n } catch (e) {/* ignore */}\n this._cropRect = null;\n }\n } catch (e) {/* ignore */}\n\n // End crop mode\n this._cropMode = false;\n this.canvas.selection = !!this._prevSelectionSetting;\n this._prevSelectionSetting = undefined;\n\n // Export full canvas and crop on offscreen canvas\n _context5.p = 2;\n fullDataUrl = this.canvas.toDataURL({\n format: 'jpeg',\n quality: this.options.downsampleQuality || 0.92,\n multiplier: 1\n });\n _context5.n = 3;\n return new Promise(function (resolve, reject) {\n var img = new Image();\n img.onload = function () {\n try {\n var oc = document.createElement('canvas');\n oc.width = sw;\n oc.height = sh;\n var ctx = oc.getContext('2d');\n ctx.drawImage(img, sx, sy, sw, sh, 0, 0, sw, sh);\n var out = oc.toDataURL('image/jpeg', _this17.options.downsampleQuality || 0.92);\n resolve(out);\n } catch (err) {\n reject(err);\n }\n };\n img.onerror = function (e) {\n return reject(e);\n };\n img.src = fullDataUrl;\n });\n case 3:\n croppedBase64 = _context5.v;\n _context5.n = 5;\n break;\n case 4:\n _context5.p = 4;\n _t2 = _context5.v;\n console.error('applyCrop: failed to create cropped image', _t2);\n this._updateUI();\n return _context5.a(2);\n case 5:\n _context5.p = 5;\n _context5.n = 6;\n return this.loadImage(croppedBase64);\n case 6:\n _context5.n = 8;\n break;\n case 7:\n _context5.p = 7;\n _t3 = _context5.v;\n console.error('applyCrop: loadImage(croppedBase64) failed', _t3);\n this._updateUI();\n return _context5.a(2);\n case 8:\n // Create \"after\" snapshot (also exclude crop rect if any) and push history command\n afterJson = null;\n try {\n jsonObj2 = this.canvas.toJSON(['maskId', 'maskName', 'isCropRect']);\n if (Array.isArray(jsonObj2.objects)) {\n jsonObj2.objects = jsonObj2.objects.filter(function (o) {\n return !o.isCropRect;\n });\n }\n afterJson = JSON.stringify(jsonObj2);\n } catch (e) {\n console.warn('applyCrop: failed to serialize after state', e);\n afterJson = null;\n }\n try {\n _self = this;\n cmd = new Command(function () {\n if (afterJson) _self.loadFromState(afterJson);\n }, function () {\n if (beforeJson) _self.loadFromState(beforeJson);\n });\n if (!this.historyManager) this.historyManager = new HistoryManager(this.maxHistorySize || 50);\n\n // trim future redo history\n if (this.historyManager.currentIndex < this.historyManager.history.length - 1) {\n this.historyManager.history = this.historyManager.history.slice(0, this.historyManager.currentIndex + 1);\n }\n this.historyManager.history.push(cmd);\n if (this.historyManager.history.length > this.historyManager.maxSize) {\n this.historyManager.history.shift();\n } else {\n this.historyManager.currentIndex++;\n }\n } catch (e) {\n console.warn('applyCrop: failed to push history command', e);\n }\n\n // Final UI update\n this._updateUI();\n this.canvas.renderAll();\n case 9:\n return _context5.a(2);\n }\n }, _callee5, this, [[5, 7], [2, 4]]);\n }));\n function applyCrop() {\n return _applyCrop.apply(this, arguments);\n }\n return applyCrop;\n }()\n /* ---------- Misc / UI ---------- */\n /**\n * Updates the scale input field in the UI to reflect the current scale.\n * Sets the value (as percentage) if the element is present.\n * @private\n */\n )\n }, {\n key: \"_updateInputs\",\n value: function _updateInputs() {\n var scaleEl = document.getElementById(this.elements.scaleRate);\n if (scaleEl) scaleEl.value = Math.round(this.currentScale * 100);\n }\n\n /**\n * Updates the enabled/disabled state of various UI controls (buttons)\n * based on the current application state (image/mask presence, animation, etc).\n * @private\n */\n }, {\n key: \"_updateUI\",\n value: function _updateUI() {\n var _this$historyManager, _this$historyManager2;\n var hasImg = !!this.originalImage;\n var masks = hasImg ? this.canvas.getObjects().filter(function (o) {\n return o.maskId;\n }) : [];\n var hasMasks = masks.length > 0;\n var active = this.canvas.getActiveObject();\n var hasSelectedMask = active && active.maskId;\n var isDefault = this.currentScale === 1 && this.currentRotation === 0;\n var canUndo = (_this$historyManager = this.historyManager) === null || _this$historyManager === void 0 ? void 0 : _this$historyManager.canUndo();\n var canRedo = (_this$historyManager2 = this.historyManager) === null || _this$historyManager2 === void 0 ? void 0 : _this$historyManager2.canRedo();\n var inCrop = !!this._cropMode;\n if (inCrop) {\n // iterate all element keys and disable unless key is applyCropBtn or cancelCropBtn\n for (var _i = 0, _Object$keys = Object.keys(this.elements || {}); _i < _Object$keys.length; _i++) {\n var k = _Object$keys[_i];\n var el = document.getElementById(this.elements[k]);\n if (!el) continue;\n if (k === 'applyCropBtn' || k === 'cancelCropBtn') {\n el.disabled = false;\n } else {\n el.disabled = true;\n }\n }\n return;\n }\n this._setDisabled('zoomInBtn', !hasImg || this.isAnimating || this.currentScale >= this.options.maxScale);\n this._setDisabled('zoomOutBtn', !hasImg || this.isAnimating || this.currentScale <= this.options.minScale);\n this._setDisabled('rotateLeftBtn', !hasImg || this.isAnimating);\n this._setDisabled('rotateRightBtn', !hasImg || this.isAnimating);\n this._setDisabled('addMaskBtn', !hasImg || this.isAnimating);\n this._setDisabled('removeMaskBtn', !hasSelectedMask || this.isAnimating);\n this._setDisabled('removeAllMasksBtn', !hasMasks || this.isAnimating);\n this._setDisabled('mergeBtn', !hasImg || !hasMasks || this.isAnimating);\n this._setDisabled('downloadBtn', !hasImg || this.isAnimating);\n this._setDisabled('resetBtn', !hasImg || isDefault || this.isAnimating);\n this._setDisabled('undoBtn', !hasImg || this.isAnimating || !canUndo);\n this._setDisabled('redoBtn', !hasImg || this.isAnimating || !canRedo);\n this._setDisabled('cropBtn', !hasImg || this.isAnimating);\n this._setDisabled('applyCropBtn', true);\n this._setDisabled('cancelCropBtn', true);\n }\n\n /**\n * Enables or disables a specific UI element (typically a button) by its key.\n * \n * @param {string} key - Key of the element in this.elements (e.g. 'zoomInBtn').\n * @param {boolean} disabled - If true, disables the element; otherwise enables.\n * @private\n */\n }, {\n key: \"_setDisabled\",\n value: function _setDisabled(key, disabled) {\n var el = document.getElementById(this.elements[key]);\n if (el) el.disabled = !!disabled;\n }\n\n /**\n * Automatically display and hide placeholders and containers based on the current image content\n * @private\n */\n }, {\n key: \"_updatePlaceholderStatus\",\n value: function _updatePlaceholderStatus() {\n if (!this.options.showPlaceholder) return;\n this._setPlaceholderVisible(!this.originalImage);\n }\n\n /**\n * Controls the display/hiding of the Placeholder and Canvas container.\n * @param {boolean} show - true displays the placeholder, false displays the canvas container\n * @private\n */\n }, {\n key: \"_setPlaceholderVisible\",\n value: function _setPlaceholderVisible(show) {\n if (!this.placeholderEl) return;\n if (show) {\n this.placeholderEl.classList.remove('d-none');\n this.placeholderEl.classList.add('d-flex');\n this.containerEl.classList.add('d-none');\n } else {\n this.placeholderEl.classList.remove('d-flex');\n this.placeholderEl.classList.add('d-none');\n this.containerEl.classList.remove('d-none');\n }\n }\n\n /**\n * Cleans up and disposes of the canvas and related references.\n * Call this method to free memory and remove canvas listeners when the editor is no longer needed.\n * @public\n */\n }, {\n key: \"dispose\",\n value: function dispose() {\n var _this18 = this;\n // Remove bound DOM event listeners\n try {\n var _loop = function _loop() {\n var handlers = _this18._boundHandlers[key] || [];\n var el = document.getElementById(_this18.elements[key]);\n if (!el) return 1; // continue\n handlers.forEach(function (h) {\n try {\n el.removeEventListener(h.event, h.handler);\n } catch (e) {}\n });\n };\n for (var key in this._boundHandlers || {}) {\n if (_loop()) continue;\n }\n } catch (e) {}\n if (this._cropRect) {\n try {\n this.canvas.remove(this._cropRect);\n } catch (e) {}\n this._cropRect = null;\n }\n if (this.canvas) {\n try {\n this.canvas.dispose();\n } catch (e) {}\n this.canvas = null;\n this.canvasEl = null;\n this.isImageLoadedToCanvas = false;\n }\n this._boundHandlers = {};\n }\n }]);\n }();\n /**\n * A simple FIFO queue that guarantees animations are executed sequentially.\n * @class AnimationQueue\n */\n var AnimationQueue = /*#__PURE__*/function () {\n /**\n * Creates a new AnimationQueue.\n *\n * @constructor\n */\n function AnimationQueue() {\n _classCallCheck(this, AnimationQueue);\n /**\n * Internal queue holding animation descriptors.\n * @type {Array<{fn: Function, resolve: Function, reject: Function}>}\n */\n this.queue = [];\n /**\n * Flag indicating whether an animation is currently running.\n * @type {boolean}\n */\n this.running = false;\n }\n\n /**\n * Adds an animation function to the queue.\n *\n * @param {Function} animationFn A function that returns a Promise or any await-able.\n * @returns {Promise<*>} A Promise that resolves/rejects with the animation result.\n */\n return _createClass(AnimationQueue, [{\n key: \"add\",\n value: (function () {\n var _add = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(animationFn) {\n var _this19 = this;\n return _regenerator().w(function (_context6) {\n while (1) switch (_context6.n) {\n case 0:\n return _context6.a(2, new Promise(function (resolve, reject) {\n // Push the animation into the queue.\n _this19.queue.push({\n fn: animationFn,\n resolve: resolve,\n reject: reject\n });\n // Start processing if it's not already running.\n if (!_this19.running) {\n _this19.processQueue();\n }\n }));\n }\n }, _callee6);\n }));\n function add(_x2) {\n return _add.apply(this, arguments);\n }\n return add;\n }()\n /**\n * Internal helper that processes the animation queue sequentially until it is empty.\n *\n * @private\n * @returns {Promise<void>}\n */\n )\n }, {\n key: \"processQueue\",\n value: (function () {\n var _processQueue = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {\n var _this$queue$shift, fn, resolve, reject, result, _t4;\n return _regenerator().w(function (_context7) {\n while (1) switch (_context7.p = _context7.n) {\n case 0:\n if (!(this.queue.length === 0)) {\n _context7.n = 1;\n break;\n }\n this.running = false;\n return _context7.a(2);\n case 1:\n this.running = true;\n _this$queue$shift = this.queue.shift(), fn = _this$queue$shift.fn, resolve = _this$queue$shift.resolve, reject = _this$queue$shift.reject;\n _context7.p = 2;\n _context7.n = 3;\n return fn();\n case 3:\n result = _context7.v;\n resolve(result);\n _context7.n = 5;\n break;\n case 4:\n _context7.p = 4;\n _t4 = _context7.v;\n reject(_t4);\n case 5:\n this.processQueue();\n case 6:\n return _context7.a(2);\n }\n }, _callee7, this, [[2, 4]]);\n }));\n function processQueue() {\n return _processQueue.apply(this, arguments);\n }\n return processQueue;\n }())\n }]);\n }();\n /**\n * Command object encapsulating an executable action and its corresponding undo operation.\n * @class Command\n */\n var Command = /*#__PURE__*/_createClass(\n /**\n * @param {Function} execute The function that performs the action.\n * @param {Function} undo The function that reverts the action.\n */\n function Command(execute, undo) {\n _classCallCheck(this, Command);\n /**\n * Executes the command.\n * @type {Function}\n */\n this.execute = execute;\n /**\n * Undoes the command.\n * @type {Function}\n */\n this.undo = undo;\n });\n /**\n * Manages a history of Command objects enabling undo/redo functionality.\n * @class HistoryManager\n */\n var HistoryManager = /*#__PURE__*/function () {\n /**\n * @param {number} [maxSize=50] Maximum number of commands to keep in history.\n */\n function HistoryManager() {\n var maxSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50;\n _classCallCheck(this, HistoryManager);\n this.history = [];\n this.currentIndex = -1;\n this.maxSize = maxSize;\n }\n\n /**\n * Executes a new command and pushes it onto the history stack.\n * Truncates any \"future\" history when branching.\n *\n * @param {Command} command The command to execute.\n * @returns {void}\n */\n return _createClass(HistoryManager, [{\n key: \"execute\",\n value: function execute(command) {\n // Perform the command.\n command.execute();\n\n // Remove any commands that are ahead of the current index.\n if (this.currentIndex < this.history.length - 1) {\n this.history = this.history.slice(0, this.currentIndex + 1);\n }\n\n // Add the new command.\n this.history.push(command);\n\n // Maintain the max size of the buffer.\n if (this.history.length > this.maxSize) {\n this.history.shift(); // Remove the oldest command.\n } else {\n this.currentIndex++;\n }\n }\n\n /**\n * Checks whether an undo operation is possible.\n *\n * @returns {boolean} True if undo can be performed.\n */\n }, {\n key: \"canUndo\",\n value: function canUndo() {\n return this.currentIndex >= 0;\n }\n\n /**\n * Checks whether a redo operation is possible.\n *\n * @returns {boolean} True if redo can be performed.\n */\n }, {\n key: \"canRedo\",\n value: function canRedo() {\n return this.currentIndex < this.history.length - 1;\n }\n\n /**\n * Undoes the last executed command if possible.\n *\n * @returns {void}\n */\n }, {\n key: \"undo\",\n value: function undo() {\n if (this.currentIndex >= 0) {\n this.history[this.currentIndex].undo();\n this.currentIndex--;\n }\n }\n\n /**\n * Redoes the next command in history if possible.\n *\n * @returns {void}\n */\n }, {\n key: \"redo\",\n value: function redo() {\n if (this.currentIndex < this.history.length - 1) {\n this.currentIndex++;\n this.history[this.currentIndex].execute();\n }\n }\n }]);\n }();\n return ImageEditor;\n});"],
5
- "mappings": "8DAAA,IAAAA,GAAAC,EAAA,CAAAC,EAAAC,IAAA,UAASC,GAAe,CAAE,kKAAmK,IAAIC,EAAGC,EAAGC,EAAkB,OAAO,QAArB,WAA8B,OAAS,CAAC,EAAGC,EAAID,EAAE,UAAY,aAAcE,EAAIF,EAAE,aAAe,gBAAiB,SAASG,EAAEH,EAAGC,EAAGC,EAAGC,EAAG,CAAE,IAAIC,EAAIH,GAAKA,EAAE,qBAAqBI,EAAYJ,EAAII,EAAWC,EAAI,OAAO,OAAOF,EAAE,SAAS,EAAG,OAAOG,EAAoBD,EAAG,UAAW,SAAUN,EAAGC,EAAGC,EAAG,CAAE,IAAIC,EAAGC,EAAGE,EAAGE,EAAI,EAAG,EAAIN,GAAK,CAAC,EAAGO,EAAI,GAAIC,EAAI,CAAE,EAAG,EAAG,EAAG,EAAG,EAAGZ,EAAG,EAAGa,EAAG,EAAGA,EAAE,KAAKb,EAAG,CAAC,EAAG,EAAG,SAAWC,EAAGC,EAAG,CAAE,OAAOG,EAAIJ,EAAGK,EAAI,EAAGE,EAAIR,EAAGY,EAAE,EAAIV,EAAGY,CAAG,CAAE,EAAG,SAASD,EAAEX,EAAGC,EAAG,CAAE,IAAKG,EAAIJ,EAAGM,EAAIL,EAAGF,EAAI,EAAG,CAACU,GAAKD,GAAK,CAACN,GAAKH,EAAI,EAAE,OAAQA,IAAK,CAAE,IAAIG,EAAGC,EAAI,EAAEJ,CAAC,EAAGY,EAAID,EAAE,EAAGG,EAAIV,EAAE,CAAC,EAAGH,EAAI,GAAKE,EAAIW,IAAMZ,KAAOK,EAAIH,GAAGC,EAAID,EAAE,CAAC,GAAK,GAAKC,EAAI,EAAG,EAAE,EAAGD,EAAE,CAAC,EAAIA,EAAE,CAAC,EAAIL,GAAKK,EAAE,CAAC,GAAKQ,KAAOT,EAAIF,EAAI,GAAKW,EAAIR,EAAE,CAAC,IAAMC,EAAI,EAAGM,EAAE,EAAIT,EAAGS,EAAE,EAAIP,EAAE,CAAC,GAAKQ,EAAIE,IAAMX,EAAIF,EAAI,GAAKG,EAAE,CAAC,EAAIF,GAAKA,EAAIY,KAAOV,EAAE,CAAC,EAAIH,EAAGG,EAAE,CAAC,EAAIF,EAAGS,EAAE,EAAIG,EAAGT,EAAI,GAAK,CAAE,GAAIF,GAAKF,EAAI,EAAG,OAAOY,EAAG,MAAMH,EAAI,GAAIR,CAAG,CAAE,OAAO,SAAUC,EAAGY,EAAGD,EAAG,CAAE,GAAIL,EAAI,EAAG,MAAM,UAAU,8BAA8B,EAAG,IAAKC,GAAWK,IAAN,GAAWH,EAAEG,EAAGD,CAAC,EAAGT,EAAIU,EAAGR,EAAIO,GAAId,EAAIK,EAAI,EAAIN,EAAIQ,IAAM,CAACG,GAAI,CAAEN,IAAMC,EAAIA,EAAI,GAAKA,EAAI,IAAMM,EAAE,EAAI,IAAKC,EAAEP,EAAGE,CAAC,GAAKI,EAAE,EAAIJ,EAAII,EAAE,EAAIJ,GAAI,GAAI,CAAE,GAAIE,EAAI,EAAGL,EAAG,CAAE,GAAIC,IAAMF,EAAI,QAASH,EAAII,EAAED,CAAC,EAAG,CAAE,GAAI,EAAEH,EAAIA,EAAE,KAAKI,EAAGG,CAAC,GAAI,MAAM,UAAU,kCAAkC,EAAG,GAAI,CAACP,EAAE,KAAM,OAAOA,EAAGO,EAAIP,EAAE,MAAOK,EAAI,IAAMA,EAAI,EAAI,MAAaA,IAAN,IAAYL,EAAII,EAAE,SAAWJ,EAAE,KAAKI,CAAC,EAAGC,EAAI,IAAME,EAAI,UAAU,oCAAsCJ,EAAI,UAAU,EAAGE,EAAI,GAAID,EAAIL,CAAG,UAAYC,GAAKU,EAAIC,EAAE,EAAI,GAAKJ,EAAIN,EAAE,KAAKC,EAAGS,CAAC,KAAOE,EAAG,KAAO,OAASb,EAAG,CAAEI,EAAIL,EAAGM,EAAI,EAAGE,EAAIP,CAAG,QAAE,CAAUS,EAAI,CAAG,CAAE,CAAE,MAAO,CAAE,MAAOT,EAAG,KAAMU,CAAE,CAAG,CAAG,EAAET,EAAGE,EAAGC,CAAC,EAAG,EAAE,EAAGG,CAAG,CAAE,IAAIM,EAAI,CAAC,EAAG,SAASP,GAAY,CAAC,CAAE,SAASU,GAAoB,CAAC,CAAE,SAASC,GAA6B,CAAC,CAAEjB,EAAI,OAAO,eAAgB,IAAIK,EAAI,CAAC,EAAEH,CAAC,EAAIF,EAAEA,EAAE,CAAC,EAAEE,CAAC,EAAE,CAAC,CAAC,GAAKM,EAAoBR,EAAI,CAAC,EAAGE,EAAG,UAAY,CAAE,OAAO,IAAM,CAAC,EAAGF,GAAIO,EAAIU,EAA2B,UAAYX,EAAU,UAAY,OAAO,OAAOD,CAAC,EAAG,SAASI,EAAEV,EAAG,CAAE,OAAO,OAAO,eAAiB,OAAO,eAAeA,EAAGkB,CAA0B,GAAKlB,EAAE,UAAYkB,EAA4BT,EAAoBT,EAAGI,EAAG,mBAAmB,GAAIJ,EAAE,UAAY,OAAO,OAAOQ,CAAC,EAAGR,CAAG,CAAE,OAAOiB,EAAkB,UAAYC,EAA4BT,EAAoBD,EAAG,cAAeU,CAA0B,EAAGT,EAAoBS,EAA4B,cAAeD,CAAiB,EAAGA,EAAkB,YAAc,oBAAqBR,EAAoBS,EAA4Bd,EAAG,mBAAmB,EAAGK,EAAoBD,CAAC,EAAGC,EAAoBD,EAAGJ,EAAG,WAAW,EAAGK,EAAoBD,EAAGL,EAAG,UAAY,CAAE,OAAO,IAAM,CAAC,EAAGM,EAAoBD,EAAG,WAAY,UAAY,CAAE,MAAO,oBAAsB,CAAC,GAAIT,EAAe,UAAwB,CAAE,MAAO,CAAE,EAAGM,EAAG,EAAGK,CAAE,CAAG,GAAG,CAAG,CAC/4F,SAASD,EAAoBT,EAAGE,EAAGC,EAAGF,EAAG,CAAE,IAAII,EAAI,OAAO,eAAgB,GAAI,CAAEA,EAAE,CAAC,EAAG,GAAI,CAAC,CAAC,CAAG,MAAY,CAAEA,EAAI,CAAG,CAAEI,EAAsB,SAA4BT,EAAGE,EAAG,EAAGD,EAAG,CAAE,SAASG,EAAE,EAAGD,EAAG,CAAEM,EAAoBT,EAAG,EAAG,SAAUA,EAAG,CAAE,OAAO,KAAK,QAAQ,EAAGG,EAAGH,CAAC,CAAG,CAAC,CAAG,CAAEE,EAAIG,EAAIA,EAAEL,EAAGE,EAAG,CAAE,MAAO,EAAG,WAAY,CAACD,EAAG,aAAc,CAACA,EAAG,SAAU,CAACA,CAAE,CAAC,EAAID,EAAEE,CAAC,EAAI,GAAKE,EAAE,OAAQ,CAAC,EAAGA,EAAE,QAAS,CAAC,EAAGA,EAAE,SAAU,CAAC,EAAI,EAAGK,EAAoBT,EAAGE,EAAGC,EAAGF,CAAC,CAAG,CACpc,SAASkB,EAAmBhB,EAAGF,EAAGD,EAAGE,EAAGE,EAAGU,EAAGR,EAAG,CAAE,GAAI,CAAE,IAAID,EAAIF,EAAEW,CAAC,EAAER,CAAC,EAAGE,EAAIH,EAAE,KAAO,OAASF,EAAG,CAAE,OAAO,KAAKH,EAAEG,CAAC,CAAG,CAAEE,EAAE,KAAOJ,EAAEO,CAAC,EAAI,QAAQ,QAAQA,CAAC,EAAE,KAAKN,EAAGE,CAAC,CAAG,CACxK,SAASgB,EAAkBjB,EAAG,CAAE,OAAO,UAAY,CAAE,IAAIF,EAAI,KAAMD,EAAI,UAAW,OAAO,IAAI,QAAQ,SAAUE,EAAGE,EAAG,CAAE,IAAIU,EAAIX,EAAE,MAAMF,EAAGD,CAAC,EAAG,SAASqB,EAAM,EAAG,CAAEF,EAAmBL,EAAGZ,EAAGE,EAAGiB,EAAOC,EAAQ,OAAQ,CAAC,CAAG,CAAE,SAASA,EAAO,EAAG,CAAEH,EAAmBL,EAAGZ,EAAGE,EAAGiB,EAAOC,EAAQ,QAAS,CAAC,CAAG,CAAED,EAAM,MAAM,CAAG,CAAC,CAAG,CAAG,CAChU,SAASE,EAAQvB,EAAGE,EAAG,CAAE,IAAID,EAAI,OAAO,KAAKD,CAAC,EAAG,GAAI,OAAO,sBAAuB,CAAE,IAAII,EAAI,OAAO,sBAAsBJ,CAAC,EAAGE,IAAME,EAAIA,EAAE,OAAO,SAAUF,EAAG,CAAE,OAAO,OAAO,yBAAyBF,EAAGE,CAAC,EAAE,UAAY,CAAC,GAAID,EAAE,KAAK,MAAMA,EAAGG,CAAC,CAAG,CAAE,OAAOH,CAAG,CAC9P,SAASuB,EAAcxB,EAAG,CAAE,QAASE,EAAI,EAAGA,EAAI,UAAU,OAAQA,IAAK,CAAE,IAAID,EAAY,UAAUC,CAAC,GAAnB,KAAuB,UAAUA,CAAC,EAAI,CAAC,EAAGA,EAAI,EAAIqB,EAAQ,OAAOtB,CAAC,EAAG,EAAE,EAAE,QAAQ,SAAUC,EAAG,CAAEuB,GAAgBzB,EAAGE,EAAGD,EAAEC,CAAC,CAAC,CAAG,CAAC,EAAI,OAAO,0BAA4B,OAAO,iBAAiBF,EAAG,OAAO,0BAA0BC,CAAC,CAAC,EAAIsB,EAAQ,OAAOtB,CAAC,CAAC,EAAE,QAAQ,SAAUC,EAAG,CAAE,OAAO,eAAeF,EAAGE,EAAG,OAAO,yBAAyBD,EAAGC,CAAC,CAAC,CAAG,CAAC,CAAG,CAAE,OAAOF,CAAG,CACtb,SAASyB,GAAgBzB,EAAGE,EAAGD,EAAG,CAAE,OAAQC,EAAIwB,EAAexB,CAAC,KAAMF,EAAI,OAAO,eAAeA,EAAGE,EAAG,CAAE,MAAOD,EAAG,WAAY,GAAI,aAAc,GAAI,SAAU,EAAG,CAAC,EAAID,EAAEE,CAAC,EAAID,EAAGD,CAAG,CACnL,SAAS2B,EAAgBb,EAAGX,EAAG,CAAE,GAAI,EAAEW,aAAaX,GAAI,MAAM,IAAI,UAAU,mCAAmC,CAAG,CAClH,SAASyB,EAAkB5B,EAAGE,EAAG,CAAE,QAASD,EAAI,EAAGA,EAAIC,EAAE,OAAQD,IAAK,CAAE,IAAIG,EAAIF,EAAED,CAAC,EAAGG,EAAE,WAAaA,EAAE,YAAc,GAAIA,EAAE,aAAe,GAAI,UAAWA,IAAMA,EAAE,SAAW,IAAK,OAAO,eAAeJ,EAAG0B,EAAetB,EAAE,GAAG,EAAGA,CAAC,CAAG,CAAE,CACvO,SAASyB,EAAa7B,EAAGE,EAAGD,EAAG,CAAE,OAAOC,GAAK0B,EAAkB5B,EAAE,UAAWE,CAAC,EAAGD,GAAK2B,EAAkB5B,EAAGC,CAAC,EAAG,OAAO,eAAeD,EAAG,YAAa,CAAE,SAAU,EAAG,CAAC,EAAGA,CAAG,CAC1K,SAAS0B,EAAezB,EAAG,CAAE,IAAII,EAAIyB,GAAa7B,EAAG,QAAQ,EAAG,OAAmB8B,EAAQ1B,CAAC,GAArB,SAAyBA,EAAIA,EAAI,EAAI,CAC5G,SAASyB,GAAa7B,EAAGC,EAAG,CAAE,GAAgB6B,EAAQ9B,CAAC,GAArB,UAA0B,CAACA,EAAG,OAAOA,EAAG,IAAID,EAAIC,EAAE,OAAO,WAAW,EAAG,GAAeD,IAAX,OAAc,CAAE,IAAIK,EAAIL,EAAE,KAAKC,EAAGC,GAAK,SAAS,EAAG,GAAgB6B,EAAQ1B,CAAC,GAArB,SAAwB,OAAOA,EAAG,MAAM,IAAI,UAAU,8CAA8C,CAAG,CAAE,OAAqBH,IAAb,SAAiB,OAAS,QAAQD,CAAC,CAAG,CAC3T,SAAS8B,EAAQ3B,EAAG,CAAE,0BAA2B,OAAO2B,EAAwB,OAAO,QAArB,YAA2C,OAAO,OAAO,UAA1B,SAAqC,SAAU3B,EAAG,CAAE,OAAO,OAAOA,CAAG,EAAI,SAAUA,EAAG,CAAE,OAAOA,GAAmB,OAAO,QAArB,YAA+BA,EAAE,cAAgB,QAAUA,IAAM,OAAO,UAAY,SAAW,OAAOA,CAAG,EAAG2B,EAAQ3B,CAAC,CAAG,CAC7T;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAcC,SAAU4B,EAAMC,EAAS,CACpB,OAAO,QAAW,YAAc,OAAO,IAEzC,OAAO,CAAC,EAAGA,CAAO,GACR,OAAOnC,EAAW,IAAc,YAAciC,EAAQjC,CAAM,KAAO,UAAYA,EAAO,QAEhGA,EAAO,QAAUmC,EAAQ,EAGzBD,EAAK,YAAcC,EAAQ,CAE/B,GAAG,OAAO,KAAS,IAAc,KAAOpC,EAAM,UAAY,CACxD,aAkDA,IAAIqC,EAA2B,UAAY,CACzC,SAASA,GAAc,CACrB,IAAIC,EAAU,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAI,CAAC,EACnFR,EAAgB,KAAMO,CAAW,EAEjC,KAAK,cAAgB,OAAO,OAAW,IAClC,KAAK,eACR,QAAQ,MAAM,0FAA0F,EAG1G,KAAK,QAAUV,EAAc,CAC3B,YAAa,IACb,aAAc,IACd,gBAAiB,cACjB,kBAAmB,IACnB,SAAU,GACV,SAAU,EACV,UAAW,IACX,aAAc,GACd,oBAAqB,GACrB,iBAAkB,GAClB,mBAAoB,GACpB,iBAAkB,GAClB,mBAAoB,IACpB,oBAAqB,IACrB,kBAAmB,IACnB,iBAAkB,EAClB,yBAA0B,GAC1B,iBAAkB,GAClB,kBAAmB,GACnB,cAAe,GACf,kBAAmB,GACnB,gBAAiB,EACjB,SAAU,OACV,eAAgB,GAChB,gBAAiB,GACjB,mBAAoB,KAGpB,wBAAyB,kBAC3B,EAAGW,CAAO,EACV,KAAK,QAAQ,MAAQ,CACnB,QAAS,SAAiBC,EAAMC,EAAW,CACzC,OAAOD,EAAK,QACd,EACA,YAAa,CACX,SAAU,GACV,KAAM,OACN,gBAAiB,kBACjB,QAAS,EACT,WAAY,YACZ,WAAY,OACZ,WAAY,GACZ,QAAS,GACT,QAAS,OACT,QAAS,KACX,CACF,EACA,KAAK,QAAQ,KAAO,CAClB,SAAU,IACV,UAAW,IACX,QAAS,GACT,oBAAqB,GACrB,uBAAwB,GACxB,wBAAyB,EAC3B,EAGA,KAAK,OAAS,KACd,KAAK,SAAW,KAChB,KAAK,YAAc,KACnB,KAAK,cAAgB,KACrB,KAAK,cAAgB,KACrB,KAAK,eAAiB,EACtB,KAAK,aAAe,EACpB,KAAK,gBAAkB,EACvB,KAAK,YAAc,EACnB,KAAK,YAAc,GACnB,KAAK,SAAW,CAAC,EACjB,KAAK,sBAAwB,GAC7B,KAAK,eAAiB,GACtB,KAAK,eAAiB,CAAC,EACvB,KAAK,qBAAuB,KAC5B,KAAK,oBAAsB,KAC3B,KAAK,sBAAwB,KAC7B,KAAK,UAAY,GACjB,KAAK,UAAY,KACjB,KAAK,cAAgB,CAAC,EACtB,KAAK,cAAgB,OAAOD,EAAQ,eAAkB,WAAaA,EAAQ,cAAgB,KAC3F,KAAK,UAAY,IAAIG,EACrB,KAAK,eAAiB,IAAIC,EAAe,KAAK,cAAc,CAC9D,CAsBA,OAAOV,EAAaK,EAAa,CAAC,CAChC,IAAK,OACL,MAAO,UAAgB,CACrB,IAAIM,EAAQ,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAI,CAAC,EACjF,GAAK,KAAK,cACV,KAAIC,EAAW,CACb,OAAQ,eACR,gBAAiB,KAEjB,eAAgB,iBAChB,UAAW,YACX,kBAAmB,oBACnB,mBAAoB,qBACpB,cAAe,gBACf,eAAgB,iBAChB,WAAY,aACZ,cAAe,gBACf,kBAAmB,oBACnB,SAAU,WACV,YAAa,cACb,SAAU,WACV,UAAW,YACX,WAAY,aACZ,SAAU,WACV,QAAS,UACT,QAAS,UACT,WAAY,aACZ,QAAS,UACT,aAAc,eACd,cAAe,eACjB,EACA,KAAK,SAAWjB,EAAcA,EAAc,CAAC,EAAGiB,CAAQ,EAAGD,CAAK,EAChE,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAGX,KAAK,QAAQ,mBACf,KAAK,UAAU,KAAK,QAAQ,kBAAkB,EAE9C,KAAK,yBAAyB,EAElC,CAMF,EAAG,CACD,IAAK,cACL,MAAO,UAAuB,CAC5B,IAAIE,EAAQ,KACRC,EAAW,SAAS,eAAe,KAAK,SAAS,MAAM,EAC3D,GAAI,CAACA,EAAU,MAAM,IAAI,MAAM,wBAA0B,KAAK,SAAS,MAAM,EAI7E,GAHA,KAAK,SAAWA,EAGZ,KAAK,SAAS,gBAAiB,CACjC,IAAIC,EAAK,SAAS,eAAe,KAAK,SAAS,eAAe,EAC9D,KAAK,YAAcA,GAAMD,EAAS,aACpC,MACE,KAAK,YAAcA,EAAS,cAE9B,KAAK,cAAgB,SAAS,eAAe,KAAK,SAAS,cAAc,GAAK,KAG9E,IAAIE,EAAW,KAAK,QAAQ,YACxBC,EAAW,KAAK,QAAQ,aAC5B,GAAI,KAAK,YAAa,CACpB,IAAIC,EAAK,KAAK,MAAM,KAAK,YAAY,WAAW,EAC5CC,EAAK,KAAK,MAAM,KAAK,YAAY,YAAY,EAC7CD,EAAK,GAAKC,EAAK,IACjBH,EAAWE,EACXD,EAAWE,EAEf,CACA,KAAK,OAAS,IAAI,OAAO,OAAOL,EAAU,CACxC,MAAOE,EACP,OAAQC,EACR,gBAAiB,KAAK,QAAQ,gBAC9B,UAAW,KAAK,QAAQ,eACxB,uBAAwB,EAC1B,CAAC,EAGD,KAAK,OAAO,GAAG,oBAAqB,SAAU9C,EAAG,CAC/C,OAAO0C,EAAM,oBAAoB1C,EAAE,QAAQ,CAC7C,CAAC,EACD,KAAK,OAAO,GAAG,oBAAqB,SAAUA,EAAG,CAC/C,OAAO0C,EAAM,oBAAoB1C,EAAE,QAAQ,CAC7C,CAAC,EACD,KAAK,OAAO,GAAG,oBAAqB,UAAY,CAC9C,OAAO0C,EAAM,oBAAoB,CAAC,CAAC,CACrC,CAAC,EACD,KAAK,OAAO,GAAG,gBAAiB,SAAU1C,EAAG,CACvCA,EAAE,QAAUA,EAAE,OAAO,QAAQ0C,EAAM,eAAe1C,EAAE,MAAM,CAChE,CAAC,EACD,KAAK,OAAO,GAAG,iBAAkB,SAAUA,EAAG,CACxCA,EAAE,QAAUA,EAAE,OAAO,QAAQ0C,EAAM,eAAe1C,EAAE,MAAM,CAChE,CAAC,EACD,KAAK,OAAO,GAAG,kBAAmB,SAAUA,EAAG,CACzCA,EAAE,QAAUA,EAAE,OAAO,QAAQ0C,EAAM,eAAe1C,EAAE,MAAM,CAChE,CAAC,EACD,KAAK,OAAO,GAAG,kBAAmB,SAAUA,EAAG,CACzCA,EAAE,QAAUA,EAAE,OAAO,QAAQ0C,EAAM,eAAe1C,EAAE,MAAM,CAChE,CAAC,EAGD,KAAK,SAAS,MAAM,QAAU,OAChC,CAMF,EAAG,CACD,IAAK,cACL,MAAO,UAAuB,CAC5B,IAAIiD,EAAS,KAEb,KAAK,cAAc,aAAc,QAAS,UAAY,CACpD,IAAIC,EACJ,OAAQA,EAAwB,SAAS,eAAeD,EAAO,SAAS,UAAU,KAAO,MAAQC,IAA0B,OAAS,OAASA,EAAsB,MAAM,CAC3K,CAAC,EAED,IAAIC,EAAU,SAAS,eAAe,KAAK,SAAS,UAAU,EAC1DA,GACFA,EAAQ,iBAAiB,SAAU,SAAUnD,EAAG,CAC9C,IAAIU,EAAIV,EAAE,OAAO,OAASA,EAAE,OAAO,MAAM,CAAC,EACtCU,GAAGuC,EAAO,eAAevC,CAAC,CAChC,CAAC,EAGH,KAAK,cAAc,YAAa,QAAS,UAAY,CACnD,OAAOuC,EAAO,WAAWA,EAAO,aAAeA,EAAO,QAAQ,SAAS,CACzE,CAAC,EACD,KAAK,cAAc,aAAc,QAAS,UAAY,CACpD,OAAOA,EAAO,WAAWA,EAAO,aAAeA,EAAO,QAAQ,SAAS,CACzE,CAAC,EACD,KAAK,cAAc,WAAY,QAAS,UAAY,CAClDA,EAAO,MAAM,CACf,CAAC,EAED,KAAK,cAAc,aAAc,QAAS,UAAY,CACpD,OAAOA,EAAO,QAAQ,CACxB,CAAC,EACD,KAAK,cAAc,gBAAiB,QAAS,UAAY,CACvD,OAAOA,EAAO,mBAAmB,CACnC,CAAC,EACD,KAAK,cAAc,oBAAqB,QAAS,UAAY,CAC3D,OAAOA,EAAO,eAAe,CAC/B,CAAC,EAED,KAAK,cAAc,WAAY,QAAS,UAAY,CAClD,OAAOA,EAAO,MAAM,CACtB,CAAC,EACD,KAAK,cAAc,cAAe,QAAS,UAAY,CACrD,OAAOA,EAAO,cAAc,CAC9B,CAAC,EAED,KAAK,cAAc,UAAW,QAAS,UAAY,CACjD,OAAOA,EAAO,KAAK,CACrB,CAAC,EACD,KAAK,cAAc,UAAW,QAAS,UAAY,CACjD,OAAOA,EAAO,KAAK,CACrB,CAAC,EAGD,IAAIG,EAAa,SAAS,eAAe,KAAK,SAAS,aAAa,EAChEC,EAAc,SAAS,eAAe,KAAK,SAAS,cAAc,EAClED,GAAYA,EAAW,iBAAiB,QAAS,UAAY,CAC/D,IAAIE,EAAK,SAAS,eAAeL,EAAO,SAAS,iBAAiB,EAC9DM,EAAON,EAAO,QAAQ,aAC1B,GAAIK,EAAI,CACN,IAAItC,EAAI,WAAWsC,EAAG,KAAK,EACtB,MAAMtC,CAAC,IAAGuC,EAAOvC,EACxB,CACAiC,EAAO,YAAYA,EAAO,gBAAkBM,CAAI,CAClD,CAAC,EACGF,GAAaA,EAAY,iBAAiB,QAAS,UAAY,CACjE,IAAIC,EAAK,SAAS,eAAeL,EAAO,SAAS,kBAAkB,EAC/DM,EAAON,EAAO,QAAQ,aAC1B,GAAIK,EAAI,CACN,IAAItC,EAAI,WAAWsC,EAAG,KAAK,EACtB,MAAMtC,CAAC,IAAGuC,EAAOvC,EACxB,CACAiC,EAAO,YAAYA,EAAO,gBAAkBM,CAAI,CAClD,CAAC,EAGD,KAAK,cAAc,UAAW,QAAS,UAAY,CACjD,OAAON,EAAO,cAAc,CAC9B,CAAC,EACD,KAAK,cAAc,eAAgB,QAAS,UAAY,CACtDA,EAAO,UAAU,EAAE,MAAM,SAAUjD,EAAG,CACpC,OAAO,QAAQ,MAAM,mBAAoBA,CAAC,CAC5C,CAAC,CACH,CAAC,EACD,KAAK,cAAc,gBAAiB,QAAS,UAAY,CACvD,OAAOiD,EAAO,WAAW,CAC3B,CAAC,CACH,CAUF,EAAG,CACD,IAAK,gBACL,MAAO,SAAuBO,EAAKC,EAAOC,EAAS,CACjD,IAAIJ,EAAK,SAAS,eAAe,KAAK,SAASE,CAAG,CAAC,EAC/CF,IACFA,EAAG,iBAAiBG,EAAOC,CAAO,EAClC,KAAK,eAAiB,KAAK,gBAAkB,CAAC,EACzC,KAAK,eAAeF,CAAG,IAAG,KAAK,eAAeA,CAAG,EAAI,CAAC,GAC3D,KAAK,eAAeA,CAAG,EAAE,KAAK,CAC5B,MAAOC,EACP,QAASC,CACX,CAAC,EAEL,CAQF,EAAG,CACD,IAAK,iBACL,MAAO,SAAwBC,EAAM,CACnC,IAAIC,EAAS,KACb,GAAI,GAACD,GAAQ,CAACA,EAAK,KAAK,WAAW,QAAQ,GAC3C,KAAIE,EAAS,IAAI,WACjBA,EAAO,OAAS,SAAU,EAAG,CAC3B,OAAOD,EAAO,UAAU,EAAE,OAAO,MAAM,CACzC,EACAC,EAAO,QAAU,SAAU,EAAG,CAC5B,QAAQ,MAAM,+BAAgC,CAAC,CACjD,EACAA,EAAO,cAAcF,CAAI,EAC3B,CAOF,EAAG,CACD,IAAK,YACL,MAAQ,UAAY,CAClB,IAAIG,EAAa1C,EAA+BrB,EAAa,EAAE,EAAE,SAASgE,EAAQC,EAAQ,CACxF,IAAIC,EAAS,KACTC,EAAOC,EAASC,EAAYC,EAAOC,EAAIC,EAC3C,OAAOxE,EAAa,EAAE,EAAE,SAAUyE,EAAU,CAC1C,OAAU,OAAQA,EAAS,EAAG,CAC5B,IAAK,GACH,GAAI,KAAK,cAAe,CACtBA,EAAS,EAAI,EACb,KACF,CACA,OAAOA,EAAS,EAAE,CAAC,EACrB,IAAK,GACH,GAAI,EAAE,CAACR,GAAU,OAAOA,GAAW,UAAY,CAACA,EAAO,WAAW,aAAa,GAAI,CACjFQ,EAAS,EAAI,EACb,KACF,CACA,OAAOA,EAAS,EAAE,CAAC,EACrB,IAAK,GACH,YAAK,uBAAuB,EAAK,EACjCA,EAAS,EAAI,EACN,KAAK,oBAAoBR,CAAM,EACxC,IAAK,GACHE,EAAQM,EAAS,EACjBL,EAAUH,EACN,KAAK,QAAQ,mBACfI,EAAaF,EAAM,aAAe,KAAK,QAAQ,oBAAsBA,EAAM,cAAgB,KAAK,QAAQ,oBACpGE,IACFC,EAAQ,KAAK,IAAI,KAAK,QAAQ,mBAAqBH,EAAM,aAAc,KAAK,QAAQ,oBAAsBA,EAAM,aAAa,EAC7HI,EAAK,KAAK,MAAMJ,EAAM,aAAeG,CAAK,EAC1CE,EAAK,KAAK,MAAML,EAAM,cAAgBG,CAAK,EAC3CF,EAAU,KAAK,wBAAwBD,EAAOI,EAAIC,EAAI,KAAK,QAAQ,iBAAiB,IAKxF,OAAO,MAAM,QAAQJ,EAAS,SAAUM,EAAM,CAC5CR,EAAO,OAAO,oBAAoB,EAClCA,EAAO,mBAAmB,EAC1BA,EAAO,OAAO,MAAM,EACpBA,EAAO,OAAO,mBAAmBA,EAAO,QAAQ,gBAAiBA,EAAO,OAAO,UAAU,KAAKA,EAAO,MAAM,CAAC,EAC5GQ,EAAK,IAAI,CACP,QAAS,OACT,QAAS,MACT,WAAY,GACZ,QAAS,EACX,CAAC,EACD,IAAIC,EAAOD,EAAK,MACZE,EAAOF,EAAK,OACZG,EAAOX,EAAO,YAAc,KAAK,MAAMA,EAAO,YAAY,aAAeA,EAAO,QAAQ,WAAW,EAAIA,EAAO,QAAQ,YACtHY,EAAOZ,EAAO,YAAc,KAAK,MAAMA,EAAO,YAAY,cAAgBA,EAAO,QAAQ,YAAY,EAAIA,EAAO,QAAQ,aAC5H,GAAIA,EAAO,QAAQ,iBAAkB,CAEnC,IAAIlB,EAAK,KAAK,IAAI,EAAG,KAAK,IAAIkB,EAAO,QAAQ,YAAaW,CAAI,EAAI,CAAC,EAC/D5B,EAAK,KAAK,IAAI,EAAG,KAAK,IAAIiB,EAAO,QAAQ,aAAcY,CAAI,EAAI,CAAC,EACpEZ,EAAO,kBAAkBlB,EAAIC,CAAE,EAC/B,IAAI8B,EAAW,KAAK,IAAI/B,EAAK2B,EAAM1B,EAAK2B,EAAM,CAAC,EAC/CF,EAAK,IAAI,CACP,KAAM,EACN,IAAK,CACP,CAAC,EACDA,EAAK,MAAMK,CAAQ,EACnBb,EAAO,eAAiBQ,EAAK,QAAU,CACzC,SAAWR,EAAO,QAAQ,mBAAoB,CAE5C,IAAIc,EAAM,KAAK,IAAId,EAAO,QAAQ,YAAaW,CAAI,EAC/CI,EAAM,KAAK,IAAIf,EAAO,QAAQ,aAAcY,CAAI,EACpDZ,EAAO,kBAAkBc,EAAKC,CAAG,EACjC,IAAIC,EAAa,KAAK,IAAI,EAAG,KAAK,IAAIF,EAAML,EAAMM,EAAML,CAAI,CAAC,EAC7DF,EAAK,IAAI,CACP,KAAM,EACN,IAAK,CACP,CAAC,EACDA,EAAK,MAAMQ,CAAU,EACrBhB,EAAO,eAAiBQ,EAAK,QAAU,CACzC,SAAWR,EAAO,QAAQ,oBAAqB,CAE7C,IAAIiB,EAAO,KAAK,IAAIN,EAAM,KAAK,MAAMF,CAAI,CAAC,EACtCS,EAAO,KAAK,IAAIN,EAAM,KAAK,MAAMF,CAAI,CAAC,EAC1CV,EAAO,kBAAkBiB,EAAMC,CAAI,EACnCV,EAAK,IAAI,CACP,KAAM,EACN,IAAK,CACP,CAAC,EACDA,EAAK,MAAM,CAAC,EACZR,EAAO,eAAiB,CAC1B,KAAO,CAEL,IAAImB,EAAO,KAAK,IAAInB,EAAO,QAAQ,YAAaW,CAAI,EAChDS,EAAO,KAAK,IAAIpB,EAAO,QAAQ,aAAcY,CAAI,EACrDZ,EAAO,kBAAkBmB,EAAMC,CAAI,EACnC,IAAIC,EAAY,KAAK,IAAIF,EAAOV,EAAMW,EAAOV,EAAM,CAAC,EACpDF,EAAK,IAAI,CACP,KAAM,EACN,IAAK,CACP,CAAC,EACDA,EAAK,MAAMa,CAAS,EACpBrB,EAAO,eAAiBQ,EAAK,QAAU,CACzC,CAEAR,EAAO,cAAgBQ,EACvBR,EAAO,OAAO,IAAIQ,CAAI,EACtBR,EAAO,OAAO,WAAWQ,CAAI,EAG7BR,EAAO,qBAAuB,KAC9BA,EAAO,oBAAsB,KAC7BA,EAAO,sBAAwB,KAC/BA,EAAO,YAAc,EACrBA,EAAO,aAAe,EACtBA,EAAO,gBAAkB,EACzBA,EAAO,cAAc,EACrBA,EAAO,gBAAgB,EACvBA,EAAO,UAAU,EACjBA,EAAO,OAAO,UAAU,EACxBA,EAAO,sBAAwB,GAC3B,OAAOA,EAAO,eAAkB,YAClCA,EAAO,cAAc,CAEzB,EAAG,CACD,YAAa,WACf,CAAC,EACH,IAAK,GACH,OAAOO,EAAS,EAAE,CAAC,CACvB,CACF,EAAGT,EAAS,IAAI,CAClB,CAAC,CAAC,EACF,SAASwB,EAAUC,EAAI,CACrB,OAAO1B,EAAW,MAAM,KAAM,SAAS,CACzC,CACA,OAAOyB,CACT,EAAE,CAMJ,EAAG,CACD,IAAK,gBACL,MAAO,UAAyB,CAC9B,MAAO,CAAC,EAAE,KAAK,eAAiB,KAAK,yBAAyB,OAAO,OAAS,KAAK,cAAc,MAAQ,GAAK,KAAK,cAAc,OAAS,EAC5I,CASF,EAAG,CACD,IAAK,sBACL,MAAO,SAA6BE,EAAS,CAC3C,OAAO,IAAI,QAAQ,SAAUC,EAAKC,EAAK,CACrC,IAAIC,EAAM,IAAI,MACdA,EAAI,OAAS,UAAY,CACvBA,EAAI,OAAS,KACbA,EAAI,QAAU,KACdF,EAAIE,CAAG,CACT,EACAA,EAAI,QAAU,SAAU5F,EAAG,CACzB4F,EAAI,OAAS,KACbA,EAAI,QAAU,KACdD,EAAI3F,CAAC,CACP,EACA4F,EAAI,IAAMH,CACZ,CAAC,CACH,CAYF,EAAG,CACD,IAAK,0BACL,MAAO,SAAiCvB,EAAO2B,EAAGC,EAAG,CACnD,IAAIC,EAAU,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAI,IAC9EC,EAAK,SAAS,cAAc,QAAQ,EACxCA,EAAG,MAAQH,EACXG,EAAG,OAASF,EACZ,IAAIG,EAAMD,EAAG,WAAW,IAAI,EAC5B,OAAAC,EAAI,UAAU/B,EAAO,EAAG,EAAGA,EAAM,aAAcA,EAAM,cAAe,EAAG,EAAG2B,EAAGC,CAAC,EACvEE,EAAG,UAAU,aAAcD,CAAO,CAC3C,CAUF,EAAG,CACD,IAAK,oBACL,MAAO,SAA2BF,EAAGC,EAAG,CACtC,IAAII,EAAK,KAAK,IAAI,EAAG,KAAK,MAAM,OAAOL,CAAC,GAAK,CAAC,CAAC,EAC3CM,EAAK,KAAK,IAAI,EAAG,KAAK,MAAM,OAAOL,CAAC,GAAK,CAAC,CAAC,EAE/C,KAAK,OAAO,SAASI,CAAE,EACvB,KAAK,OAAO,UAAUC,CAAE,EACpB,OAAO,KAAK,OAAO,YAAe,YAAY,KAAK,OAAO,WAAW,EAErE,KAAK,WACP,KAAK,SAAS,MAAM,MAAQD,EAAK,KACjC,KAAK,SAAS,MAAM,OAASC,EAAK,KAClC,KAAK,SAAS,MAAM,SAAW,OAEnC,CAUF,EAAG,CACD,IAAK,yBACL,MAAO,SAAgCC,EAAK,CAC1C,GAAI,CAACA,EAAK,MAAO,CACf,EAAG,EACH,EAAG,CACL,EACAA,EAAI,UAAU,EACd,IAAIC,EAAS,OAAOD,EAAI,WAAc,WAAaA,EAAI,UAAU,EAAI,KACrE,GAAIC,GAAUA,EAAO,OAAQ,OAAOA,EAAO,CAAC,EAC5C,IAAIC,EAAKF,EAAI,gBAAgB,GAAM,EAAI,EACvC,MAAO,CACL,EAAGE,EAAG,KACN,EAAGA,EAAG,GACR,CACF,CAWF,EAAG,CACD,IAAK,kCACL,MAAO,SAAyCF,EAAKG,EAASC,EAASC,EAAU,CAC3E,CAACL,GAAO,CAACK,GAAY,CAACL,EAAI,sBAC9BA,EAAI,IAAI,CACN,QAASG,EACT,QAASC,CACX,CAAC,EACDJ,EAAI,oBAAoBK,EAAUF,EAASC,CAAO,EAClDJ,EAAI,UAAU,EAChB,CAQF,EAAG,CACD,IAAK,yCACL,MAAO,SAAgDA,EAAK,CAC1D,GAAKA,EACL,CAAAA,EAAI,UAAU,EACd,IAAIE,EAAKF,EAAI,gBAAgB,GAAM,EAAI,EACnCM,EAAKJ,EAAG,KACRK,EAAKL,EAAG,IACZF,EAAI,IAAI,CACN,MAAOA,EAAI,MAAQ,GAAKM,EACxB,KAAMN,EAAI,KAAO,GAAKO,CACxB,CAAC,EACDP,EAAI,UAAU,EACd,KAAK,OAAO,UAAU,EACxB,CAOF,EAAG,CACD,IAAK,iCACL,MAAO,UAA0C,CAC/C,GAAK,KAAK,cACV,MAAK,cAAc,UAAU,EAC7B,IAAIE,EAAK,KAAK,cAAc,gBAAgB,GAAM,EAAI,EAGlDM,EAAa,KAAK,YAAc,KAAK,KAAK,KAAK,YAAY,aAAe,CAAC,EAAI,EAC/EC,EAAa,KAAK,YAAc,KAAK,KAAK,KAAK,YAAY,cAAgB,CAAC,EAAI,EAGpF,GAAID,EAAa,GAAKC,EAAa,GAAKP,EAAG,OAASM,GAAcN,EAAG,QAAUO,EAAY,CACzF,KAAK,kBAAkBD,EAAYC,CAAU,EAC7C,MACF,CAGA,IAAIC,EAAO,KAAK,IAAIF,GAAc,EAAG,KAAK,MAAMN,EAAG,KAAK,CAAC,EACrDS,EAAO,KAAK,IAAIF,GAAc,EAAG,KAAK,MAAMP,EAAG,MAAM,CAAC,EAC1D,KAAK,kBAAkBQ,EAAMC,CAAI,EACnC,CASF,EAAG,CACD,IAAK,aACL,MAAO,SAAoBC,EAAQ,CACjC,IAAIC,EAAS,KACb,OAAO,KAAK,UAAU,IAAI,UAAY,CACpC,OAAOA,EAAO,gBAAgBD,CAAM,CACtC,CAAC,CACH,CASF,EAAG,CACD,IAAK,kBACL,MAAO,SAAyBA,EAAQ,CACtC,IAAIE,EAAS,KAEb,GADI,CAAC,KAAK,eACN,KAAK,YAAa,OAAO,QAAQ,QAAQ,EAC7CF,EAAS,KAAK,IAAI,KAAK,QAAQ,SAAU,KAAK,IAAI,KAAK,QAAQ,SAAUA,CAAM,CAAC,EAChF,KAAK,aAAeA,EACpB,KAAK,YAAc,GACnB,KAAK,UAAU,EACf,IAAIG,EAAY,KAAK,eAAiBH,EAGlCI,EAAU,KAAK,uBAAuB,KAAK,aAAa,EAC5D,KAAK,gCAAgC,KAAK,cAAe,OAAQ,MAAOA,CAAO,EAC/E,IAAIC,EAAK,IAAI,QAAQ,SAAU3B,EAAK,CAClCwB,EAAO,cAAc,QAAQ,SAAUC,EAAW,CAChD,SAAUD,EAAO,QAAQ,kBACzB,SAAUA,EAAO,OAAO,UAAU,KAAKA,EAAO,MAAM,EACpD,WAAYxB,CACd,CAAC,CACH,CAAC,EACG4B,EAAK,IAAI,QAAQ,SAAU5B,EAAK,CAClCwB,EAAO,cAAc,QAAQ,SAAUC,EAAW,CAChD,SAAUD,EAAO,QAAQ,kBACzB,SAAUA,EAAO,OAAO,UAAU,KAAKA,EAAO,MAAM,EACpD,WAAYxB,CACd,CAAC,CACH,CAAC,EACD,OAAO,QAAQ,IAAI,CAAC2B,EAAIC,CAAE,CAAC,EAAE,KAAK,UAAY,CAC5CJ,EAAO,cAAc,IAAI,CACvB,OAAQC,EACR,OAAQA,CACV,CAAC,EACDD,EAAO,cAAc,UAAU,EAC3BA,EAAO,QAAQ,qBAAqBA,EAAO,+BAA+B,EAC9EA,EAAO,uCAAuCA,EAAO,aAAa,EAGlEA,EAAO,OAAO,WAAW,EAAE,QAAQ,SAAU9G,EAAG,CAC1CA,EAAE,QAAQ8G,EAAO,eAAe9G,CAAC,CACvC,CAAC,EACD8G,EAAO,YAAc,GACrBA,EAAO,cAAc,EACrBA,EAAO,UAAU,EACjBA,EAAO,UAAU,CACnB,CAAC,EAAE,MAAM,UAAY,CACnBA,EAAO,YAAc,GACrBA,EAAO,UAAU,CACnB,CAAC,CACH,CASF,EAAG,CACD,IAAK,cACL,MAAO,SAAqBK,EAAK,CAC/B,IAAIC,EAAS,KACb,OAAO,KAAK,UAAU,IAAI,UAAY,CACpC,OAAOA,EAAO,iBAAiBD,CAAG,CACpC,CAAC,CACH,CASF,EAAG,CACD,IAAK,mBACL,MAAO,SAA0BE,EAAS,CACxC,IAAIC,EAAS,KAGb,GAFI,CAAC,KAAK,eACN,KAAK,aACL,MAAMD,CAAO,EAAG,OAAO,QAAQ,QAAQ,EAC3C,KAAK,gBAAkBA,EACvB,KAAK,YAAc,GACnB,KAAK,UAAU,EACf,IAAIE,EAAS,KAAK,cAAc,eAAe,EAC/C,KAAK,gCAAgC,KAAK,cAAe,SAAU,SAAUA,CAAM,EACnF,IAAI3G,EAAI,IAAI,QAAQ,SAAU0E,EAAK,CACjCgC,EAAO,cAAc,QAAQ,QAASD,EAAS,CAC7C,SAAUC,EAAO,QAAQ,kBACzB,SAAUA,EAAO,OAAO,UAAU,KAAKA,EAAO,MAAM,EACpD,WAAYhC,CACd,CAAC,CACH,CAAC,EACD,OAAO1E,EAAE,KAAK,UAAY,CACxB0G,EAAO,cAAc,IAAI,QAASD,CAAO,EACzCC,EAAO,cAAc,UAAU,EAC3BA,EAAO,QAAQ,qBAAqBA,EAAO,+BAA+B,EAC9EA,EAAO,uCAAuCA,EAAO,aAAa,EAClE,IAAIE,EAAaF,EAAO,uBAAuBA,EAAO,aAAa,EACnEA,EAAO,gCAAgCA,EAAO,cAAe,OAAQ,MAAOE,CAAU,EAGtFF,EAAO,OAAO,WAAW,EAAE,QAAQ,SAAUtH,EAAG,CAC1CA,EAAE,QAAQsH,EAAO,eAAetH,CAAC,CACvC,CAAC,EACDsH,EAAO,YAAc,GACrBA,EAAO,cAAc,EACrBA,EAAO,UAAU,EACjBA,EAAO,UAAU,CACnB,CAAC,EAAE,MAAM,UAAY,CACnBA,EAAO,YAAc,GACrBA,EAAO,UAAU,CACnB,CAAC,CACH,CAMF,EAAG,CACD,IAAK,QACL,MAAO,UAAiB,CACtB,IAAIG,EAAS,KACb,OAAK,KAAK,cACH,KAAK,WAAW,CAAC,EAAE,KAAK,UAAY,CACzC,OAAOA,EAAO,YAAY,CAAC,CAC7B,CAAC,EAAE,KAAK,UAAY,CAClBA,EAAO,UAAU,CACnB,CAAC,EAAE,MAAM,SAAUC,EAAK,CACtB,QAAQ,MAAM,iBAAkBA,CAAG,CACrC,CAAC,EAP+B,QAAQ,QAAQ,CAQlD,CAMF,EAAG,CACD,IAAK,gBACL,MAAO,SAAuBC,EAAY,CACxC,IAAIC,EAAS,KACb,GAAI,GAACD,GAAc,CAAC,KAAK,QACzB,GAAI,CACF,IAAIE,EAAO,OAAOF,GAAe,SAAW,KAAK,MAAMA,CAAU,EAAIA,EACrE,KAAK,OAAO,aAAaE,EAAM,UAAY,CACzCD,EAAO,mBAAmB,EAC1B,IAAIE,EAAOF,EAAO,OAAO,WAAW,EACpCA,EAAO,cAAgBE,EAAK,KAAK,SAAU9H,EAAG,CAC5C,OAAOA,EAAE,OAAS,SAAW,CAACA,EAAE,MAClC,CAAC,GAAK,KACN4H,EAAO,cAAc,IAAI,CACvB,QAAS,OACT,QAAS,MACT,WAAY,GACZ,QAAS,GACT,YAAa,GACb,YAAa,SACf,CAAC,EACDA,EAAO,OAAO,WAAWA,EAAO,aAAa,EAC7C,IAAIG,EAAQD,EAAK,OAAO,SAAU9H,EAAG,CACnC,OAAOA,EAAE,MACX,CAAC,EACD4H,EAAO,YAAcG,EAAM,OAAO,SAAUC,EAAKC,EAAG,CAClD,OAAO,KAAK,IAAID,EAAKC,EAAE,MAAM,CAC/B,EAAG,CAAC,EACJL,EAAO,OAAO,UAAU,EACxBA,EAAO,gBAAgB,EACvBA,EAAO,UAAU,CACnB,CAAC,CACH,OAAS,EAAG,CACV,QAAQ,MAAM,yBAA0B,CAAC,CAC3C,CACF,CAKF,EAAG,CACD,IAAK,YACL,MAAO,UAAqB,CAC1B,IAAIM,EAAS,KACb,GAAK,KAAK,OACV,KAAIC,EAAY,KAAK,OAAO,gBAAgB,EAC5C,KAAK,mBAAmB,EACxB,GAAI,CAEF,IAAIC,EAAU,KAAK,OAAO,OAAO,CAAC,SAAU,WAAY,YAAY,CAAC,EACjE,MAAM,QAAQA,EAAQ,OAAO,IAE/BA,EAAQ,QAAUA,EAAQ,QAAQ,OAAO,SAAUpI,EAAG,CACpD,MAAO,CAACA,EAAE,UACZ,CAAC,GAEH,IAAIqI,EAAQ,KAAK,UAAUD,CAAO,EAC9BE,EAAS,KAAK,eAAiBD,EAC/BE,EAAe,GACfC,EAAM,IAAIC,EAAQ,UAAY,CAC5BF,GACFL,EAAO,cAAcG,CAAK,EAE5BE,EAAe,EACjB,EAAG,UAAY,CACbL,EAAO,cAAcI,CAAM,CAC7B,CAAC,EACD,KAAK,eAAe,QAAQE,CAAG,EAC/B,KAAK,cAAgBH,EACjBF,GAAaA,EAAU,QACzB,KAAK,kBAAkBA,CAAS,EAElC,KAAK,UAAU,CACjB,OAAST,EAAK,CACZ,QAAQ,KAAK,4CAA6CA,CAAG,CAC/D,EACF,CAKF,EAAG,CACD,IAAK,OACL,MAAO,UAAgB,CACrB,KAAK,eAAe,KAAK,CAC3B,CAKF,EAAG,CACD,IAAK,OACL,MAAO,UAAgB,CACrB,KAAK,eAAe,KAAK,CAC3B,CAqBF,EAAG,CACD,IAAK,UACL,MAAO,UAAmB,CACxB,IAAIgB,EAAU,KACVC,EAAS,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAI,CAAC,EAClF,GAAI,CAAC,KAAK,OAAQ,OAAO,KACzB,IAAIC,EAAYD,EAAO,OAAS,OAE5BE,EAAMzH,EAAc,CACtB,MAAOwH,EACP,MAAO,KAAK,QAAQ,iBACpB,OAAQ,KAAK,QAAQ,kBACrB,MAAO,kBACP,MAAO,GACP,IAAK,EACL,KAAM,OACN,IAAK,OACL,MAAO,EACP,WAAY,EACd,EAAGD,CAAM,EAGLG,EAAc,GACdC,EAAOD,EACPE,EAAMF,EACNG,EAAe,SAAsBC,EAAKC,EAAU,CACtD,GAAI,OAAOD,GAAQ,WAAY,OAAOA,EAAIR,EAAQ,OAAQA,EAAQ,OAAO,EACzE,GAAI,OAAOQ,GAAQ,UAAYA,EAAI,SAAS,GAAG,EAAG,CAChD,IAAIE,EAAU,WAAWF,CAAG,EAAI,IAChC,OAAO,KAAK,OAAOR,EAAQ,OAASA,EAAQ,OAAO,SAAS,EAAI,GAAKU,CAAO,CAC9E,CACA,OAAOF,GAAoBC,CAC7B,EACA,GAAIN,EAAI,OAAS,QAAa,KAAK,UAAW,CAC5C,IAAIQ,EACAC,EAAO,KAAK,UACZC,EAAYD,EAAK,KACrB,GAAIA,EAAK,eACPC,GAAaD,EAAK,eAAe,UACxBA,EAAK,MAAO,CACrB,IAAIE,EACJD,GAAaD,EAAK,QAAUE,EAAeF,EAAK,UAAY,MAAQE,IAAiB,OAASA,EAAe,EAC/G,CACAT,EAAO,KAAK,MAAMQ,EAAYV,EAAI,GAAG,EACrCG,GAAOK,EAAYC,EAAK,OAAS,MAAQD,IAAc,OAASA,EAAYP,CAC9E,MACEC,EAAOE,EAAaJ,EAAI,KAAMC,CAAW,EACzCE,EAAMC,EAAaJ,EAAI,IAAKC,CAAW,EAMzC,GAJAD,EAAI,MAAQI,EAAaJ,EAAI,MAAO,KAAK,QAAQ,gBAAgB,EACjEA,EAAI,OAASI,EAAaJ,EAAI,OAAQ,KAAK,QAAQ,iBAAiB,EAGhE,KAAK,QAAQ,qBAAuBD,IAAc,OAAQ,CAC5D,IAAIa,EAAY,KAAK,KAAKV,EAAOF,EAAI,MAAQ,EAAE,EAC3Ca,EAAY,KAAK,KAAKV,EAAMH,EAAI,OAAS,EAAE,EAC3CrE,EAAO,KAAK,YAAc,KAAK,MAAM,KAAK,YAAY,aAAe,CAAC,EAAI,EAC1EC,EAAO,KAAK,YAAc,KAAK,MAAM,KAAK,YAAY,cAAgB,CAAC,EAAI,EAC3EiC,EAAO,KAAK,IAAI,KAAK,OAAO,SAAS,EAAGlC,EAAMiF,CAAS,EACvD9C,EAAO,KAAK,IAAI,KAAK,OAAO,UAAU,EAAGlC,EAAMiF,CAAS,EAC5D,KAAK,kBAAkBhD,EAAMC,CAAI,CACnC,CACA,IAAI3E,EACJ,GAAI,OAAO6G,EAAI,iBAAoB,WACjC7G,EAAO6G,EAAI,gBAAgBA,EAAK,KAAK,OAAQ,KAAK,OAAO,MAEzD,QAAQD,EAAW,CACjB,IAAK,SACH5G,EAAO,IAAI,OAAO,OAAOZ,EAAc,CACrC,KAAM2H,EACN,IAAKC,EACL,OAAQC,EAAaJ,EAAI,OAAQ,KAAK,IAAIA,EAAI,MAAOA,EAAI,MAAM,EAAI,CAAC,EACpE,KAAMA,EAAI,MACV,QAASA,EAAI,MACb,MAAOA,EAAI,KACb,EAAGA,EAAI,MAAM,CAAC,EACd,MACF,IAAK,UACH7G,EAAO,IAAI,OAAO,QAAQZ,EAAc,CACtC,KAAM2H,EACN,IAAKC,EACL,GAAIC,EAAaJ,EAAI,GAAIA,EAAI,MAAQ,CAAC,EACtC,GAAII,EAAaJ,EAAI,GAAIA,EAAI,OAAS,CAAC,EACvC,KAAMA,EAAI,MACV,QAASA,EAAI,MACb,MAAOA,EAAI,KACb,EAAGA,EAAI,MAAM,CAAC,EACd,MACF,IAAK,UACH,IAAIc,EAAad,EAAI,QAAU,CAAC,EAC5B,MAAM,QAAQc,CAAU,GAAKA,EAAW,QAAUhI,EAAQgI,EAAW,CAAC,CAAC,IAAM,WAE/EA,EAAaA,EAAW,IAAI,SAAUC,EAAI,CACxC,MAAO,CACL,EAAG,OAAOA,EAAG,CAAC,EACd,EAAG,OAAOA,EAAG,CAAC,CAChB,CACF,CAAC,GAEH5H,EAAO,IAAI,OAAO,QAAQ2H,EAAYvI,EAAc,CAClD,KAAM2H,EACN,IAAKC,EACL,KAAMH,EAAI,MACV,QAASA,EAAI,MACb,MAAOA,EAAI,KACb,EAAGA,EAAI,MAAM,CAAC,EACd,MACF,IAAK,OACL,QACE7G,EAAO,IAAI,OAAO,KAAKZ,EAAc,CACnC,KAAM2H,EACN,IAAKC,EACL,MAAOC,EAAaJ,EAAI,MAAO,KAAK,QAAQ,gBAAgB,EAC5D,OAAQI,EAAaJ,EAAI,OAAQ,KAAK,QAAQ,iBAAiB,EAC/D,KAAMA,EAAI,MACV,QAASA,EAAI,MACb,MAAOA,EAAI,MACX,GAAIA,EAAI,GAER,GAAIA,EAAI,EACV,EAAGA,EAAI,MAAM,CAAC,CAClB,CAEF7G,EAAK,WAAa6G,EAAI,aAAe,GACrC7G,EAAK,YAAc,gBAAiB6G,EAAMA,EAAI,YAAc,GAC5D7G,EAAK,aAAe,CAAC,KAAK,QAAQ,cAClCA,EAAK,YAAc6G,EAAI,aAAe,MACtC7G,EAAK,YAAc6G,EAAI,aAAe,QACtC7G,EAAK,WAAa6G,EAAI,YAAc,EACpC7G,EAAK,mBAAqB,uBAAwB6G,EAAMA,EAAI,mBAAqB,GACjF7G,EAAK,OAAS6G,EAAI,QAAUA,EAAI,OAAO,QAAU,OACjD7G,EAAK,YAAc6G,EAAI,QAAUA,EAAI,OAAO,aAAe,EAC3D7G,EAAK,cAAgB,kBAAmB6G,EAAMA,EAAI,cAAgB,GAC9DA,EAAI,QAAUA,EAAI,OAAO,kBAAiB7G,EAAK,gBAAkB6G,EAAI,OAAO,iBAChF7G,EAAK,cAAgB6G,EAAI,MACzB,IAAIgB,EAAc,CAChB,OAAQ7H,EAAK,OACb,YAAaA,EAAK,YAClB,QAASA,EAAK,aAChB,EACI8H,EAAa,CACf,OAAQ,UACR,YAAa,EACb,QAAS,KAAK,IAAI9H,EAAK,cAAgB,GAAK,CAAC,CAC/C,EACA,OAAAA,EAAK,GAAG,YAAa,UAAY,CAC/BA,EAAK,IAAI8H,CAAU,EACnB9H,EAAK,OAAO,iBAAiB,CAC/B,CAAC,EACDA,EAAK,GAAG,WAAY,UAAY,CAC9BA,EAAK,IAAI6H,CAAW,EACpB7H,EAAK,OAAO,iBAAiB,CAC/B,CAAC,EAGD,KAAK,qBAAuB+G,EAC5B,KAAK,oBAAsBC,EAC3B,KAAK,sBAAwBC,EAAaJ,EAAI,MAAO,KAAK,QAAQ,gBAAgB,EAClF7G,EAAK,OAAS,EAAE,KAAK,YACrBA,EAAK,SAAW,GAAG,OAAO,KAAK,QAAQ,QAAQ,EAAE,OAAOA,EAAK,MAAM,EACnE,KAAK,UAAYA,EACjB,KAAK,OAAO,IAAIA,CAAI,EACpB,KAAK,OAAO,aAAaA,CAAI,EACzB6G,EAAI,YAAY,KAAK,OAAO,gBAAgB7G,CAAI,EACpD,KAAK,oBAAoB,CAACA,CAAI,CAAC,EAC/B,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,OAAO,UAAU,EACtB,KAAK,UAAU,EACX,OAAO6G,EAAI,UAAa,YAAYA,EAAI,SAAS7G,EAAM,KAAK,MAAM,EAC/DA,CACT,CAMF,EAAG,CACD,IAAK,qBACL,MAAO,UAA8B,CACnC,IAAI+H,EAAS,KAAK,OAAO,gBAAgB,EACrC,CAACA,GAAU,CAACA,EAAO,SACvB,KAAK,oBAAoBA,CAAM,EAC/B,KAAK,OAAO,OAAOA,CAAM,EACzB,KAAK,OAAO,oBAAoB,EAChC,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,OAAO,UAAU,EACtB,KAAK,UAAU,EACjB,CAMF,EAAG,CACD,IAAK,iBACL,MAAO,UAA0B,CAC/B,IAAIC,EAAU,KACVjC,EAAQ,KAAK,OAAO,WAAW,EAAE,OAAO,SAAU/H,EAAG,CACvD,OAAOA,EAAE,MACX,CAAC,EACD+H,EAAM,QAAQ,SAAUE,EAAG,CACzB,OAAO+B,EAAQ,oBAAoB/B,CAAC,CACtC,CAAC,EACDF,EAAM,QAAQ,SAAUE,EAAG,CACzB,OAAO+B,EAAQ,OAAO,OAAO/B,CAAC,CAChC,CAAC,EACD,KAAK,OAAO,oBAAoB,EAChC,KAAK,qBAAuB,KAC5B,KAAK,oBAAsB,KAC3B,KAAK,sBAAwB,KAC7B,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,OAAO,UAAU,EACtB,KAAK,UAAU,CACjB,CAQF,EAAG,CACD,IAAK,sBACL,MAAO,SAA6BjG,EAAM,CACxC,GAAI,GAACA,GAAQ,CAAC,KAAK,SACfA,EAAK,QAAS,CAChB,GAAI,CACF,IAAI8F,EAAO,KAAK,OAAO,WAAW,EAC9BA,EAAK,SAAS9F,EAAK,OAAO,GAC5B,KAAK,OAAO,OAAOA,EAAK,OAAO,CAEnC,MAAY,CAAa,CACzB,GAAI,CACF,OAAOA,EAAK,OACd,MAAY,CAAC,CACf,CACF,CASF,EAAG,CACD,IAAK,sBACL,MAAO,SAA6BA,EAAM,CACxC,GAAI,GAACA,GAAQ,CAAC,KAAK,QAAQ,mBAC3B,MAAK,oBAAoBA,CAAI,EAC7B,IAAIiI,EAAU,KAId,GAHI,KAAK,QAAQ,OAAS,OAAO,KAAK,QAAQ,MAAM,QAAW,aAC7DA,EAAU,KAAK,QAAQ,MAAM,OAAOjI,EAAM,MAAM,GAE9C,CAACiI,EAAS,CACZ,IAAIC,EAAMlI,EAAK,SACXmI,EAAc,CAChB,KAAM,EACN,IAAK,EACL,SAAU,GACV,KAAM,OACN,gBAAiB,kBACjB,WAAY,GACZ,QAAS,GACT,QAAS,EACT,QAAS,OACT,QAAS,KACX,EACI,KAAK,QAAQ,QACX,OAAO,KAAK,QAAQ,MAAM,SAAY,aACxCD,EAAM,KAAK,QAAQ,MAAM,QAAQlI,EAAM,KAAK,WAAW,GAGrD,KAAK,QAAQ,MAAM,aACrB,OAAO,OAAOmI,EAAa,KAAK,QAAQ,MAAM,WAAW,GAG7DF,EAAU,IAAI,OAAO,KAAKC,EAAKC,CAAW,CAC5C,CACAF,EAAQ,UAAY,GACpBjI,EAAK,QAAUiI,EACf,KAAK,OAAO,IAAIA,CAAO,EACvB,KAAK,OAAO,aAAaA,CAAO,EAChC,KAAK,eAAejI,CAAI,EAC1B,CAOF,EAAG,CACD,IAAK,qBACL,MAAO,UAA8B,CACnC,IAAIoI,EAAU,KACd,GAAK,KAAK,OACV,KAAItC,EAAO,KAAK,OAAO,WAAW,EAC9BuC,EAASvC,EAAK,OAAO,SAAU9H,EAAG,CACpC,OAAOA,EAAE,SACX,CAAC,EACDqK,EAAO,QAAQ,SAAU1J,EAAG,CAC1B,GAAI,CACEmH,EAAK,SAASnH,CAAC,GAAGyJ,EAAQ,OAAO,OAAOzJ,CAAC,CAC/C,MAAY,CAAC,CACf,CAAC,EACDmH,EAAK,QAAQ,SAAU9H,EAAG,CACxB,GAAIA,EAAE,QAAUA,EAAE,QAChB,GAAI,CACF,OAAOA,EAAE,OACX,MAAY,CAAC,CAEjB,CAAC,EACH,CAQF,EAAG,CACD,IAAK,iBACL,MAAO,SAAwBgC,EAAM,CACnC,IAAIsI,EACJ,GAAKtI,GACA,KAAK,QAAQ,mBACbA,EAAK,QACV,KAAIiE,EAASjE,EAAK,UAAYA,EAAK,UAAU,EAAI,KACjD,GAAI,GAACiE,GAAUA,EAAO,OAAS,GAC/B,KAAIsE,EAAKtE,EAAO,CAAC,EACbsB,EAASvF,EAAK,eAAe,EAC7BwI,EAAKjD,EAAO,EAAIgD,EAAG,EACnBE,EAAKlD,EAAO,EAAIgD,EAAG,EACnBG,EAAO,KAAK,KAAKF,EAAKA,EAAKC,EAAKA,CAAE,GAAK,EACvCE,EAAKH,EAAKE,EACVE,EAAKH,EAAKC,EACVG,EAAS,KAAK,IAAI,GAAIP,EAAwB,KAAK,QAAQ,mBAAqB,MAAQA,IAA0B,OAASA,EAAwB,CAAC,EACpJQ,EAAKP,EAAG,EAAII,EAAKE,EACjBE,EAAKR,EAAG,EAAIK,EAAKC,EACrB7I,EAAK,QAAQ,IAAI,CACf,KAAM,KAAK,MAAM8I,CAAE,EACnB,IAAK,KAAK,MAAMC,CAAE,EAClB,MAAO/I,EAAK,OAAS,EACrB,QAAS,OACT,QAAS,MACT,QAAS,EACX,CAAC,EACDA,EAAK,QAAQ,UAAU,EACvB,KAAK,OAAO,UAAU,GACxB,CAQF,EAAG,CACD,IAAK,oBACL,MAAO,SAA2BA,EAAM,CACjCA,GACA,KAAK,QAAQ,oBACbA,EAAK,SAAS,KAAK,oBAAoBA,CAAI,EAChDA,EAAK,QAAQ,QAAU,GACvB,KAAK,eAAeA,CAAI,EAC1B,CASF,EAAG,CACD,IAAK,sBACL,MAAO,SAA6BgJ,EAAU,CAC5C,IAAIC,EAAU,KACVC,GAAgBF,GAAY,CAAC,GAAG,KAAK,SAAUhL,EAAG,CACpD,OAAOA,EAAE,MACX,CAAC,EACG+H,EAAQ,KAAK,OAAO,WAAW,EAAE,OAAO,SAAU/H,EAAG,CACvD,OAAOA,EAAE,MACX,CAAC,EACD+H,EAAM,QAAQ,SAAUE,EAAG,CACzB,GAAIA,IAAMiD,EAAc,CACtB,GAAIjD,EAAE,QAAS,CACb,GAAI,CACFgD,EAAQ,OAAO,OAAOhD,EAAE,OAAO,CACjC,MAAY,CAAC,CACb,OAAOA,EAAE,OACX,CACAA,EAAE,IAAI,CACJ,OAAQ,OACR,YAAa,CACf,CAAC,CACH,MACEA,EAAE,IAAI,CACJ,OAAQ,UACR,YAAa,CACf,CAAC,CAEL,CAAC,EACGiD,GAAc,KAAK,kBAAkBA,CAAY,EACrD,KAAK,yBAAyBA,CAAY,EAC1C,KAAK,OAAO,UAAU,EACtB,KAAK,UAAU,CACjB,CAOF,EAAG,CACD,IAAK,kBACL,MAAO,UAA2B,CAChC,IAAIC,EAAU,KACVC,EAAS,SAAS,eAAe,KAAK,SAAS,QAAQ,EAC3D,GAAKA,EACL,CAAAA,EAAO,UAAY,GACnB,IAAIrD,EAAQ,KAAK,OAAO,WAAW,EAAE,OAAO,SAAU/H,EAAG,CACvD,OAAOA,EAAE,MACX,CAAC,EACD+H,EAAM,QAAQ,SAAU/F,EAAM,CAC5B,IAAIqJ,EAAK,SAAS,cAAc,IAAI,EACpCA,EAAG,UAAY,4BACfA,EAAG,YAAcrJ,EAAK,SACtBqJ,EAAG,QAAU,UAAY,CACvBF,EAAQ,OAAO,gBAAgBnJ,CAAI,EACnCmJ,EAAQ,oBAAoB,CAACnJ,CAAI,CAAC,CACpC,EACAoJ,EAAO,YAAYC,CAAE,CACvB,CAAC,EACH,CAQF,EAAG,CACD,IAAK,2BACL,MAAO,SAAkCH,EAAc,CACrD,IAAIE,EAAS,SAAS,eAAe,KAAK,SAAS,QAAQ,EAC3D,GAAKA,EACL,KAAIE,EAAQF,EAAO,iBAAiB,YAAY,EAChDE,EAAM,QAAQ,SAAUC,EAAM,CAC5B,IAAIC,EAAa,CAAC,CAACN,GAAgBK,EAAK,cAAgBL,EAAa,SACrEK,EAAK,UAAU,OAAO,SAAUC,CAAU,CAC5C,CAAC,EACH,CAQF,EAAG,CACD,IAAK,QACL,MAAQ,UAAY,CAClB,IAAIC,EAASzK,EAA+BrB,EAAa,EAAE,EAAE,SAAS+L,GAAW,CAC/E,IAAI3D,EAAO4D,EAAQC,EACnB,OAAOjM,EAAa,EAAE,EAAE,SAAUkM,EAAW,CAC3C,OAAU,OAAQA,EAAU,EAAIA,EAAU,EAAG,CAC3C,IAAK,GACH,GAAI,KAAK,cAAe,CACtBA,EAAU,EAAI,EACd,KACF,CACA,OAAOA,EAAU,EAAE,CAAC,EACtB,IAAK,GAIH,GAHA9D,EAAQ,KAAK,OAAO,WAAW,EAAE,OAAO,SAAU/H,EAAG,CACnD,OAAOA,EAAE,MACX,CAAC,EACG+H,EAAM,OAAQ,CAChB8D,EAAU,EAAI,EACd,KACF,CACA,OAAOA,EAAU,EAAE,CAAC,EACtB,IAAK,GACH,YAAK,OAAO,oBAAoB,EAChC,KAAK,OAAO,UAAU,EACtBA,EAAU,EAAI,EACdA,EAAU,EAAI,EACP,KAAK,eAAe,CACzB,gBAAiB,GACjB,WAAY,KAAK,QAAQ,gBAC3B,CAAC,EACH,IAAK,GACH,OAAAF,EAASE,EAAU,EACnB,KAAK,eAAe,EACpBA,EAAU,EAAI,EACP,KAAK,UAAUF,CAAM,EAC9B,IAAK,GACH,KAAK,UAAU,EACfE,EAAU,EAAI,EACd,MACF,IAAK,GACHA,EAAU,EAAI,EACdD,EAAKC,EAAU,EACf,QAAQ,MAAM,cAAeD,CAAE,EAC3B,KAAK,WAAU,KAAK,SAAS,MAAM,WAAa,IACtD,IAAK,GACH,OAAOC,EAAU,EAAE,CAAC,CACxB,CACF,EAAGH,EAAU,KAAM,CAAC,CAAC,EAAG,CAAC,CAAC,CAAC,CAC7B,CAAC,CAAC,EACF,SAASI,GAAQ,CACf,OAAOL,EAAO,MAAM,KAAM,SAAS,CACrC,CACA,OAAOK,CACT,EAAE,CAOJ,EAAG,CACD,IAAK,gBACL,MAAO,UAAyB,CAC9B,IAAIC,EAAW,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAI,KAAK,QAAQ,wBAChG,GAAK,KAAK,cACV,KAAIC,EAAkB,KAAK,QAAQ,yBACnC,KAAK,eAAe,CAClB,gBAAiBA,EACjB,WAAY,KAAK,QAAQ,gBAC3B,CAAC,EAAE,KAAK,SAAUpI,EAAQ,CACxB,IAAIqI,EAAO,SAAS,cAAc,GAAG,EACrCA,EAAK,SAAWF,EAChBE,EAAK,KAAOrI,EACZ,SAAS,KAAK,YAAYqI,CAAI,EAC9BA,EAAK,MAAM,EACX,SAAS,KAAK,YAAYA,CAAI,CAChC,CAAC,EAAE,MAAM,SAAUvE,EAAK,CACtB,OAAO,QAAQ,MAAM,iBAAkBA,CAAG,CAC5C,CAAC,EACH,CAaF,EAAG,CACD,IAAK,iBACL,MAAQ,UAAY,CAClB,IAAIwE,EAAgBlL,EAA+BrB,EAAa,EAAE,EAAE,SAASwM,GAAW,CACtF,IAAIC,EAAU,KACVC,EACFL,EACAM,EACAxI,EACA2B,EACAC,EACAE,EACAC,EACAkC,EACAwE,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EAAS,UACX,OAAOnN,EAAa,EAAE,EAAE,SAAUoN,EAAW,CAC3C,OAAU,OAAQA,EAAU,EAAG,CAC7B,IAAK,GAEH,GADAV,EAAOS,EAAO,OAAS,GAAKA,EAAO,CAAC,IAAM,OAAYA,EAAO,CAAC,EAAI,CAAC,EAC/D,KAAK,cAAe,CACtBC,EAAU,EAAI,EACd,KACF,CACA,MAAM,IAAI,MAAM,iBAAiB,EACnC,IAAK,GAGH,GAFAf,EAAkB,OAAOK,EAAK,iBAAoB,UAAYA,EAAK,gBAAkB,KAAK,QAAQ,yBAClGC,EAAaD,EAAK,YAAc,KAAK,QAAQ,kBAAoB,EAC7DL,EAAiB,CACnBe,EAAU,EAAI,EACd,KACF,CAGA,GADAjJ,EAAQ,KAAK,cAAc,WAAa,KAAK,cAAc,WAAW,EAAI,KAAK,cAAc,UAAY,KACrGA,EAAO,CACTiJ,EAAU,EAAI,EACd,KACF,CACA,OAAOA,EAAU,EAAE,EAAG,KAAK,OAAO,UAAU,CAC1C,OAAQ,OACR,QAAS,KAAK,QAAQ,kBACtB,WAAYT,CACd,CAAC,CAAC,EACJ,IAAK,GACH,OAAA7G,EAAI,KAAK,cAAc,MACvBC,EAAI,KAAK,cAAc,OACvBE,EAAK,SAAS,cAAc,QAAQ,EACpCA,EAAG,MAAQH,EACXG,EAAG,OAASF,EACZG,EAAMD,EAAG,WAAW,IAAI,EACxBC,EAAI,UAAU/B,EAAO,EAAG,EAAG2B,EAAGC,CAAC,EACxBqH,EAAU,EAAE,EAAGnH,EAAG,UAAU,aAAc,KAAK,QAAQ,iBAAiB,CAAC,EAClF,IAAK,GAEH,OAAAmC,EAAQ,KAAK,OAAO,WAAW,EAAE,OAAO,SAAU/H,EAAG,CACnD,OAAOA,EAAE,MACX,CAAC,EACDuM,EAAcxE,EAAM,IAAI,SAAUE,EAAG,CACnC,MAAO,CACL,IAAKA,EACL,QAASA,EAAE,QACX,KAAMA,EAAE,KACR,YAAaA,EAAE,YACf,OAAQA,EAAE,OACV,WAAYA,EAAE,WACd,aAAcA,EAAE,YAClB,CACF,CAAC,EACDF,EAAM,QAAQ,SAAUE,EAAG,CACzB,OAAOmE,EAAQ,oBAAoBnE,CAAC,CACtC,CAAC,EACD,KAAK,OAAO,oBAAoB,EAChC,KAAK,OAAO,UAAU,EAGtBF,EAAM,QAAQ,SAAUE,EAAG,CACzBA,EAAE,IAAI,CACJ,QAAS,EACT,KAAM,UACN,YAAa,EACb,OAAQ,KACR,WAAY,EACd,CAAC,EACDA,EAAE,UAAU,CACd,CAAC,EACD,KAAK,OAAO,UAAU,EAGtB,KAAK,cAAc,UAAU,EAC7BuE,EAAQ,KAAK,cAAc,gBAAgB,GAAM,EAAI,EACrDC,EAAK,KAAK,IAAI,EAAG,KAAK,MAAMD,EAAM,IAAI,CAAC,EACvCE,EAAK,KAAK,IAAI,EAAG,KAAK,MAAMF,EAAM,GAAG,CAAC,EACtCG,EAAK,KAAK,IAAI,EAAG,KAAK,MAAMH,EAAM,KAAK,CAAC,EACxCI,EAAK,KAAK,IAAI,EAAG,KAAK,MAAMJ,EAAM,MAAM,CAAC,EACzCO,EAAU,EAAI,EACP,IAAI,QAAQ,SAAUC,EAASC,EAAQ,CAC5C,GAAI,CACF,IAAIC,EAAcd,EAAQ,OAAO,UAAU,CACzC,OAAQ,OACR,QAASA,EAAQ,QAAQ,kBACzB,WAAYE,CACd,CAAC,EACG9G,EAAM,IAAI,MACdA,EAAI,OAAS,UAAY,CACvB,GAAI,CACF,IAAI2H,EAAM,KAAK,MAAMV,EAAKH,CAAU,EAChCc,EAAM,KAAK,MAAMV,EAAKJ,CAAU,EAChCe,EAAM,KAAK,MAAMV,EAAKL,CAAU,EAChCgB,EAAM,KAAK,MAAMV,EAAKN,CAAU,EAChCiB,EAAM,SAAS,cAAc,QAAQ,EACzCA,EAAI,MAAQF,EACZE,EAAI,OAASD,EACb,IAAIE,EAAOD,EAAI,WAAW,IAAI,EAC9BC,EAAK,UAAUhI,EAAK2H,EAAKC,EAAKC,EAAKC,EAAK,EAAG,EAAGD,EAAKC,CAAG,EACtD,IAAIG,EAAMF,EAAI,UAAU,aAAcnB,EAAQ,QAAQ,iBAAiB,EACvEY,EAAQS,CAAG,CACb,OAAS7N,EAAG,CACVqN,EAAOrN,CAAC,CACV,CACF,EACA4F,EAAI,QAAUyH,EACdzH,EAAI,IAAM0H,CACZ,OAAStN,EAAG,CACVqN,EAAOrN,CAAC,CACV,CACF,CAAC,EACH,IAAK,GACH,OAAAiN,EAAcE,EAAU,EAExBR,EAAY,QAAQ,SAAUmB,EAAG,CAC/B,GAAI,CACFA,EAAE,IAAI,IAAI,CACR,QAASA,EAAE,QACX,KAAMA,EAAE,KACR,YAAaA,EAAE,YACf,OAAQA,EAAE,OACV,WAAYA,EAAE,WACd,aAAcA,EAAE,YAClB,CAAC,EACDA,EAAE,IAAI,UAAU,CAClB,MAAY,CAAC,CACf,CAAC,EACD,KAAK,OAAO,UAAU,EACfX,EAAU,EAAE,EAAGF,CAAW,CACrC,CACF,EAAGV,EAAU,IAAI,CACnB,CAAC,CAAC,EACF,SAASwB,GAAiB,CACxB,OAAOzB,EAAc,MAAM,KAAM,SAAS,CAC5C,CACA,OAAOyB,CACT,EAAE,CAkBJ,EAAG,CACD,IAAK,kBACL,MAAQ,UAAY,CAClB,IAAIC,EAAmB5M,EAA+BrB,EAAa,EAAE,EAAE,SAASkO,GAAW,CACzF,IAAIC,EAAuBC,EAAuBC,EAC9C3B,EACF4B,EACAC,EACAC,EACAC,EACAC,EACA1I,EACA2I,EACAhC,EACAiC,EACAxC,EACAyC,EACAC,EACA7K,EACA8K,EACAC,EACAC,EACA7O,EACA8O,EACAtL,EACAuL,EAAS,UACX,OAAOnP,EAAa,EAAE,EAAE,SAAUoP,EAAW,CAC3C,OAAU,OAAQA,EAAU,EAAG,CAC7B,IAAK,GAEH,GADA1C,EAAOyC,EAAO,OAAS,GAAKA,EAAO,CAAC,IAAM,OAAYA,EAAO,CAAC,EAAI,CAAC,EAC/D,KAAK,cAAe,CACtBC,EAAU,EAAI,EACd,KACF,CACA,MAAM,IAAI,MAAM,iBAAiB,EACnC,IAAK,GAYH,GAXAd,EAAkB5B,EAAK,UAAW6B,EAAYD,IAAoB,OAAS,GAAOA,EAAiBE,EAAiB9B,EAAK,SAAU+B,EAAWD,IAAmB,OAAS,OAASA,EAAgBE,EAAgBhC,EAAK,QAAS1G,EAAU0I,IAAkB,QAAUP,EAAwB,KAAK,QAAQ,qBAAuB,MAAQA,IAA0B,OAASA,EAAwB,IAAOO,EAAeC,EAAmBjC,EAAK,WAAYC,EAAagC,IAAqB,QAAUP,EAAwB,KAAK,QAAQ,oBAAsB,MAAQA,IAA0B,OAASA,EAAwB,EAAIO,EAAkBC,EAAiBlC,EAAK,SAAUN,EAAWwC,IAAmB,QAAUP,EAAwB,KAAK,QAAQ,2BAA6B,MAAQA,IAA0B,OAASA,EAAwB,qBAAuBO,EACp2BC,EAAc,CACZ,KAAQ,OACR,IAAO,OACP,aAAc,OACd,IAAO,MACP,YAAa,MACb,KAAQ,OACR,aAAc,MAChB,EACAC,EAAeD,EAAY,OAAOJ,CAAQ,EAAE,YAAY,CAAC,GAAK,OAC1D,CAACF,EAAW,CACda,EAAU,EAAI,EACd,KACF,CACA,OAAAA,EAAU,EAAI,EACP,KAAK,eAAe,CACzB,gBAAiB,GACjB,WAAYzC,CACd,CAAC,EACH,IAAK,GACH1I,EAASmL,EAAU,EACnBA,EAAU,EAAI,EACd,MACF,IAAK,GACH,OAAAA,EAAU,EAAI,EACP,KAAK,eAAe,CACzB,gBAAiB,GACjB,WAAYzC,CACd,CAAC,EACH,IAAK,GACH1I,EAASmL,EAAU,EACrB,IAAK,GAGH,GADAL,EAAe9K,EACX8K,EAAa,WAAW,cAAc,OAAOD,CAAY,CAAC,EAAG,CAC/DM,EAAU,EAAI,EACd,KACF,CACA,OAAAA,EAAU,EAAI,EACP,IAAI,QAAQ,SAAU/B,EAASC,EAAQ,CAC5C,IAAIzH,EAAM,IAAI,OAAO,MACrBA,EAAI,YAAc,YAClBA,EAAI,OAAS,UAAY,CACvB,GAAI,CACF,IAAII,EAAK,SAAS,cAAc,QAAQ,EACxCA,EAAG,MAAQJ,EAAI,MACfI,EAAG,OAASJ,EAAI,OAChB,IAAIK,EAAMD,EAAG,WAAW,IAAI,EAC5BC,EAAI,UAAUL,EAAK,EAAG,CAAC,EACvB,IAAIwJ,EAAOpJ,EAAG,UAAU,SAAS,OAAO6I,CAAY,EAAG9I,CAAO,EAC9DqH,EAAQgC,CAAI,CACd,OAASpP,EAAG,CACVqN,EAAOrN,CAAC,CACV,CACF,EACA4F,EAAI,QAAUyH,EACdzH,EAAI,IAAM5B,CACZ,CAAC,EACH,IAAK,GACH8K,EAAeK,EAAU,EAC3B,IAAK,GAMH,IAJAJ,EAAO,KAAKD,EAAa,MAAM,GAAG,EAAE,CAAC,CAAC,EACtCE,EAAO,SAAS,OAAOH,CAAY,EACnC1O,EAAI4O,EAAK,OACTE,EAAQ,IAAI,WAAW9O,CAAC,EACjBA,KACL8O,EAAM9O,CAAC,EAAI4O,EAAK,WAAW5O,CAAC,EAE9B,OAAAwD,EAAO,IAAI,KAAK,CAACsL,CAAK,EAAG9C,EAAU,CACjC,KAAM6C,CACR,CAAC,EACMG,EAAU,EAAE,EAAGxL,CAAI,CAC9B,CACF,EAAGsK,EAAU,IAAI,CACnB,CAAC,CAAC,EACF,SAASoB,GAAkB,CACzB,OAAOrB,EAAiB,MAAM,KAAM,SAAS,CAC/C,CACA,OAAOqB,CACT,EAAE,CAMJ,EAAG,CACD,IAAK,gBACL,MAAO,UAAyB,CAC9B,IAAIC,EAAU,KACd,GAAI,GAAC,KAAK,QAAU,CAAC,KAAK,eAAiB,KAAK,YAC3C,KAAK,cAAc,EACxB,MAAK,UAAY,GAGjB,KAAK,sBAAwB,KAAK,OAAO,UACzC,KAAK,OAAO,UAAY,GAGxB,KAAK,OAAO,oBAAoB,EAGhC,KAAK,cAAc,UAAU,EAC7B,IAAI1C,EAAQ,KAAK,cAAc,gBAAgB,GAAM,EAAI,EAErD2C,EAAU,KAAK,QAAQ,MAAQ,KAAK,QAAQ,KAAK,QAAU,KAAK,QAAQ,KAAK,QAAU,GACvFpG,EAAO,KAAK,IAAI,EAAG,KAAK,MAAMyD,EAAM,KAAO2C,CAAO,CAAC,EACnDnG,EAAM,KAAK,IAAI,EAAG,KAAK,MAAMwD,EAAM,IAAM2C,CAAO,CAAC,EACjDC,EAAQ,KAAK,IAAI,KAAK,QAAQ,KAAK,UAAY,GAAI,KAAK,MAAM5C,EAAM,MAAQ2C,EAAU,CAAC,CAAC,EACxFE,EAAS,KAAK,IAAI,KAAK,QAAQ,KAAK,WAAa,GAAI,KAAK,MAAM7C,EAAM,OAAS2C,EAAU,CAAC,CAAC,EAG3FG,EAAW,IAAI,OAAO,KAAK,CAC7B,KAAMvG,EACN,IAAKC,EACL,MAAOoG,EACP,OAAQC,EACR,KAAM,mBACN,OAAQ,UACR,gBAAiB,CAAC,EAAG,CAAC,EACtB,YAAa,EACb,cAAe,GACf,WAAY,GACZ,iBAAkB,CAAC,EAAE,KAAK,QAAQ,MAAQ,KAAK,QAAQ,KAAK,yBAC5D,aAAc,EAAE,KAAK,QAAQ,MAAQ,KAAK,QAAQ,KAAK,yBACvD,WAAY,EACZ,cAAe,GACf,QAAS,OACT,QAAS,KACX,CAAC,EAGD,KAAK,OAAO,IAAIC,CAAQ,EACxBA,EAAS,WAAa,GACtB,KAAK,OAAO,aAAaA,CAAQ,EACjC,KAAK,OAAO,gBAAgBA,CAAQ,EAGpC,KAAK,UAAYA,EAIjB,KAAK,iBAAmB,CAAC,EACzB,KAAK,OAAO,WAAW,EAAE,QAAQ,SAAUtP,EAAG,CAC5C,GAAIA,IAAMsP,EAAU,CAClBJ,EAAQ,iBAAiB,KAAK,CAC5B,IAAKlP,EACL,QAASA,EAAE,QACX,WAAYA,EAAE,UAChB,CAAC,EACD,GAAI,CACFA,EAAE,QAAU,GACZA,EAAE,WAAa,EACjB,MAAY,CAAa,CAC3B,CACF,CAAC,EAGD,IAAIuP,EAAa,UAAsB,CACrC,GAAI,CACFD,EAAS,UAAU,EACnBJ,EAAQ,OAAO,iBAAiB,CAClC,MAAY,CAAC,CACf,EACAI,EAAS,GAAG,WAAYC,CAAU,EAClCD,EAAS,GAAG,SAAUC,CAAU,EAChCD,EAAS,GAAG,UAAWC,CAAU,EAGjC,KAAK,cAAc,KAAK,CACtB,OAAQD,EACR,SAAU,CAAC,CACT,IAAK,WACL,GAAIC,CACN,EAAG,CACD,IAAK,SACL,GAAIA,CACN,EAAG,CACD,IAAK,UACL,GAAIA,CACN,CAAC,CACH,CAAC,EACD,KAAK,UAAU,EACf,KAAK,OAAO,UAAU,EACxB,CAMF,EAAG,CACD,IAAK,aACL,MAAO,UAAsB,CAC3B,GAAI,GAAC,KAAK,QAAU,CAAC,KAAK,WAE1B,IAAI,KAAK,UAAW,CAClB,GAAI,CACE,KAAK,eAAiB,KAAK,cAAc,QAC3C,KAAK,cAAc,QAAQ,SAAU7J,EAAG,CACtCA,EAAE,SAAS,QAAQ,SAAU8J,EAAK,CAChC,OAAO9J,EAAE,OAAO,IAAI8J,EAAI,IAAKA,EAAI,EAAE,CACrC,CAAC,CACH,CAAC,CAEL,MAAY,CAAa,CACzB,GAAI,CACF,KAAK,OAAO,OAAO,KAAK,SAAS,CACnC,MAAY,CAAC,CACb,KAAK,UAAY,IACnB,CAEI,MAAM,QAAQ,KAAK,gBAAgB,GACrC,KAAK,iBAAiB,QAAQ,SAAUvP,EAAG,CACzC,GAAI,CACFA,EAAE,IAAI,QAAUA,EAAE,QAClBA,EAAE,IAAI,WAAaA,EAAE,UACvB,MAAY,CAAC,CACf,CAAC,EAEH,KAAK,iBAAmB,KACxB,KAAK,cAAgB,CAAC,EACtB,KAAK,UAAY,GAEjB,KAAK,OAAO,UAAY,CAAC,CAAC,KAAK,sBAC/B,KAAK,sBAAwB,OAC7B,KAAK,OAAO,oBAAoB,EAChC,KAAK,UAAU,EACf,KAAK,OAAO,UAAU,EACxB,CAOF,EAAG,CACD,IAAK,YACL,MAAQ,UAAY,CAClB,IAAIwP,EAAazO,EAA+BrB,EAAa,EAAE,EAAE,SAAS+P,GAAW,CACnF,IAAIC,EAAU,KACVC,EAAYnD,EAAIC,EAAIC,EAAIC,EAAIiD,EAAYzH,EAASL,EAAO+H,EAAe5C,EAAa6C,EAAWC,EAAUC,EAAOzH,EAAK0H,EAAKC,EAC9H,OAAOxQ,EAAa,EAAE,EAAE,SAAUyQ,EAAW,CAC3C,OAAU,OAAQA,EAAU,EAAIA,EAAU,EAAG,CAC3C,IAAK,GACH,GAAI,EAAE,CAAC,KAAK,QAAU,CAAC,KAAK,WAAa,CAAC,KAAK,WAAY,CACzDA,EAAU,EAAI,EACd,KACF,CACA,OAAOA,EAAU,EAAE,CAAC,EACtB,IAAK,GAEH,KAAK,UAAU,UAAU,EACzBR,EAAa,KAAK,UAAU,gBAAgB,GAAM,EAAI,EACtDnD,EAAK,KAAK,IAAI,EAAG,KAAK,MAAMmD,EAAW,IAAI,CAAC,EAC5ClD,EAAK,KAAK,IAAI,EAAG,KAAK,MAAMkD,EAAW,GAAG,CAAC,EAC3CjD,EAAK,KAAK,IAAI,EAAG,KAAK,MAAM,KAAK,IAAIiD,EAAW,MAAO,KAAK,OAAO,SAAS,EAAInD,CAAE,CAAC,CAAC,EACpFG,EAAK,KAAK,IAAI,EAAG,KAAK,MAAM,KAAK,IAAIgD,EAAW,OAAQ,KAAK,OAAO,UAAU,EAAIlD,CAAE,CAAC,CAAC,EACtFmD,EAAa,KACb,GAAI,CACFzH,EAAU,KAAK,OAAO,OAAO,CAAC,SAAU,WAAY,YAAY,CAAC,EAC7D,MAAM,QAAQA,EAAQ,OAAO,IAC/BA,EAAQ,QAAUA,EAAQ,QAAQ,OAAO,SAAUpI,EAAG,CACpD,MAAO,CAACA,EAAE,UACZ,CAAC,GAEH6P,EAAa,KAAK,UAAUzH,CAAO,CACrC,OAASxI,EAAG,CACV,QAAQ,KAAK,8CAA+CA,CAAC,EAC7DiQ,EAAa,IACf,CAGA,GAAI,CACF9H,EAAQ,KAAK,OAAO,WAAW,EAAE,OAAO,SAAU/H,EAAG,CACnD,OAAOA,EAAE,MACX,CAAC,EACG+H,GAASA,EAAM,SACjBA,EAAM,QAAQ,SAAUE,EAAG,CACzB,GAAI,CACF0H,EAAQ,oBAAoB1H,CAAC,EAC7B0H,EAAQ,OAAO,OAAO1H,CAAC,CACzB,OAASP,EAAK,CACZ,QAAQ,KAAK,mCAAoCA,CAAG,CACtD,CACF,CAAC,EACD,KAAK,OAAO,oBAAoB,EAChC,KAAK,OAAO,UAAU,EAE1B,OAAS9H,EAAG,CACV,QAAQ,KAAK,wCAAyCA,CAAC,CACzD,CACA,GAAI,CACF,GAAI,KAAK,UAAW,CAClB,GAAI,CACE,KAAK,eAAiB,KAAK,cAAc,QAC3C,KAAK,cAAc,QAAQ,SAAU8F,EAAG,CACtCA,EAAE,SAAS,QAAQ,SAAU8J,EAAK,CAChC,OAAO9J,EAAE,OAAO,IAAI8J,EAAI,IAAKA,EAAI,EAAE,CACrC,CAAC,CACH,CAAC,CAEL,MAAY,CAAa,CACzB,GAAI,CACF,KAAK,OAAO,OAAO,KAAK,SAAS,CACnC,MAAY,CAAa,CACzB,KAAK,UAAY,IACnB,CACF,MAAY,CAAa,CAGzB,YAAK,UAAY,GACjB,KAAK,OAAO,UAAY,CAAC,CAAC,KAAK,sBAC/B,KAAK,sBAAwB,OAG7BY,EAAU,EAAI,EACdlD,EAAc,KAAK,OAAO,UAAU,CAClC,OAAQ,OACR,QAAS,KAAK,QAAQ,mBAAqB,IAC3C,WAAY,CACd,CAAC,EACDkD,EAAU,EAAI,EACP,IAAI,QAAQ,SAAUpD,EAASC,EAAQ,CAC5C,IAAIzH,EAAM,IAAI,MACdA,EAAI,OAAS,UAAY,CACvB,GAAI,CACF,IAAII,EAAK,SAAS,cAAc,QAAQ,EACxCA,EAAG,MAAQ+G,EACX/G,EAAG,OAASgH,EACZ,IAAI/G,EAAMD,EAAG,WAAW,IAAI,EAC5BC,EAAI,UAAUL,EAAKiH,EAAIC,EAAIC,EAAIC,EAAI,EAAG,EAAGD,EAAIC,CAAE,EAC/C,IAAIa,EAAM7H,EAAG,UAAU,aAAc+J,EAAQ,QAAQ,mBAAqB,GAAI,EAC9E3C,EAAQS,CAAG,CACb,OAAS/F,EAAK,CACZuF,EAAOvF,CAAG,CACZ,CACF,EACAlC,EAAI,QAAU,SAAU5F,EAAG,CACzB,OAAOqN,EAAOrN,CAAC,CACjB,EACA4F,EAAI,IAAM0H,CACZ,CAAC,EACH,IAAK,GACH4C,EAAgBM,EAAU,EAC1BA,EAAU,EAAI,EACd,MACF,IAAK,GACH,OAAAA,EAAU,EAAI,EACdF,EAAME,EAAU,EAChB,QAAQ,MAAM,4CAA6CF,CAAG,EAC9D,KAAK,UAAU,EACRE,EAAU,EAAE,CAAC,EACtB,IAAK,GACH,OAAAA,EAAU,EAAI,EACdA,EAAU,EAAI,EACP,KAAK,UAAUN,CAAa,EACrC,IAAK,GACHM,EAAU,EAAI,EACd,MACF,IAAK,GACH,OAAAA,EAAU,EAAI,EACdD,EAAMC,EAAU,EAChB,QAAQ,MAAM,6CAA8CD,CAAG,EAC/D,KAAK,UAAU,EACRC,EAAU,EAAE,CAAC,EACtB,IAAK,GAEHL,EAAY,KACZ,GAAI,CACFC,EAAW,KAAK,OAAO,OAAO,CAAC,SAAU,WAAY,YAAY,CAAC,EAC9D,MAAM,QAAQA,EAAS,OAAO,IAChCA,EAAS,QAAUA,EAAS,QAAQ,OAAO,SAAUhQ,EAAG,CACtD,MAAO,CAACA,EAAE,UACZ,CAAC,GAEH+P,EAAY,KAAK,UAAUC,CAAQ,CACrC,OAASpQ,EAAG,CACV,QAAQ,KAAK,6CAA8CA,CAAC,EAC5DmQ,EAAY,IACd,CACA,GAAI,CACFE,EAAQ,KACRzH,EAAM,IAAIC,EAAQ,UAAY,CACxBsH,GAAWE,EAAM,cAAcF,CAAS,CAC9C,EAAG,UAAY,CACTF,GAAYI,EAAM,cAAcJ,CAAU,CAChD,CAAC,EACI,KAAK,iBAAgB,KAAK,eAAiB,IAAI1N,EAAe,KAAK,gBAAkB,EAAE,GAGxF,KAAK,eAAe,aAAe,KAAK,eAAe,QAAQ,OAAS,IAC1E,KAAK,eAAe,QAAU,KAAK,eAAe,QAAQ,MAAM,EAAG,KAAK,eAAe,aAAe,CAAC,GAEzG,KAAK,eAAe,QAAQ,KAAKqG,CAAG,EAChC,KAAK,eAAe,QAAQ,OAAS,KAAK,eAAe,QAC3D,KAAK,eAAe,QAAQ,MAAM,EAElC,KAAK,eAAe,cAExB,OAAS5I,EAAG,CACV,QAAQ,KAAK,4CAA6CA,CAAC,CAC7D,CAGA,KAAK,UAAU,EACf,KAAK,OAAO,UAAU,EACxB,IAAK,GACH,OAAOwQ,EAAU,EAAE,CAAC,CACxB,CACF,EAAGV,EAAU,KAAM,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,CAAC,CAAC,CACrC,CAAC,CAAC,EACF,SAASW,GAAY,CACnB,OAAOZ,EAAW,MAAM,KAAM,SAAS,CACzC,CACA,OAAOY,CACT,EAAE,CAQJ,EAAG,CACD,IAAK,gBACL,MAAO,UAAyB,CAC9B,IAAIC,EAAU,SAAS,eAAe,KAAK,SAAS,SAAS,EACzDA,IAASA,EAAQ,MAAQ,KAAK,MAAM,KAAK,aAAe,GAAG,EACjE,CAOF,EAAG,CACD,IAAK,YACL,MAAO,UAAqB,CAC1B,IAAIC,EAAsBC,EACtBC,EAAS,CAAC,CAAC,KAAK,cAChB1I,EAAQ0I,EAAS,KAAK,OAAO,WAAW,EAAE,OAAO,SAAUzQ,EAAG,CAChE,OAAOA,EAAE,MACX,CAAC,EAAI,CAAC,EACF0Q,EAAW3I,EAAM,OAAS,EAC1BgC,EAAS,KAAK,OAAO,gBAAgB,EACrC4G,EAAkB5G,GAAUA,EAAO,OACnC6G,EAAY,KAAK,eAAiB,GAAK,KAAK,kBAAoB,EAChEC,GAAWN,EAAuB,KAAK,kBAAoB,MAAQA,IAAyB,OAAS,OAASA,EAAqB,QAAQ,EAC3IO,GAAWN,EAAwB,KAAK,kBAAoB,MAAQA,IAA0B,OAAS,OAASA,EAAsB,QAAQ,EAC9IO,EAAS,CAAC,CAAC,KAAK,UACpB,GAAIA,EAAQ,CAEV,QAASC,EAAK,EAAGC,EAAe,OAAO,KAAK,KAAK,UAAY,CAAC,CAAC,EAAGD,EAAKC,EAAa,OAAQD,IAAM,CAChG,IAAIE,EAAID,EAAaD,CAAE,EACnB9N,EAAK,SAAS,eAAe,KAAK,SAASgO,CAAC,CAAC,EAC5ChO,IACDgO,IAAM,gBAAkBA,IAAM,gBAChChO,EAAG,SAAW,GAEdA,EAAG,SAAW,GAElB,CACA,MACF,CACA,KAAK,aAAa,YAAa,CAACuN,GAAU,KAAK,aAAe,KAAK,cAAgB,KAAK,QAAQ,QAAQ,EACxG,KAAK,aAAa,aAAc,CAACA,GAAU,KAAK,aAAe,KAAK,cAAgB,KAAK,QAAQ,QAAQ,EACzG,KAAK,aAAa,gBAAiB,CAACA,GAAU,KAAK,WAAW,EAC9D,KAAK,aAAa,iBAAkB,CAACA,GAAU,KAAK,WAAW,EAC/D,KAAK,aAAa,aAAc,CAACA,GAAU,KAAK,WAAW,EAC3D,KAAK,aAAa,gBAAiB,CAACE,GAAmB,KAAK,WAAW,EACvE,KAAK,aAAa,oBAAqB,CAACD,GAAY,KAAK,WAAW,EACpE,KAAK,aAAa,WAAY,CAACD,GAAU,CAACC,GAAY,KAAK,WAAW,EACtE,KAAK,aAAa,cAAe,CAACD,GAAU,KAAK,WAAW,EAC5D,KAAK,aAAa,WAAY,CAACA,GAAUG,GAAa,KAAK,WAAW,EACtE,KAAK,aAAa,UAAW,CAACH,GAAU,KAAK,aAAe,CAACI,CAAO,EACpE,KAAK,aAAa,UAAW,CAACJ,GAAU,KAAK,aAAe,CAACK,CAAO,EACpE,KAAK,aAAa,UAAW,CAACL,GAAU,KAAK,WAAW,EACxD,KAAK,aAAa,eAAgB,EAAI,EACtC,KAAK,aAAa,gBAAiB,EAAI,CACzC,CASF,EAAG,CACD,IAAK,eACL,MAAO,SAAsBrN,EAAK+N,EAAU,CAC1C,IAAIjO,EAAK,SAAS,eAAe,KAAK,SAASE,CAAG,CAAC,EAC/CF,IAAIA,EAAG,SAAW,CAAC,CAACiO,EAC1B,CAMF,EAAG,CACD,IAAK,2BACL,MAAO,UAAoC,CACpC,KAAK,QAAQ,iBAClB,KAAK,uBAAuB,CAAC,KAAK,aAAa,CACjD,CAOF,EAAG,CACD,IAAK,yBACL,MAAO,SAAgCC,EAAM,CACtC,KAAK,gBACNA,GACF,KAAK,cAAc,UAAU,OAAO,QAAQ,EAC5C,KAAK,cAAc,UAAU,IAAI,QAAQ,EACzC,KAAK,YAAY,UAAU,IAAI,QAAQ,IAEvC,KAAK,cAAc,UAAU,OAAO,QAAQ,EAC5C,KAAK,cAAc,UAAU,IAAI,QAAQ,EACzC,KAAK,YAAY,UAAU,OAAO,QAAQ,GAE9C,CAOF,EAAG,CACD,IAAK,UACL,MAAO,UAAmB,CACxB,IAAIC,EAAU,KAEd,GAAI,CACF,IAAIC,EAAQ,UAAiB,CAC3B,IAAIC,EAAWF,EAAQ,eAAejO,CAAG,GAAK,CAAC,EAC3CF,EAAK,SAAS,eAAemO,EAAQ,SAASjO,CAAG,CAAC,EACtD,GAAI,CAACF,EAAI,MAAO,GAChBqO,EAAS,QAAQ,SAAU7L,EAAG,CAC5B,GAAI,CACFxC,EAAG,oBAAoBwC,EAAE,MAAOA,EAAE,OAAO,CAC3C,MAAY,CAAC,CACf,CAAC,CACH,EACA,QAAStC,KAAO,KAAK,gBAAkB,CAAC,EAClCkO,EAAM,CAEd,MAAY,CAAC,CACb,GAAI,KAAK,UAAW,CAClB,GAAI,CACF,KAAK,OAAO,OAAO,KAAK,SAAS,CACnC,MAAY,CAAC,CACb,KAAK,UAAY,IACnB,CACA,GAAI,KAAK,OAAQ,CACf,GAAI,CACF,KAAK,OAAO,QAAQ,CACtB,MAAY,CAAC,CACb,KAAK,OAAS,KACd,KAAK,SAAW,KAChB,KAAK,sBAAwB,EAC/B,CACA,KAAK,eAAiB,CAAC,CACzB,CACF,CAAC,CAAC,CACJ,EAAE,EAKEpP,EAA8B,UAAY,CAM5C,SAASA,GAAiB,CACxBX,EAAgB,KAAMW,CAAc,EAKpC,KAAK,MAAQ,CAAC,EAKd,KAAK,QAAU,EACjB,CAQA,OAAOT,EAAaS,EAAgB,CAAC,CACnC,IAAK,MACL,MAAQ,UAAY,CAClB,IAAIsP,EAAOxQ,EAA+BrB,EAAa,EAAE,EAAE,SAAS8R,EAASC,EAAa,CACxF,IAAIC,EAAU,KACd,OAAOhS,EAAa,EAAE,EAAE,SAAUiS,EAAW,CAC3C,OAAU,OAAQA,EAAU,EAAG,CAC7B,IAAK,GACH,OAAOA,EAAU,EAAE,EAAG,IAAI,QAAQ,SAAU5E,EAASC,EAAQ,CAE3D0E,EAAQ,MAAM,KAAK,CACjB,GAAID,EACJ,QAAS1E,EACT,OAAQC,CACV,CAAC,EAEI0E,EAAQ,SACXA,EAAQ,aAAa,CAEzB,CAAC,CAAC,CACN,CACF,EAAGF,CAAQ,CACb,CAAC,CAAC,EACF,SAASI,EAAIC,EAAK,CAChB,OAAON,EAAK,MAAM,KAAM,SAAS,CACnC,CACA,OAAOK,CACT,EAAE,CAQJ,EAAG,CACD,IAAK,eACL,MAAQ,UAAY,CAClB,IAAIE,EAAgB/Q,EAA+BrB,EAAa,EAAE,EAAE,SAASqS,GAAW,CACtF,IAAIC,EAAmBC,EAAIlF,EAASC,EAAQkF,EAAQC,EACpD,OAAOzS,EAAa,EAAE,EAAE,SAAU0S,EAAW,CAC3C,OAAU,OAAQA,EAAU,EAAIA,EAAU,EAAG,CAC3C,IAAK,GACH,GAAM,KAAK,MAAM,SAAW,EAAI,CAC9BA,EAAU,EAAI,EACd,KACF,CACA,YAAK,QAAU,GACRA,EAAU,EAAE,CAAC,EACtB,IAAK,GACH,YAAK,QAAU,GACfJ,EAAoB,KAAK,MAAM,MAAM,EAAGC,EAAKD,EAAkB,GAAIjF,EAAUiF,EAAkB,QAAShF,EAASgF,EAAkB,OACnII,EAAU,EAAI,EACdA,EAAU,EAAI,EACPH,EAAG,EACZ,IAAK,GACHC,EAASE,EAAU,EACnBrF,EAAQmF,CAAM,EACdE,EAAU,EAAI,EACd,MACF,IAAK,GACHA,EAAU,EAAI,EACdD,EAAMC,EAAU,EAChBpF,EAAOmF,CAAG,EACZ,IAAK,GACH,KAAK,aAAa,EACpB,IAAK,GACH,OAAOC,EAAU,EAAE,CAAC,CACxB,CACF,EAAGL,EAAU,KAAM,CAAC,CAAC,EAAG,CAAC,CAAC,CAAC,CAC7B,CAAC,CAAC,EACF,SAASM,GAAe,CACtB,OAAOP,EAAc,MAAM,KAAM,SAAS,CAC5C,CACA,OAAOO,CACT,EAAE,CACJ,CAAC,CAAC,CACJ,EAAE,EAKE7J,EAAuBhH,EAK3B,SAASgH,EAAQ8J,EAASC,EAAM,CAC9BjR,EAAgB,KAAMkH,CAAO,EAK7B,KAAK,QAAU8J,EAKf,KAAK,KAAOC,CACd,CAAC,EAKGrQ,EAA8B,UAAY,CAI5C,SAASA,GAAiB,CACxB,IAAIsQ,EAAU,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAI,GAClFlR,EAAgB,KAAMY,CAAc,EACpC,KAAK,QAAU,CAAC,EAChB,KAAK,aAAe,GACpB,KAAK,QAAUsQ,CACjB,CASA,OAAOhR,EAAaU,EAAgB,CAAC,CACnC,IAAK,UACL,MAAO,SAAiBuQ,EAAS,CAE/BA,EAAQ,QAAQ,EAGZ,KAAK,aAAe,KAAK,QAAQ,OAAS,IAC5C,KAAK,QAAU,KAAK,QAAQ,MAAM,EAAG,KAAK,aAAe,CAAC,GAI5D,KAAK,QAAQ,KAAKA,CAAO,EAGrB,KAAK,QAAQ,OAAS,KAAK,QAC7B,KAAK,QAAQ,MAAM,EAEnB,KAAK,cAET,CAOF,EAAG,CACD,IAAK,UACL,MAAO,UAAmB,CACxB,OAAO,KAAK,cAAgB,CAC9B,CAOF,EAAG,CACD,IAAK,UACL,MAAO,UAAmB,CACxB,OAAO,KAAK,aAAe,KAAK,QAAQ,OAAS,CACnD,CAOF,EAAG,CACD,IAAK,OACL,MAAO,UAAgB,CACjB,KAAK,cAAgB,IACvB,KAAK,QAAQ,KAAK,YAAY,EAAE,KAAK,EACrC,KAAK,eAET,CAOF,EAAG,CACD,IAAK,OACL,MAAO,UAAgB,CACjB,KAAK,aAAe,KAAK,QAAQ,OAAS,IAC5C,KAAK,eACL,KAAK,QAAQ,KAAK,YAAY,EAAE,QAAQ,EAE5C,CACF,CAAC,CAAC,CACJ,EAAE,EACF,OAAO5Q,CACT,CAAC",
6
- "names": ["require_image_editor", "__commonJSMin", "exports", "module", "_regenerator", "e", "t", "r", "n", "o", "i", "c", "Generator", "u", "_regeneratorDefine2", "f", "y", "G", "d", "a", "l", "p", "GeneratorFunction", "GeneratorFunctionPrototype", "asyncGeneratorStep", "_asyncToGenerator", "_next", "_throw", "ownKeys", "_objectSpread", "_defineProperty", "_toPropertyKey", "_classCallCheck", "_defineProperties", "_createClass", "_toPrimitive", "_typeof", "root", "factory", "ImageEditor", "options", "mask", "maskIndex", "AnimationQueue", "HistoryManager", "idMap", "defaults", "_this", "canvasEl", "ce", "initialW", "initialH", "cw", "ch", "_this2", "_document$getElementB", "inputEl", "rotLeftBtn", "rotRightBtn", "el", "step", "key", "event", "handler", "file", "_this3", "reader", "_loadImage", "_callee", "base64", "_this4", "imgEl", "loadSrc", "needResize", "ratio", "tw", "th", "_context", "fimg", "imgW", "imgH", "minW", "minH", "fitScale", "_cw", "_ch", "coverScale", "_cw2", "_ch2", "_cw3", "_ch3", "_fitScale", "loadImage", "_x", "dataURL", "res", "rej", "img", "w", "h", "quality", "oc", "ctx", "iw", "ih", "obj", "coords", "br", "originX", "originY", "refPoint", "dx", "dy", "containerW", "containerH", "newW", "newH", "factor", "_this5", "_this6", "targetAbs", "topLeft", "p1", "p2", "deg", "_this7", "degrees", "_this8", "center", "newTopLeft", "_this9", "err", "jsonString", "_this0", "json", "objs", "masks", "max", "m", "_this1", "activeObj", "jsonObj", "after", "before", "executedOnce", "cmd", "Command", "_this10", "config", "shapeType", "cfg", "firstOffset", "left", "top", "resolveValue", "val", "fallback", "percent", "_prev$top", "prev", "prevRight", "_prev$scaleX", "requiredW", "requiredH", "polyPoints", "pt", "normalStyle", "hoverStyle", "active", "_this11", "textObj", "txt", "textOptions", "_this12", "labels", "_this$options$maskLab", "tl", "vx", "vy", "dist", "ux", "uy", "offset", "px", "py", "selected", "_this13", "selectedMask", "_this14", "listEl", "li", "items", "item", "isSelected", "_merge", "_callee2", "merged", "_t", "_context2", "merge", "fileName", "exportImageArea", "link", "_getImageBase", "_callee3", "_this15", "opts", "multiplier", "masksBackup", "imgBr", "sx", "sy", "sw", "sh", "finalBase64", "_args3", "_context3", "resolve", "reject", "fullDataUrl", "sxM", "syM", "swM", "shM", "_oc", "_ctx", "out", "b", "getImageBase64", "_exportImageFile", "_callee4", "_this$options$downsam", "_this$options$exportM", "_this$options$default", "_opts$mergeMask", "mergeMask", "_opts$fileType", "fileType", "_opts$quality", "_opts$multiplier", "_opts$fileName", "typeMapping", "safeFileType", "imageDataUrl", "bstr", "mime", "u8arr", "_args4", "_context4", "durl", "exportImageFile", "_this16", "padding", "width", "height", "cropRect", "onModified", "rec", "_applyCrop", "_callee5", "_this17", "rectBounds", "beforeJson", "croppedBase64", "afterJson", "jsonObj2", "_self", "_t2", "_t3", "_context5", "applyCrop", "scaleEl", "_this$historyManager", "_this$historyManager2", "hasImg", "hasMasks", "hasSelectedMask", "isDefault", "canUndo", "canRedo", "inCrop", "_i", "_Object$keys", "k", "disabled", "show", "_this18", "_loop", "handlers", "_add", "_callee6", "animationFn", "_this19", "_context6", "add", "_x2", "_processQueue", "_callee7", "_this$queue$shift", "fn", "result", "_t4", "_context7", "processQueue", "execute", "undo", "maxSize", "command"]
3
+ "sources": ["../src/esm.js", "../src/image-editor.js"],
4
+ "sourcesContent": ["import fabricModule from 'fabric';\nimport ImageEditor, { setFabric } from './image-editor.js';\n\nconst fabricInstance = fabricModule && (fabricModule.fabric || fabricModule.default || fabricModule);\n\nsetFabric(fabricInstance);\n\nexport { ImageEditor };\nexport default ImageEditor;\n", "/**\n * @file image-editor.js\n * @module image-editor\n * @version 1.2.2\n * @author Ben Situ\n * @license MIT\n * @description Lightweight canvas-based image editor with masking/transform/export support.\n */\n\nlet fabric = null;\n\nfunction getGlobalScope() {\n if (typeof globalThis !== 'undefined') return globalThis;\n if (typeof self !== 'undefined') return self;\n if (typeof window !== 'undefined') return window;\n return null;\n}\n\nfunction getGlobalFabric() {\n const scope = getGlobalScope();\n return scope && scope.fabric ? scope.fabric : null;\n}\n\nexport function setFabric(fabricInstance) {\n fabric = fabricInstance || getGlobalFabric();\n return fabric;\n}\n\nfunction ensureFabric() {\n if (!fabric) setFabric();\n return fabric;\n}\n\n /**\n * ImageEditor\n * \n * A lightweight wrapper around fabric.js providing masking, scaling, rotation,\n * merging/export helpers, and UI integrations for image editing.\n *\n * <b>Note:</b> Requires fabric.js (v5.x) to be loaded on the page before use.\n *\n * <pre>\n * Example usage:\n * const editor = new ImageEditor({ canvasWidth: 1024, canvasHeight: 768 });\n * editor.init();\n * </pre>\n *\n * @class ImageEditor\n * @classdesc Fabric.js-based image editor with simple mask, transform, export and UI features.\n *\n * @param {Object} [options={}] - Customization options to override defaults.\n * @param {number} [options.canvasWidth=800] - The initial canvas width in pixels.\n * @param {number} [options.canvasHeight=600] - The initial canvas height in pixels.\n * @param {string} [options.backgroundColor='transparent'] - The canvas background color.\n * @param {number} [options.animationDuration=300] - Duration in ms for scale/rotate animations.\n * @param {number} [options.minScale=0.1] - Minimum image scaling factor.\n * @param {number} [options.maxScale=5.0] - Maximum image scaling factor.\n * @param {number} [options.scaleStep=0.05] - Scale increment/decrement per step.\n * @param {number} [options.rotationStep=90] - Rotation step in degrees.\n * @param {boolean} [options.expandCanvasToImage=true] - If true, expands the canvas to fit image/mask.\n * @param {boolean} [options.fitImageToCanvas=false] - If true, fits loaded image inside canvas.\n * @param {boolean} [options.coverImageToCanvas=false] - If true, scales image to cover the visible canvas viewport.\n * @param {boolean} [options.downsampleOnLoad=true] - Whether to downsample very large images on load.\n * @param {number} [options.downsampleMaxWidth=4000] - Max width for downsampling.\n * @param {number} [options.downsampleMaxHeight=3000] - Max height for downsampling.\n * @param {number} [options.downsampleQuality=0.92] - JPEG quality for downsampling/export.\n * @param {number} [options.exportMultiplier=1] - Scale output image by this multiplier on export.\n * @param {boolean} [options.exportImageAreaByDefault=true] - Export only the image area (clipped to masks).\n * @param {number} [options.defaultMaskWidth=50] - Default width of new mask rectangles.\n * @param {number} [options.defaultMaskHeight=80] - Default height of new masks.\n * @param {boolean} [options.maskRotatable=false] - If true, masks can be rotated.\n * @param {boolean} [options.maskLabelOnSelect=true] - Show label on selected mask.\n * @param {number} [options.maskLabelOffset=3] - Offset for mask labels from top-left corner.\n * @param {string} [options.maskName='mask'] - Prefix for mask names/labels.\n * @param {boolean} [options.showPlaceholder=true] - If true, shows placeholder when no image is loaded.\n * @param {string|null} [options.initialImageBase64=null] - Base64 string to auto-load as initial image, if any.\n * @param {string} [options.defaultDownloadFileName='edited_image.jpg'] - Default file name for downloads.\n * @param {function} [options.onImageLoaded] - Optional callback to invoke after an image loads.\n * @param {function} [options.onError] - Optional callback for recoverable internal errors.\n * @param {function} [options.onWarning] - Optional callback for recoverable internal warnings.\n * \n * @constructor\n */\n class ImageEditor {\n constructor(options = {}) {\n // Default options (can be overridden via ctor param)\n const defaultLabel = {\n getText: (mask) => mask.maskName,\n textOptions: {\n fontSize: 12,\n fill: '#fff',\n backgroundColor: 'rgba(0,0,0,0.7)',\n padding: 2,\n fontFamily: 'monospace',\n fontWeight: 'bold',\n selectable: false,\n evented: false,\n originX: 'left',\n originY: 'top'\n }\n };\n const defaultCrop = {\n minWidth: 100,\n minHeight: 100,\n padding: 10,\n hideMasksDuringCrop: true,\n preserveMasksAfterCrop: false,\n allowRotationOfCropRect: false\n };\n const userLabel = options.label || {};\n const userCrop = options.crop || {};\n this.options = {\n canvasWidth: 800,\n canvasHeight: 600,\n backgroundColor: 'transparent',\n\n animationDuration: 300,\n minScale: 0.1,\n maxScale: 5.0,\n scaleStep: 0.05,\n rotationStep: 90,\n\n expandCanvasToImage: true,\n fitImageToCanvas: false,\n coverImageToCanvas: false,\n\n downsampleOnLoad: true,\n downsampleMaxWidth: 4000,\n downsampleMaxHeight: 3000,\n downsampleQuality: 0.92,\n\n exportMultiplier: 1,\n exportImageAreaByDefault: true,\n\n defaultMaskWidth: 50,\n defaultMaskHeight: 80,\n maskRotatable: false,\n maskLabelOnSelect: true,\n maskLabelOffset: 3,\n maskName: 'mask',\n\n groupSelection: false,\n\n showPlaceholder: true,\n initialImageBase64: null, // Provide a base64 'data:image/...' string here if you want auto-load\n\n defaultDownloadFileName: 'edited_image.jpg',\n onError: null,\n onWarning: null,\n\n ...options,\n label: {\n ...defaultLabel,\n ...userLabel,\n textOptions: {\n ...defaultLabel.textOptions,\n ...(userLabel.textOptions || {})\n }\n },\n crop: {\n ...defaultCrop,\n ...userCrop\n }\n };\n\n // Verify that fabric.js is present\n this._fabricLoaded = !!ensureFabric();\n if (!this._fabricLoaded) {\n this._reportError('fabric.js is not loaded. Please include fabric.js first. Initialization will be aborted.');\n }\n\n // Runtime state\n this.canvas = null;\n this.canvasElement = null;\n this.containerElement = null;\n this.placeholderElement = null;\n\n this.originalImage = null; // fabric.Image\n this.baseImageScale = 1;\n this.currentScale = 1;\n this.currentRotation = 0;\n this.maskCounter = 0;\n this.isAnimating = false;\n this.elements = {};\n this.isImageLoadedToCanvas = false;\n this.maxHistorySize = 50;\n\n this._handlersByElementKey = {};\n\n this._lastMask = null;\n this._lastMaskInitialLeft = null;\n this._lastMaskInitialTop = null;\n this._lastMaskInitialWidth = null;\n this._lastSnapshot = null;\n\n this._cropMode = false;\n this._cropRect = null;\n this._cropHandlers = [];\n this._cropPrevEvented = null;\n this._prevSelectionSetting = undefined;\n this._containerOriginalOverflow = undefined;\n\n this.onImageLoaded = typeof options.onImageLoaded === 'function' ? options.onImageLoaded : null;\n\n this.animQueue = new AnimationQueue();\n this.historyManager = new HistoryManager(this.maxHistorySize);\n }\n\n /**\n * @deprecated Use canvasElement instead.\n */\n get canvasEl() {\n return this.canvasElement;\n }\n\n set canvasEl(value) {\n this.canvasElement = value;\n }\n\n /**\n * @deprecated Use containerElement instead.\n */\n get containerEl() {\n return this.containerElement;\n }\n\n set containerEl(value) {\n this.containerElement = value;\n }\n\n /**\n * @deprecated Use placeholderElement instead.\n */\n get placeholderEl() {\n return this.placeholderElement;\n }\n\n set placeholderEl(value) {\n this.placeholderElement = value;\n }\n\n /**\n * Initializes the editor, binds to DOM elements, sets up event handlers,\n * and (optionally) loads an initial image.\n * Use this method to set up the editor UI before interacting with it.\n *\n * @param {Object} [idMap={}] - Optional mapping from logical element names to actual DOM element IDs.\n * Supported keys include: canvas, canvasContainer, imgPlaceholder, scaleRate, rotationLeftInput, rotationRightInput,\n * rotateLeftBtn, rotateRightBtn, addMaskBtn, removeMaskBtn, removeAllMasksBtn, mergeBtn, downloadBtn, maskList,\n * zoomInBtn, zoomOutBtn, resetBtn, imageInput. Unknown keys are ignored.\n *\n * @returns {void}\n *\n * @public\n *\n * @example\n * editor.init({\n * canvas: 'myFabricCanvasId',\n * downloadBtn: 'myDownloadButtonId'\n * });\n */\n init(idMap = {}) {\n if (!this._fabricLoaded) return;\n\n const defaults = {\n canvas: 'fabricCanvas',\n canvasContainer: null, // Pass an ID here if you have a scrollable viewport container\n imgPlaceholder: 'imgPlaceholder',\n scaleRate: 'scaleRate',\n rotationLeftInput: 'rotationLeftInput',\n rotationRightInput: 'rotationRightInput',\n rotateLeftBtn: 'rotateLeftBtn',\n rotateRightBtn: 'rotateRightBtn',\n addMaskBtn: 'addMaskBtn',\n removeMaskBtn: 'removeMaskBtn',\n removeAllMasksBtn: 'removeAllMasksBtn',\n mergeBtn: 'mergeBtn',\n downloadBtn: 'downloadBtn',\n maskList: 'maskList',\n zoomInBtn: 'zoomInBtn',\n zoomOutBtn: 'zoomOutBtn',\n resetBtn: 'resetBtn',\n undoBtn: 'undoBtn',\n redoBtn: 'redoBtn',\n imageInput: 'imageInput',\n cropBtn: 'cropBtn',\n applyCropBtn: 'applyCropBtn',\n cancelCropBtn: 'cancelCropBtn'\n };\n\n this.elements = { ...defaults, ...idMap };\n\n this._initCanvas();\n this._bindEvents();\n this._updateInputs();\n this._updateMaskList();\n this._updateUI();\n\n // Auto-load initial image if provided\n if (this.options.initialImageBase64) {\n this.loadImage(this.options.initialImageBase64);\n } else {\n this._updatePlaceholderStatus();\n }\n }\n\n _reportError(message, error = null) {\n const handler = this.options && this.options.onError;\n if (typeof handler !== 'function') return;\n\n try {\n handler(error, message);\n } catch {\n // Ignore observer failures so editor recovery paths remain stable.\n }\n }\n\n _reportWarning(message, error = null) {\n const handler = this.options && this.options.onWarning;\n if (typeof handler !== 'function') return;\n\n try {\n handler(error, message);\n } catch {\n // Ignore observer failures so editor recovery paths remain stable.\n }\n }\n\n /**\n * Canvas setup helpers\n * @private\n */\n _initCanvas() {\n const canvasElement = document.getElementById(this.elements.canvas);\n if (!canvasElement) throw new Error('Canvas is not found: ' + this.elements.canvas);\n this.canvasElement = canvasElement;\n\n // Decide which element acts as \"viewport\" (for width/height fallback)\n if (this.elements.canvasContainer) {\n const containerElement = document.getElementById(this.elements.canvasContainer);\n this.containerElement = containerElement || canvasElement.parentElement;\n } else {\n this.containerElement = canvasElement.parentElement;\n }\n\n this.placeholderElement = document.getElementById(this.elements.imgPlaceholder) || null;\n\n // Initial size \u2014 take container size if available\n let initialWidth = this.options.canvasWidth;\n let initialHeight = this.options.canvasHeight;\n if (this.containerElement) {\n const containerWidth = Math.floor(this.containerElement.clientWidth);\n const containerHeight = Math.floor(this.containerElement.clientHeight);\n if (containerWidth > 0 && containerHeight > 0) {\n initialWidth = containerWidth;\n initialHeight = containerHeight;\n }\n }\n\n this.canvas = new fabric.Canvas(canvasElement, {\n width: initialWidth,\n height: initialHeight,\n backgroundColor: this.options.backgroundColor,\n selection: this.options.groupSelection,\n preserveObjectStacking: true\n });\n\n // Fabric event wiring\n this.canvas.on('selection:created', (event) => this._handleSelectionChanged(event.selected));\n this.canvas.on('selection:updated', (event) => this._handleSelectionChanged(event.selected));\n this.canvas.on('selection:cleared', () => this._handleSelectionChanged([]));\n this.canvas.on('object:moving', (event) => { if (event.target && event.target.maskId) this._syncMaskLabel(event.target); });\n this.canvas.on('object:scaling', (event) => { if (event.target && event.target.maskId) this._syncMaskLabel(event.target); });\n this.canvas.on('object:rotating', (event) => { if (event.target && event.target.maskId) this._syncMaskLabel(event.target); });\n this.canvas.on('object:modified', (event) => this._handleObjectModified(event.target));\n\n // Avoid inline-element whitespace artefacts\n this.canvasElement.style.display = 'block';\n }\n\n _handleObjectModified(target) {\n const masks = this._getModifiedMasks(target);\n if (!masks.length) return;\n masks.forEach(mask => {\n if (typeof mask.setCoords === 'function') mask.setCoords();\n this._syncMaskLabel(mask);\n this._expandCanvasToFitObject(mask);\n });\n this.saveState();\n }\n\n _getModifiedMasks(target) {\n if (!target) return [];\n if (target.maskId) return [target];\n\n const objects = typeof target.getObjects === 'function' ? target.getObjects() : [];\n\n return Array.isArray(objects) ? objects.filter(object => object && object.maskId) : [];\n }\n\n _syncContainerOverflow() {\n if (!this.containerElement || !this.containerElement.style) return;\n if (this._containerOriginalOverflow === undefined) {\n this._containerOriginalOverflow = this.containerElement.style.overflow || '';\n }\n\n if (this.options.coverImageToCanvas) {\n const shouldResetScroll = !this.isImageLoadedToCanvas;\n this.containerElement.style.overflow = 'scroll';\n if (shouldResetScroll) {\n this.containerElement.scrollLeft = 0;\n this.containerElement.scrollTop = 0;\n }\n } else if (this.options.fitImageToCanvas) {\n this.containerElement.style.overflow = 'auto';\n this.containerElement.scrollLeft = 0;\n this.containerElement.scrollTop = 0;\n } else {\n this.containerElement.style.overflow = this._containerOriginalOverflow;\n }\n }\n\n /** \n * DOM / UI bindings\n * @private\n */\n _bindEvents() {\n // Click anywhere on the upload area opens the native file dialog\n this._bindIfExists('uploadArea', 'click', () => {\n const uploadAreaElement = document.getElementById(this.elements.uploadArea);\n if (this._isElementDisabled(uploadAreaElement)) return;\n document.getElementById(this.elements.imageInput)?.click();\n });\n // File-input change\n this._bindIfExists('imageInput', 'change', (event) => {\n const file = event.target.files && event.target.files[0];\n if (file) this._loadImageFile(file);\n });\n // Zoom & reset\n this._bindIfExists('zoomInBtn', 'click', () => this.scaleImage(this.currentScale + this.options.scaleStep));\n this._bindIfExists('zoomOutBtn', 'click', () => this.scaleImage(this.currentScale - this.options.scaleStep));\n this._bindIfExists('resetBtn', 'click', () => { this.resetImageTransform(); });\n // Mask management\n this._bindIfExists('addMaskBtn', 'click', () => this.createMask());\n this._bindIfExists('removeMaskBtn', 'click', () => this.removeSelectedMask());\n this._bindIfExists('removeAllMasksBtn', 'click', () => this.removeAllMasks());\n // Merge + download\n this._bindIfExists('mergeBtn', 'click', () => this.mergeMasks());\n this._bindIfExists('downloadBtn', 'click', () => this.downloadImage());\n // Undo + Redo\n this._bindIfExists('undoBtn', 'click', () => this.undo());\n this._bindIfExists('redoBtn', 'click', () => this.redo());\n\n // Rotation buttons (step can be overridden by two input fields)\n this._bindIfExists('rotateLeftBtn', 'click', () => {\n const rotationInputElement = document.getElementById(this.elements.rotationLeftInput);\n let step = this.options.rotationStep;\n if (rotationInputElement) {\n const parsedStep = parseFloat(rotationInputElement.value);\n if (!isNaN(parsedStep)) step = parsedStep;\n }\n this.rotateImage(this.currentRotation - step);\n });\n this._bindIfExists('rotateRightBtn', 'click', () => {\n const rotationInputElement = document.getElementById(this.elements.rotationRightInput);\n let step = this.options.rotationStep;\n if (rotationInputElement) {\n const parsedStep = parseFloat(rotationInputElement.value);\n if (!isNaN(parsedStep)) step = parsedStep;\n }\n this.rotateImage(this.currentRotation + step);\n });\n\n // Crop bindings (optional: bound only if element IDs exist in elements)\n this._bindIfExists('cropBtn', 'click', () => this.enterCropMode());\n this._bindIfExists('applyCropBtn', 'click', () => { this.applyCrop().catch(error => this._reportError('applyCrop failed', error)); });\n this._bindIfExists('cancelCropBtn', 'click', () => this.cancelCrop());\n }\n\n /** \n * Event binding element check\n * \n * @param {*} eventName\n * @param {*} handler \n * @param {*} key \n * @private\n */\n _bindIfExists(key, eventName, handler) {\n const element = document.getElementById(this.elements[key]);\n if (element) {\n element.addEventListener(eventName, handler);\n this._handlersByElementKey = this._handlersByElementKey || {};\n if (!this._handlersByElementKey[key]) this._handlersByElementKey[key] = [];\n this._handlersByElementKey[key].push({ eventName, handler });\n }\n }\n\n /** \n * Image loading helpers\n * \n * @param {File} file \n * @private\n */\n _loadImageFile(file) {\n if (!file || !file.type.startsWith('image/')) return;\n const reader = new FileReader();\n reader.onload = (event) => this.loadImage(event.target.result);\n reader.onerror = (event) => { this._reportError('Image file could not be read', event); };\n reader.readAsDataURL(file);\n }\n\n /**\n * Load a base64 encoded image string into fabric.\n * @async\n * @param {String} imageBase64\n */\n async loadImage(imageBase64) {\n if (!this._fabricLoaded) return;\n if (!this.canvas) return;\n if (!imageBase64 || typeof imageBase64 !== 'string' || !imageBase64.startsWith('data:image/')) return;\n\n this._setPlaceholderVisible(false);\n this._syncContainerOverflow();\n\n const imageElement = await this._createImageElement(imageBase64);\n\n let loadSource = imageBase64;\n if (this.options.downsampleOnLoad) {\n const shouldResize =\n imageElement.naturalWidth > this.options.downsampleMaxWidth ||\n imageElement.naturalHeight > this.options.downsampleMaxHeight;\n if (shouldResize) {\n const ratio = Math.min(\n this.options.downsampleMaxWidth / imageElement.naturalWidth,\n this.options.downsampleMaxHeight / imageElement.naturalHeight\n );\n const targetWidth = Math.round(imageElement.naturalWidth * ratio);\n const targetHeight = Math.round(imageElement.naturalHeight * ratio);\n loadSource = this._resampleImageToDataURL(imageElement, targetWidth, targetHeight, this.options.downsampleQuality);\n }\n }\n\n // Create fabric.Image from URL\n return new Promise((resolve, reject) => {\n fabric.Image.fromURL(loadSource, (fabricImage) => {\n try {\n if (!fabricImage) throw new Error('Image could not be loaded');\n\n this.canvas.discardActiveObject();\n this._hideAllMaskLabels();\n this.canvas.clear();\n this.canvas.setBackgroundColor(this.options.backgroundColor, this.canvas.renderAll.bind(this.canvas));\n\n fabricImage.set({ originX: 'left', originY: 'top', selectable: false, evented: false });\n\n const imageWidth = fabricImage.width;\n const imageHeight = fabricImage.height;\n\n const viewport = this._getContainerViewportSize();\n const minWidth = viewport.width;\n const minHeight = viewport.height;\n\n if (this.options.fitImageToCanvas) {\n // Fit into current canvas (shrink only) and ensure canvas does not exceed container\n const canvasWidth = Math.max(1, Math.min(this.options.canvasWidth, minWidth) - 1)\n const canvasHeight = Math.max(1, Math.min(this.options.canvasHeight, minHeight) - 1);\n this._setCanvasSizeInt(canvasWidth, canvasHeight);\n const fitScale = Math.min(canvasWidth / imageWidth, canvasHeight / imageHeight, 1);\n fabricImage.set({ left: 0, top: 0 });\n fabricImage.scale(fitScale);\n this.baseImageScale = fabricImage.scaleX || 1;\n } else if (this.options.coverImageToCanvas) {\n const layout = this._calculateCoverCanvasLayout(imageWidth, imageHeight);\n this._setCanvasSizeInt(layout.canvasWidth, layout.canvasHeight);\n fabricImage.set({ left: 0, top: 0 });\n fabricImage.scale(layout.scale);\n this.baseImageScale = fabricImage.scaleX || 1;\n } else if (this.options.expandCanvasToImage) {\n // Expand canvas so that it fully contains the image\n const canvasWidth = Math.max(minWidth, Math.floor(imageWidth));\n const canvasHeight = Math.max(minHeight, Math.floor(imageHeight));\n this._setCanvasSizeInt(canvasWidth, canvasHeight);\n fabricImage.set({ left: 0, top: 0 });\n fabricImage.scale(1);\n this.baseImageScale = 1;\n } else {\n // Keep existing canvas size and center the image\n const canvasWidth = Math.max(this.options.canvasWidth, minWidth);\n const canvasHeight = Math.max(this.options.canvasHeight, minHeight);\n this._setCanvasSizeInt(canvasWidth, canvasHeight);\n const fitScale = Math.min(canvasWidth / imageWidth, canvasHeight / imageHeight, 1);\n fabricImage.set({ left: 0, top: 0 });\n fabricImage.scale(fitScale);\n this.baseImageScale = fabricImage.scaleX || 1;\n }\n // Put the image onto the canvas\n this.originalImage = fabricImage;\n this.canvas.add(fabricImage);\n this.canvas.sendToBack(fabricImage);\n\n // Reset mask placement memory\n this._lastMask = null;\n this._lastMaskInitialLeft = null;\n this._lastMaskInitialTop = null;\n this._lastMaskInitialWidth = null;\n\n this.maskCounter = 0;\n this.currentScale = 1;\n this.currentRotation = 0;\n\n this._updateInputs();\n this._updateMaskList();\n this.isImageLoadedToCanvas = true;\n this._updateUI();\n this.canvas.renderAll();\n try {\n this._lastSnapshot = this._serializeCanvasState();\n } catch (error) {\n this._reportWarning('loadImage: failed to capture initial canvas snapshot', error);\n }\n\n if (typeof this.onImageLoaded === 'function') {\n this.onImageLoaded();\n }\n\n resolve();\n } catch (error) {\n reject(error);\n }\n }, { crossOrigin: 'anonymous' });\n });\n }\n\n /**\n * Checks whether there is a loaded image on the current canvas.\n * @returns {boolean} true if loaded, false if not\n */\n isImageLoaded() {\n const fabricInstance = ensureFabric();\n return !!(\n this.originalImage &&\n fabricInstance &&\n this.originalImage instanceof fabricInstance.Image &&\n this.originalImage.width > 0 &&\n this.originalImage.height > 0\n );\n }\n\n /**\n * Creates an HTMLImageElement from a given data URL.\n * \n * @param {string} dataUrl - A data URL representing the image (e.g., \"data:image/png;base64,...\").\n * @returns {Promise<HTMLImageElement>} A promise that resolves to the created image element when loaded, or rejects on error.\n * @private\n */\n _createImageElement(dataUrl) {\n return new Promise((resolve, reject) => {\n const imageElement = new Image();\n imageElement.onload = () => {\n imageElement.onload = null;\n imageElement.onerror = null;\n resolve(imageElement);\n };\n imageElement.onerror = (error) => {\n imageElement.onload = null;\n imageElement.onerror = null;\n reject(error);\n };\n imageElement.src = dataUrl;\n });\n }\n\n /**\n * Resamples the given image element to a new width and height and returns the result as a JPEG data URL.\n * \n * @param {HTMLImageElement} imageElement - The image element to resample.\n * @param {number} targetWidth - Target width (in pixels) for the resampled image.\n * @param {number} targetHeight - Target height (in pixels) for the resampled image.\n * @param {number} [quality=0.92] - JPEG image quality between 0 and 1 (optional, default 0.92).\n * @returns {string} A data URL representing the resampled image as JPEG.\n * @private\n */\n _resampleImageToDataURL(imageElement, targetWidth, targetHeight, quality = 0.92) {\n const offscreenCanvas = document.createElement('canvas');\n offscreenCanvas.width = targetWidth;\n offscreenCanvas.height = targetHeight;\n const context = offscreenCanvas.getContext('2d');\n context.drawImage(imageElement, 0, 0, imageElement.naturalWidth, imageElement.naturalHeight, 0, 0, targetWidth, targetHeight);\n return offscreenCanvas.toDataURL('image/jpeg', quality);\n }\n\n /** \n * Sets canvas size to integer width and height values to prevent scrollbars due to sub-pixel rendering.\n * Also updates the corresponding style attributes.\n * \n * @param {number} w - Canvas width (in pixels).\n * @param {number} h - Canvas height (in pixels).\n * @private\n */\n _setCanvasSizeInt(w, h) {\n const iw = Math.max(1, Math.round(Number(w) || 1));\n const ih = Math.max(1, Math.round(Number(h) || 1));\n // Set fabric internal and also style attributes to keep DOM consistent\n this.canvas.setWidth(iw);\n this.canvas.setHeight(ih);\n if (typeof this.canvas.calcOffset === 'function') this.canvas.calcOffset();\n // Keep DOM element in sync (avoid fractional CSS pixels)\n if (this.canvasElement) {\n this.canvasElement.style.width = iw + 'px';\n this.canvasElement.style.height = ih + 'px';\n this.canvasElement.style.maxWidth = 'none';\n }\n }\n\n _ceilCanvasDimension(value) {\n const numericValue = Number(value) || 0;\n const roundedValue = Math.round(numericValue);\n if (Math.abs(numericValue - roundedValue) < 0.01) return roundedValue;\n return Math.ceil(numericValue);\n }\n\n _getContainerViewportSize() {\n if (!this.containerElement) {\n return {\n width: Math.max(1, Math.floor(this.options.canvasWidth || 1)),\n height: Math.max(1, Math.floor(this.options.canvasHeight || 1))\n };\n }\n\n if (this._hasFixedContainerScrollbars()) {\n return {\n width: Math.max(1, Math.floor(this.containerElement.clientWidth || this.options.canvasWidth || 1)),\n height: Math.max(1, Math.floor(this.containerElement.clientHeight || this.options.canvasHeight || 1))\n };\n }\n\n const previousOverflow = this.containerElement.style.overflow;\n this.containerElement.style.overflow = 'hidden';\n\n const width = Math.max(1, Math.floor(this.containerElement.clientWidth || this.options.canvasWidth || 1));\n const height = Math.max(1, Math.floor(this.containerElement.clientHeight || this.options.canvasHeight || 1));\n\n this.containerElement.style.overflow = previousOverflow;\n return { width, height };\n }\n\n _hasFixedContainerScrollbars() {\n if (!this.containerElement) return false;\n const inlineOverflow = this.containerElement.style.overflow;\n const inlineOverflowX = this.containerElement.style.overflowX;\n const inlineOverflowY = this.containerElement.style.overflowY;\n let computedOverflow = '';\n let computedOverflowX = '';\n let computedOverflowY = '';\n\n if (typeof window !== 'undefined' && typeof window.getComputedStyle === 'function') {\n const style = window.getComputedStyle(this.containerElement);\n computedOverflow = style.overflow;\n computedOverflowX = style.overflowX;\n computedOverflowY = style.overflowY;\n }\n\n return [inlineOverflow, inlineOverflowX, inlineOverflowY, computedOverflow, computedOverflowX, computedOverflowY]\n .some(value => value === 'scroll');\n }\n\n _getScrollbarSize() {\n if (typeof document === 'undefined' || !document.createElement || !document.body) {\n return { width: 0, height: 0 };\n }\n\n const probe = document.createElement('div');\n probe.style.position = 'absolute';\n probe.style.visibility = 'hidden';\n probe.style.overflow = 'scroll';\n probe.style.width = '100px';\n probe.style.height = '100px';\n probe.style.top = '-9999px';\n document.body.appendChild(probe);\n\n const width = Math.max(0, probe.offsetWidth - probe.clientWidth);\n const height = Math.max(0, probe.offsetHeight - probe.clientHeight);\n document.body.removeChild(probe);\n\n return { width, height };\n }\n\n _getScrollSafetyMargin() {\n return 2;\n }\n\n _getScrollableCanvasSize(contentWidth, contentHeight, viewport = this._getContainerViewportSize()) {\n if (this._hasFixedContainerScrollbars()) {\n const safetyMargin = this._getScrollSafetyMargin();\n const safeWidth = Math.max(1, viewport.width - safetyMargin);\n const safeHeight = Math.max(1, viewport.height - safetyMargin);\n return {\n width: contentWidth > viewport.width + 0.5 ? this._ceilCanvasDimension(contentWidth) : safeWidth,\n height: contentHeight > viewport.height + 0.5 ? this._ceilCanvasDimension(contentHeight) : safeHeight,\n viewportWidth: viewport.width,\n viewportHeight: viewport.height,\n hasHorizontal: true,\n hasVertical: true\n };\n }\n\n const scrollbar = this._getScrollbarSize();\n let hasVertical = false;\n let hasHorizontal = false;\n let effectiveWidth = viewport.width;\n let effectiveHeight = viewport.height;\n\n for (let i = 0; i < 4; i += 1) {\n effectiveWidth = Math.max(1, viewport.width - (hasVertical ? scrollbar.width : 0));\n effectiveHeight = Math.max(1, viewport.height - (hasHorizontal ? scrollbar.height : 0));\n\n const nextHasVertical = contentHeight > effectiveHeight + 0.5;\n const nextHasHorizontal = contentWidth > effectiveWidth + 0.5;\n\n if (nextHasVertical === hasVertical && nextHasHorizontal === hasHorizontal) break;\n hasVertical = nextHasVertical;\n hasHorizontal = nextHasHorizontal;\n }\n\n effectiveWidth = Math.max(1, viewport.width - (hasVertical ? scrollbar.width : 0));\n effectiveHeight = Math.max(1, viewport.height - (hasHorizontal ? scrollbar.height : 0));\n\n return {\n width: hasHorizontal ? this._ceilCanvasDimension(contentWidth) : effectiveWidth,\n height: hasVertical ? this._ceilCanvasDimension(contentHeight) : effectiveHeight,\n viewportWidth: effectiveWidth,\n viewportHeight: effectiveHeight,\n hasHorizontal,\n hasVertical\n };\n }\n\n _calculateCoverCanvasLayout(imageWidth, imageHeight) {\n const viewport = this._getContainerViewportSize();\n\n if (this._hasFixedContainerScrollbars()) {\n const safetyMargin = this._getScrollSafetyMargin();\n const targetWidth = Math.max(1, viewport.width - safetyMargin);\n const targetHeight = Math.max(1, viewport.height - safetyMargin);\n const scale = Math.min(1, Math.max(targetWidth / imageWidth, targetHeight / imageHeight));\n const contentWidth = imageWidth * scale;\n const contentHeight = imageHeight * scale;\n const canvasSize = this._getScrollableCanvasSize(contentWidth, contentHeight, viewport);\n return {\n scale,\n canvasWidth: canvasSize.width,\n canvasHeight: canvasSize.height\n };\n }\n\n const scrollbar = this._getScrollbarSize();\n let hasVertical = false;\n let hasHorizontal = false;\n let scale = 1;\n let contentWidth = imageWidth;\n let contentHeight = imageHeight;\n let effectiveWidth = viewport.width;\n let effectiveHeight = viewport.height;\n\n for (let i = 0; i < 4; i += 1) {\n effectiveWidth = Math.max(1, viewport.width - (hasVertical ? scrollbar.width : 0));\n effectiveHeight = Math.max(1, viewport.height - (hasHorizontal ? scrollbar.height : 0));\n scale = Math.min(1, Math.max(effectiveWidth / imageWidth, effectiveHeight / imageHeight));\n contentWidth = imageWidth * scale;\n contentHeight = imageHeight * scale;\n\n const nextHasVertical = contentHeight > effectiveHeight + 0.5;\n const nextHasHorizontal = contentWidth > effectiveWidth + 0.5;\n\n if (nextHasVertical === hasVertical && nextHasHorizontal === hasHorizontal) break;\n hasVertical = nextHasVertical;\n hasHorizontal = nextHasHorizontal;\n }\n\n const canvasSize = this._getScrollableCanvasSize(contentWidth, contentHeight, viewport);\n return {\n scale,\n canvasWidth: canvasSize.width,\n canvasHeight: canvasSize.height\n };\n }\n\n _getStateProperties() {\n return [\n 'maskId',\n 'maskName',\n 'maskLabel',\n 'isCropRect',\n 'originalAlpha',\n 'originalStroke',\n 'originalStrokeWidth',\n 'selectable',\n 'evented',\n 'hasControls',\n 'lockRotation',\n 'borderColor',\n 'cornerColor',\n 'cornerSize',\n 'transparentCorners',\n 'strokeUniform',\n 'strokeDashArray'\n ];\n }\n\n _getMaskNormalStyle(mask) {\n const strokeWidth = Number(mask && mask.originalStrokeWidth);\n const opacity = Number(mask && mask.originalAlpha);\n const style = {\n stroke: (mask && mask.originalStroke) || '#ccc',\n strokeWidth: Number.isFinite(strokeWidth) ? strokeWidth : 1\n };\n if (Number.isFinite(opacity)) style.opacity = opacity;\n return style;\n }\n\n _withNormalizedMaskStyles(callback) {\n if (!this.canvas) return callback();\n const masks = this.canvas.getObjects().filter(object => object.maskId);\n const maskStyleBackups = masks.map(mask => ({\n object: mask,\n stroke: mask.stroke,\n strokeWidth: mask.strokeWidth,\n opacity: mask.opacity\n }));\n\n try {\n masks.forEach(mask => {\n mask.set(this._getMaskNormalStyle(mask));\n });\n return callback();\n } finally {\n maskStyleBackups.forEach(backup => {\n try {\n backup.object.set({\n stroke: backup.stroke,\n strokeWidth: backup.strokeWidth,\n opacity: backup.opacity\n });\n } catch (error) { void error; }\n });\n }\n }\n\n _restoreMaskControls(mask) {\n if (!mask) return;\n\n const cornerSize = Number(mask.cornerSize);\n mask.set({\n selectable: mask.selectable !== false,\n evented: mask.evented !== false,\n hasControls: mask.hasControls !== false,\n lockRotation: typeof mask.lockRotation === 'boolean' ? mask.lockRotation : !this.options.maskRotatable,\n borderColor: mask.borderColor || 'red',\n cornerColor: mask.cornerColor || 'black',\n cornerSize: Number.isFinite(cornerSize) ? cornerSize : 8,\n transparentCorners: mask.transparentCorners === true,\n strokeUniform: mask.strokeUniform !== false\n });\n if (typeof mask.setCoords === 'function') mask.setCoords();\n }\n\n _serializeCanvasState() {\n if (!this.canvas) return null;\n return this._withNormalizedMaskStyles(() => {\n const jsonObject = this.canvas.toJSON(this._getStateProperties());\n if (Array.isArray(jsonObject.objects)) {\n jsonObject.objects = jsonObject.objects.filter(object => !object.isCropRect && !object.maskLabel);\n }\n return JSON.stringify(jsonObject);\n });\n }\n\n _normalizeQuality(quality) {\n const numericQuality = Number(quality);\n if (!Number.isFinite(numericQuality)) return this.options.downsampleQuality ?? 0.92;\n return Math.max(0, Math.min(1, numericQuality));\n }\n\n _normalizeImageFormat(format) {\n const typeMapping = {\n 'jpeg': 'jpeg',\n 'jpg': 'jpeg',\n 'image/jpeg': 'jpeg',\n 'png': 'png',\n 'image/png': 'png',\n 'webp': 'webp',\n 'image/webp': 'webp'\n };\n return typeMapping[String(format || 'jpeg').toLowerCase()] || 'jpeg';\n }\n\n _getClampedCanvasRegion(bounds, options = {}) {\n const canvasWidth = Math.max(1, Math.round(this.canvas.getWidth()));\n const canvasHeight = Math.max(1, Math.round(this.canvas.getHeight()));\n const left = Number(bounds.left) || 0;\n const top = Number(bounds.top) || 0;\n const width = Math.max(0, Number(bounds.width) || 0);\n const height = Math.max(0, Number(bounds.height) || 0);\n const includePartialPixels = options.includePartialPixels !== false;\n const roundEnd = includePartialPixels ? Math.ceil : Math.floor;\n const sourceX = Math.min(canvasWidth - 1, Math.max(0, Math.floor(left)));\n const sourceY = Math.min(canvasHeight - 1, Math.max(0, Math.floor(top)));\n const endX = Math.min(canvasWidth, Math.max(sourceX + 1, roundEnd(left + width)));\n const endY = Math.min(canvasHeight, Math.max(sourceY + 1, roundEnd(top + height)));\n\n return {\n sx: sourceX,\n sy: sourceY,\n sw: Math.max(1, endX - sourceX),\n sh: Math.max(1, endY - sourceY)\n };\n }\n\n async _cropDataUrl(dataUrl, sourceX, sourceY, sourceWidth, sourceHeight, multiplier, format = 'jpeg', quality = 0.92) {\n return new Promise((resolve, reject) => {\n const imageElement = new Image();\n imageElement.onload = () => {\n try {\n const safeMultiplier = Math.max(1, Number(multiplier) || 1);\n const scaledSourceX = Math.round(sourceX * safeMultiplier);\n const scaledSourceY = Math.round(sourceY * safeMultiplier);\n const scaledSourceWidth = Math.max(1, Math.round(sourceWidth * safeMultiplier));\n const scaledSourceHeight = Math.max(1, Math.round(sourceHeight * safeMultiplier));\n const offscreenCanvas = document.createElement('canvas');\n offscreenCanvas.width = scaledSourceWidth;\n offscreenCanvas.height = scaledSourceHeight;\n const context = offscreenCanvas.getContext('2d');\n\n context.drawImage(imageElement, scaledSourceX, scaledSourceY, scaledSourceWidth, scaledSourceHeight, 0, 0, scaledSourceWidth, scaledSourceHeight);\n resolve(offscreenCanvas.toDataURL(`image/${format}`, quality));\n } catch (error) {\n reject(error);\n }\n };\n imageElement.onerror = reject;\n imageElement.src = dataUrl;\n });\n }\n\n async _exportCanvasRegionToDataURL({ sx, sy, sw, sh, multiplier = 1, quality = 0.92, format = 'jpeg' }) {\n const safeMultiplier = Math.max(1, Number(multiplier) || 1);\n const fullDataUrl = this.canvas.toDataURL({\n format,\n quality,\n multiplier: safeMultiplier\n });\n\n return this._cropDataUrl(fullDataUrl, sx, sy, sw, sh, safeMultiplier, format, quality);\n }\n\n /** \n * Gets the top-left corner coordinates of the given object.\n * Used for geometry calculations (e.g., scale, rotate).\n * \n * @param {Object} fabricObject - The object for which to get the top-left coordinates. Should support setCoords and getCoords/getBoundingRect methods.\n * @returns {{x: number, y: number}} The top-left corner point as an object with x and y properties.\n * @private\n */\n _getObjectTopLeftPoint(fabricObject) {\n if (!fabricObject) return { x: 0, y: 0 };\n fabricObject.setCoords();\n const coords = typeof fabricObject.getCoords === 'function' ? fabricObject.getCoords() : null;\n if (coords && coords.length) return coords[0];\n const boundingRect = fabricObject.getBoundingRect(true, true);\n return { x: boundingRect.left, y: boundingRect.top };\n }\n\n /**\n * Sets the object's origin at the specified origin point, keeping a reference point fixed in position.\n * \n * @param {Object} fabricObject - The object to modify. Should support set, setPositionByOrigin, and setCoords.\n * @param {string} originX - The new originX (\"left\", \"center\", \"right\", etc.).\n * @param {string} originY - The new originY (\"top\", \"center\", \"bottom\", etc.).\n * @param {{x: number, y: number}} refPoint - The point to keep fixed while setting the new origins.\n * @private\n */\n _setObjectOriginKeepingPosition(fabricObject, originX, originY, refPoint) {\n if (!fabricObject || !refPoint || !fabricObject.setPositionByOrigin) return;\n fabricObject.set({ originX, originY });\n fabricObject.setPositionByOrigin(refPoint, originX, originY);\n fabricObject.setCoords();\n }\n\n /**\n * Moves the object so its bounding box aligns with the canvas's top-left corner (0, 0).\n * \n * @param {Object} fabricObject - The object to align.\n * @private\n */\n _alignObjectBoundingBoxToCanvasTopLeft(fabricObject) {\n if (!fabricObject) return;\n fabricObject.setCoords();\n const boundingRect = fabricObject.getBoundingRect(true, true);\n const deltaX = boundingRect.left;\n const deltaY = boundingRect.top;\n fabricObject.set({ left: (fabricObject.left || 0) - deltaX, top: (fabricObject.top || 0) - deltaY });\n fabricObject.setCoords();\n this.canvas.renderAll();\n }\n\n /**\n * Updates the canvas size to match the bounding box of the original image,\n * ensuring that the canvas is always at least as large as its container.\n * @private\n */\n _updateCanvasSizeToImageBounds() {\n if (!this.originalImage) return;\n this.originalImage.setCoords();\n const imageBounds = this.originalImage.getBoundingRect(true, true);\n\n const size = this._getScrollableCanvasSize(imageBounds.width, imageBounds.height);\n this._setCanvasSizeInt(size.width, size.height);\n }\n\n _expandCanvasToFitObject(fabricObject, padding = 10) {\n if (!this.canvas || !fabricObject || !this.options.expandCanvasToImage) return;\n try {\n fabricObject.setCoords();\n const boundingRect = fabricObject.getBoundingRect(true, true);\n const requiredWidth = Math.ceil(boundingRect.left + boundingRect.width + padding);\n const requiredHeight = Math.ceil(boundingRect.top + boundingRect.height + padding);\n const minWidth = this.containerElement ? Math.floor(this.containerElement.clientWidth || 0) : 0;\n const minHeight = this.containerElement ? Math.floor(this.containerElement.clientHeight || 0) : 0;\n const newWidth = Math.max(this.canvas.getWidth(), minWidth, requiredWidth);\n const newHeight = Math.max(this.canvas.getHeight(), minHeight, requiredHeight);\n this._setCanvasSizeInt(newWidth, newHeight);\n } catch (error) {\n this._reportWarning('expandCanvasToFitObject: failed to expand canvas', error);\n }\n }\n\n /** \n * Scales the original image by a given factor, with animation.\n * Returns a promise that resolves when the scale animation is complete.\n * @param {number} factor - The scaling factor (will be clamped between `options.minScale` and `options.maxScale`).\n * @returns {Promise<void>} Promise that resolves once the scaling animation finishes.\n * @public\n */\n scaleImage(factor, options = {}) {\n return this.animQueue.add(() => this._scaleImageImpl(factor, options));\n }\n\n /** \n * Scales the original image by a given factor, with animation.\n * Returns a promise that resolves when the scale animation is complete.\n * @param {number} factor - The scaling factor (will be clamped between `options.minScale` and `options.maxScale`).\n * @returns {Promise<void>} Promise that resolves once the scaling animation finishes.\n * @private\n */\n _scaleImageImpl(factor, options = {}) {\n if (!this.originalImage) return Promise.resolve();\n if (this.isAnimating) return Promise.resolve();\n const saveHistory = options.saveHistory !== false;\n factor = Math.max(this.options.minScale, Math.min(this.options.maxScale, factor));\n this.currentScale = factor;\n this.isAnimating = true;\n this._updateUI();\n\n const targetScale = this.baseImageScale * factor;\n\n // Scale around current top-left (recompute)\n const topLeft = this._getObjectTopLeftPoint(this.originalImage);\n this._setObjectOriginKeepingPosition(this.originalImage, 'left', 'top', topLeft);\n\n const scaleXAnimation = new Promise((resolve) => {\n this.originalImage.animate('scaleX', targetScale, {\n duration: this.options.animationDuration,\n onChange: this.canvas.renderAll.bind(this.canvas),\n onComplete: resolve\n });\n });\n const scaleYAnimation = new Promise((resolve) => {\n this.originalImage.animate('scaleY', targetScale, {\n duration: this.options.animationDuration,\n onChange: this.canvas.renderAll.bind(this.canvas),\n onComplete: resolve\n });\n });\n\n return Promise.all([scaleXAnimation, scaleYAnimation]).then(() => {\n this.originalImage.set({ scaleX: targetScale, scaleY: targetScale });\n this.originalImage.setCoords();\n\n if (this.options.expandCanvasToImage || this.options.coverImageToCanvas) {\n this._updateCanvasSizeToImageBounds();\n }\n\n this._alignObjectBoundingBoxToCanvasTopLeft(this.originalImage);\n\n // Sync mask labels\n this.canvas.getObjects().forEach(object => { if (object.maskId) this._syncMaskLabel(object); });\n\n this.isAnimating = false;\n this._updateInputs();\n this._updateUI();\n if (saveHistory) this.saveState();\n }).catch(() => {\n this.isAnimating = false;\n this._updateUI();\n });\n }\n\n /** \n * Rotates the original image by a given number of degrees, with animation.\n * Returns a promise that resolves when the rotation animation is complete.\n * @param {number} degrees - The angle in degrees to rotate the image.\n * @returns {Promise<void>} Promise that resolves once the rotation animation finishes.\n * @public\n */\n rotateImage(degrees, options = {}) {\n return this.animQueue.add(() => this._rotateImageImpl(degrees, options));\n }\n\n /** \n * Rotates the original image by a given number of degrees, with animation.\n * Returns a promise that resolves when the rotation animation is complete.\n * @param {number} degrees - The angle in degrees to rotate the image.\n * @returns {Promise<void>} Promise that resolves once the rotation animation finishes.\n * @private\n */\n _rotateImageImpl(degrees, options = {}) {\n if (!this.originalImage) return Promise.resolve();\n if (this.isAnimating) return Promise.resolve();\n if (isNaN(degrees)) return Promise.resolve();\n const saveHistory = options.saveHistory !== false;\n this.currentRotation = degrees;\n this.isAnimating = true;\n this._updateUI();\n\n const center = this.originalImage.getCenterPoint();\n this._setObjectOriginKeepingPosition(this.originalImage, 'center', 'center', center);\n\n const rotationAnimation = new Promise((resolve) => {\n this.originalImage.animate('angle', degrees, {\n duration: this.options.animationDuration,\n onChange: this.canvas.renderAll.bind(this.canvas),\n onComplete: resolve\n });\n });\n\n return rotationAnimation.then(() => {\n this.originalImage.set('angle', degrees);\n this.originalImage.setCoords();\n\n if (this.options.expandCanvasToImage || this.options.coverImageToCanvas) {\n this._updateCanvasSizeToImageBounds();\n }\n\n this._alignObjectBoundingBoxToCanvasTopLeft(this.originalImage);\n\n const newTopLeft = this._getObjectTopLeftPoint(this.originalImage);\n this._setObjectOriginKeepingPosition(this.originalImage, 'left', 'top', newTopLeft);\n\n // Sync mask labels\n this.canvas.getObjects().forEach(object => { if (object.maskId) this._syncMaskLabel(object); });\n\n this.isAnimating = false;\n this._updateInputs();\n this._updateUI();\n if (saveHistory) this.saveState();\n }).catch(() => {\n this.isAnimating = false;\n this._updateUI();\n });\n }\n\n /**\n * Resets the image transform: scales to 1 and rotates to 0 degrees.\n * @returns {Promise<void>} Promise that resolves when reset is complete.\n */\n resetImageTransform() {\n if (!this.originalImage) return Promise.resolve();\n\n return this.animQueue.add(async () => {\n const before = this._serializeCanvasState();\n await this._scaleImageImpl(1, { saveHistory: false });\n await this._rotateImageImpl(0, { saveHistory: false });\n const after = this._serializeCanvasState();\n this._pushStateTransition(before, after);\n }).catch(err => {\n this._reportError('resetImageTransform() failed', err);\n });\n }\n\n /**\n * @deprecated Use resetImageTransform() instead.\n */\n reset() {\n return this.resetImageTransform();\n }\n\n /**\n * Restores a canvas state that was previously stored by saveState().\n * @param {string} jsonString - the JSON string returned by fabric.toJSON().\n */\n loadFromState(jsonString) {\n if (!jsonString || !this.canvas) return Promise.resolve();\n\n return new Promise((resolve) => {\n try {\n const json = (typeof jsonString === 'string')\n ? JSON.parse(jsonString)\n : jsonString;\n\n this.canvas.loadFromJSON(json, () => {\n try {\n this._hideAllMaskLabels();\n const canvasObjects = this.canvas.getObjects();\n this.originalImage = canvasObjects.find(object => object.type === 'image' && !object.maskId) || null;\n\n if (this.originalImage) {\n this.originalImage.set({ originX: 'left', originY: 'top', selectable: false, evented: false, hasControls: false, hoverCursor: 'default' });\n this.canvas.sendToBack(this.originalImage);\n this.currentRotation = Number(this.originalImage.angle) || 0;\n const baseScale = Number(this.baseImageScale) || 1;\n const imageScale = Number(this.originalImage.scaleX) || baseScale;\n this.currentScale = imageScale / baseScale;\n } else {\n this.currentScale = 1;\n this.currentRotation = 0;\n }\n\n const masks = canvasObjects.filter(object => object.maskId);\n masks.forEach(mask => {\n this._restoreMaskControls(mask);\n this._rebindMaskEvents(mask);\n mask.set(this._getMaskNormalStyle(mask));\n });\n this.maskCounter = masks.reduce((max, mask) =>\n Math.max(max, mask.maskId), 0);\n this._lastMask = masks.length ? masks[masks.length - 1] : null;\n if (!this._lastMask) {\n this._lastMaskInitialLeft = null;\n this._lastMaskInitialTop = null;\n this._lastMaskInitialWidth = null;\n }\n this.isImageLoadedToCanvas = !!this.originalImage;\n\n this.canvas.renderAll();\n this._updateInputs();\n this._updateMaskList();\n this._updatePlaceholderStatus();\n this._lastSnapshot = this._serializeCanvasState();\n this._updateUI();\n } catch (callbackError) {\n this._reportError('loadFromState() failed', callbackError);\n } finally {\n resolve();\n }\n });\n\n } catch (error) {\n this._reportError('loadFromState() failed', error);\n resolve();\n }\n });\n }\n\n /**\n * Saves the current state of the canvas to history, storing any mask/raster label information.\n */\n saveState() {\n if (!this.canvas) return;\n const activeObject = this.canvas.getActiveObject();\n this._hideAllMaskLabels();\n\n try {\n const after = this._serializeCanvasState();\n const before = this._lastSnapshot || after;\n if (after === before) return;\n let executedOnce = false;\n\n const command = new Command(\n () => {\n if (executedOnce) {\n return this.loadFromState(after);\n }\n executedOnce = true;\n return undefined;\n },\n () => this.loadFromState(before)\n );\n\n this.historyManager.execute(command);\n this._lastSnapshot = after;\n } catch (error) {\n this._reportWarning('saveState: failed to save canvas snapshot', error);\n } finally {\n if (activeObject && activeObject.maskId && this.canvas.getObjects().includes(activeObject)) {\n this._handleSelectionChanged([activeObject]);\n }\n this._updateUI();\n }\n }\n\n _pushStateTransition(before, after) {\n if (!before || !after) return;\n if (before === after) return;\n if (!this.historyManager) this.historyManager = new HistoryManager(this.maxHistorySize || 50);\n\n const command = new Command(\n () => this.loadFromState(after),\n () => this.loadFromState(before)\n );\n this.historyManager.push(command);\n this._lastSnapshot = after;\n this._updateUI();\n }\n\n /**\n * Undo the last state change, if possible.\n */\n undo() {\n return this.historyManager.undo()\n .then(() => { this._updateUI(); })\n .catch(error => { this._reportError('undo failed', error); });\n }\n\n /**\n * Redo the next state change, if possible.\n */\n redo() {\n return this.historyManager.redo()\n .then(() => { this._updateUI(); })\n .catch(error => { this._reportError('redo failed', error); });\n }\n\n _rebindMaskEvents(mask) {\n if (!mask) return;\n if (mask.__imageEditorMaskHandlers) {\n try {\n mask.off('mouseover', mask.__imageEditorMaskHandlers.mouseover);\n mask.off('mouseout', mask.__imageEditorMaskHandlers.mouseout);\n } catch (e) { void e; }\n }\n\n const metadata = {};\n if (!Number.isFinite(Number(mask.originalAlpha))) {\n metadata.originalAlpha = Number.isFinite(Number(mask.opacity)) ? Number(mask.opacity) : 0.5;\n }\n if (!mask.originalStroke) metadata.originalStroke = mask.stroke || '#ccc';\n if (!Number.isFinite(Number(mask.originalStrokeWidth))) {\n metadata.originalStrokeWidth = Number.isFinite(Number(mask.strokeWidth)) ? Number(mask.strokeWidth) : 1;\n }\n if (Object.keys(metadata).length) mask.set(metadata);\n\n const normalStyle = {\n stroke: mask.originalStroke || '#ccc',\n strokeWidth: mask.originalStrokeWidth,\n opacity: mask.originalAlpha\n };\n const hoverStyle = {\n stroke: '#ff5500',\n strokeWidth: 2,\n opacity: Math.min(mask.originalAlpha + 0.2, 1)\n };\n\n const mouseover = () => {\n mask.set(hoverStyle);\n if (mask.canvas) mask.canvas.requestRenderAll();\n };\n const mouseout = () => {\n mask.set(normalStyle);\n if (mask.canvas) mask.canvas.requestRenderAll();\n };\n\n mask.on('mouseover', mouseover);\n mask.on('mouseout', mouseout);\n mask.__imageEditorMaskHandlers = { mouseover, mouseout };\n }\n\n /** \n * Creates a mask and adds it to the canvas.\n * Mask placement and properties are determined by the provided config and instance options.\n * Canvas and list UI are updated accordingly.\n * @param {Object} [config={}] - Optional mask configuration overrides:\n * @param {string} [config.shape='rect'] - 'rect', 'circle', 'ellipse', 'polygon', ...\n * @param {Object|Array} [config.points] - Required for polygon: [{x, y}, ...] or [[x, y], ...]\n * @param {number|function} [config.width/height/rx/ry/radius] - Can be number or function(canvas, options) \n * @param {number|string|function} [config.left/top] - Absolute, %, or function\n * @param {number|string} [config.angle] - Rotation angle (degree)\n * @param {string} [config.color] - Fill color in CSS color format (default 'rgba(0,0,0,0.5)')\n * @param {number} [config.alpha] - Opacity, from 0 to 1 (default 0.5)\n * @param {boolean} [config.selectable=true]\n * @param {Object} [config.styles] - Custom styles (stroke, dashArray, etc)\n * @param {function} [config.onCreate] - Callback after mask created (receives Fabric object)\n * @param {function} [config.fabricGenerator] - (maskConfig) => new FabricObj\n * @returns {fabric.Rect|null} The created mask object, or null if canvas is not available.\n * @public\n */\n createMask(config = {}) {\n if (!this.canvas) return null;\n const shapeType = config.shape || 'rect';\n // Default config\n const maskConfig = {\n shape: shapeType,\n width: this.options.defaultMaskWidth,\n height: this.options.defaultMaskHeight,\n color: 'rgba(0,0,0,0.5)',\n alpha: 0.5,\n gap: 5,\n left: undefined,\n top: undefined,\n angle: 0,\n selectable: true,\n ...config\n };\n\n // Always start placement relative to canvas left/top.\n const firstOffset = 10;\n let left = firstOffset;\n let top = firstOffset;\n\n const resolveValue = (value, fallback) => {\n if (typeof value === 'function')\n return value(this.canvas, this.options);\n if (typeof value === 'string' && value.endsWith('%')) {\n const percent = parseFloat(value) / 100;\n return Math.floor((this.canvas ? this.canvas.getWidth() : 0) * percent);\n }\n return value != null ? value : fallback;\n }\n\n if (maskConfig.left === undefined && this._lastMask) {\n const previousMask = this._lastMask;\n let previousMaskRight = previousMask.left;\n\n if (previousMask.getScaledWidth) {\n previousMaskRight += previousMask.getScaledWidth();\n } else if (previousMask.width) {\n previousMaskRight += previousMask.width * (previousMask.scaleX ?? 1);\n }\n left = Math.round(previousMaskRight + maskConfig.gap);\n top = previousMask.top ?? firstOffset;\n } else {\n left = resolveValue(maskConfig.left, firstOffset);\n top = resolveValue(maskConfig.top, firstOffset);\n }\n\n maskConfig.width = resolveValue(maskConfig.width, this.options.defaultMaskWidth);\n maskConfig.height = resolveValue(maskConfig.height, this.options.defaultMaskHeight);\n\n let mask;\n if (typeof maskConfig.fabricGenerator === 'function') {\n mask = maskConfig.fabricGenerator(maskConfig, this.canvas, this.options);\n } else {\n switch (shapeType) {\n case 'circle':\n mask = new fabric.Circle({\n left, top,\n radius: resolveValue(maskConfig.radius, Math.min(maskConfig.width, maskConfig.height) / 2),\n fill: maskConfig.color,\n opacity: maskConfig.alpha,\n angle: maskConfig.angle,\n ...maskConfig.styles\n });\n break;\n case 'ellipse':\n mask = new fabric.Ellipse({\n left, top,\n rx: resolveValue(maskConfig.rx, maskConfig.width / 2),\n ry: resolveValue(maskConfig.ry, maskConfig.height / 2),\n fill: maskConfig.color,\n opacity: maskConfig.alpha,\n angle: maskConfig.angle,\n ...maskConfig.styles\n });\n break;\n case 'polygon': {\n let polygonPoints = maskConfig.points || [];\n if (Array.isArray(polygonPoints) && polygonPoints.length && typeof polygonPoints[0] === 'object') {\n // Ensure numeric {x,y} objects for fabric.Polygon\n polygonPoints = polygonPoints.map(point => ({ x: Number(point.x), y: Number(point.y) }));\n }\n mask = new fabric.Polygon(polygonPoints, {\n left, top,\n fill: maskConfig.color,\n opacity: maskConfig.alpha,\n angle: maskConfig.angle,\n ...maskConfig.styles\n });\n break;\n }\n case 'rect':\n default:\n mask = new fabric.Rect({\n left, top,\n width: resolveValue(maskConfig.width, this.options.defaultMaskWidth),\n height: resolveValue(maskConfig.height, this.options.defaultMaskHeight),\n fill: maskConfig.color,\n opacity: maskConfig.alpha,\n angle: maskConfig.angle,\n rx: maskConfig.rx, // Rounded Corners\n ry: maskConfig.ry,\n ...maskConfig.styles\n });\n }\n }\n\n const styles = maskConfig.styles || {};\n const hasStyle = property => Object.prototype.hasOwnProperty.call(styles, property);\n const maskSettings = {\n selectable: maskConfig.selectable !== false,\n hasControls: ('hasControls' in maskConfig) ? maskConfig.hasControls : true,\n lockRotation: !this.options.maskRotatable,\n borderColor: ('borderColor' in maskConfig) ? maskConfig.borderColor : 'red',\n cornerColor: ('cornerColor' in maskConfig) ? maskConfig.cornerColor : 'black',\n cornerSize: ('cornerSize' in maskConfig) ? maskConfig.cornerSize : 8,\n transparentCorners: ('transparentCorners' in maskConfig) ? maskConfig.transparentCorners : false,\n stroke: hasStyle('stroke') ? styles.stroke : '#ccc',\n strokeWidth: hasStyle('strokeWidth') ? styles.strokeWidth : 1,\n strokeUniform: ('strokeUniform' in maskConfig) ? maskConfig.strokeUniform : (hasStyle('strokeUniform') ? styles.strokeUniform : true)\n };\n if (hasStyle('strokeDashArray')) maskSettings.strokeDashArray = styles.strokeDashArray;\n mask.set(maskSettings);\n mask.setCoords();\n\n mask.set({\n originalAlpha: maskConfig.alpha,\n originalStroke: mask.stroke || '#ccc',\n originalStrokeWidth: Number.isFinite(Number(mask.strokeWidth)) ? Number(mask.strokeWidth) : 1\n });\n this._rebindMaskEvents(mask);\n this._expandCanvasToFitObject(mask);\n\n // Remember initial for next one\n this._lastMaskInitialLeft = left;\n this._lastMaskInitialTop = top;\n this._lastMaskInitialWidth = resolveValue(maskConfig.width, this.options.defaultMaskWidth);\n\n const maskId = ++this.maskCounter;\n mask.set({\n maskId,\n maskName: `${this.options.maskName}${maskId}`\n });\n this._lastMask = mask;\n\n this.canvas.add(mask);\n this.canvas.bringToFront(mask);\n if (maskConfig.selectable) this.canvas.setActiveObject(mask);\n this._handleSelectionChanged([mask]);\n this._updateMaskList();\n this._updateUI();\n this.canvas.renderAll();\n this.saveState();\n\n if (typeof maskConfig.onCreate === 'function') maskConfig.onCreate(mask, this.canvas);\n return mask;\n }\n\n /**\n * @deprecated Use createMask() instead.\n */\n addMask(config = {}) {\n return this.createMask(config);\n }\n\n /**\n * Removes the currently selected mask from the canvas, if any.\n * The associated label is also removed. UI and mask list are updated.\n */\n removeSelectedMask() {\n const activeObject = this.canvas.getActiveObject();\n const selectedMasks = this._getModifiedMasks(activeObject);\n if (!selectedMasks.length) return;\n\n this.canvas.discardActiveObject();\n selectedMasks.forEach(mask => {\n this._removeLabelForMask(mask);\n this.canvas.remove(mask);\n });\n\n const masks = this.canvas.getObjects().filter(object => object.maskId);\n this._lastMask = masks.length ? masks[masks.length - 1] : null;\n if (!this._lastMask) {\n this._lastMaskInitialLeft = null;\n this._lastMaskInitialTop = null;\n this._lastMaskInitialWidth = null;\n }\n this._updateMaskList();\n this._updateUI();\n this.canvas.renderAll();\n this.saveState();\n }\n\n /**\n * Removes all masks from the canvas, including their labels.\n * UI and internal mask placement memory are reset.\n */\n removeAllMasks(options = {}) {\n const saveHistory = options.saveHistory !== false;\n const masks = this.canvas.getObjects().filter(object => object.maskId);\n masks.forEach(mask => this._removeLabelForMask(mask));\n masks.forEach(mask => this.canvas.remove(mask));\n this.canvas.discardActiveObject();\n this._lastMask = null;\n this._lastMaskInitialLeft = null;\n this._lastMaskInitialTop = null;\n this._lastMaskInitialWidth = null;\n this._updateMaskList();\n this._updateUI();\n this.canvas.renderAll();\n if (saveHistory) this.saveState();\n }\n\n /**\n * Removes the label associated with the specified mask object, if it exists.\n * \n * @param {fabric.Object} mask - The mask object whose label should be removed.\n * @private\n */\n _removeLabelForMask(mask) {\n if (!mask || !this.canvas) return;\n if (mask.__label) {\n try {\n const canvasObjects = this.canvas.getObjects();\n if (canvasObjects.includes(mask.__label)) {\n this.canvas.remove(mask.__label);\n }\n } catch (error) { void error; }\n try { delete mask.__label; } catch (error) { void error; }\n }\n }\n\n /**\n * Creates and adds a custom label (fabric.Text or fabric.IText) for the mask.\n * The label is default bound to the top-left of the mask and managed as a non-interactive overlay.\n * \n * @param {fabric.Object} mask - The mask to create a label for.\n * @private\n */\n _createLabelForMask(mask) {\n if (!mask || !this.options.maskLabelOnSelect) return;\n this._removeLabelForMask(mask);\n let textObject = null;\n if (this.options.label && typeof this.options.label.create === 'function') {\n textObject = this.options.label.create(mask, fabric);\n }\n if (!textObject) {\n let labelText = mask.maskName;\n let textOptions = {\n left: 0,\n top: 0,\n fontSize: 12,\n fill: '#fff',\n backgroundColor: 'rgba(0,0,0,0.7)',\n selectable: false,\n evented: false,\n padding: 2,\n originX: 'left',\n originY: 'top'\n };\n if (this.options.label) {\n if (typeof this.options.label.getText === 'function') {\n const masks = this.canvas ? this.canvas.getObjects().filter(object => object.maskId) : [];\n const maskIndex = Math.max(0, masks.indexOf(mask));\n labelText = this.options.label.getText(mask, maskIndex);\n }\n // Merge external styles\n if (this.options.label.textOptions) {\n Object.assign(textOptions, this.options.label.textOptions);\n }\n }\n textObject = new fabric.Text(labelText, textOptions);\n }\n\n textObject.maskLabel = true;\n mask.__label = textObject;\n this.canvas.add(textObject);\n this.canvas.bringToFront(textObject);\n this._syncMaskLabel(mask);\n }\n\n /**\n * Hides (removes) all mask labels from the canvas.\n * Internal label references on mask objects are also deleted.\n * @private\n */\n _hideAllMaskLabels() {\n if (!this.canvas) return;\n const canvasObjects = this.canvas.getObjects();\n const labels = canvasObjects.filter(object => object.maskLabel);\n labels.forEach(label => {\n try {\n if (canvasObjects.includes(label)) this.canvas.remove(label);\n } catch (error) { void error; }\n });\n canvasObjects.forEach(object => {\n if (object.maskId && object.__label) {\n try { delete object.__label; } catch (error) { void error; }\n }\n });\n }\n\n /**\n * Synchronizes the position, angle, and visibility of the mask's label so that it appears properly above the mask.\n * \n * @param {fabric.Object} mask - The mask whose label should be repositioned.\n * @private\n */\n _syncMaskLabel(mask) {\n if (!mask) return;\n if (!this.options.maskLabelOnSelect) return;\n if (!mask.__label) return;\n\n const coords = mask.getCoords ? mask.getCoords() : null;\n if (!coords || coords.length < 4) return;\n\n const tl = coords[0];\n const center = mask.getCenterPoint();\n\n const vx = center.x - tl.x;\n const vy = center.y - tl.y;\n const dist = Math.sqrt(vx * vx + vy * vy) || 1;\n const ux = vx / dist;\n const uy = vy / dist;\n\n const offset = Math.max(0, this.options.maskLabelOffset ?? 3);\n\n const px = tl.x + ux * offset;\n const py = tl.y + uy * offset;\n\n mask.__label.set({\n left: Math.round(px),\n top: Math.round(py),\n angle: mask.angle || 0,\n originX: 'left',\n originY: 'top',\n visible: true\n });\n mask.__label.setCoords();\n if (typeof this.canvas.requestRenderAll === 'function') {\n this.canvas.requestRenderAll();\n } else {\n this.canvas.renderAll();\n }\n }\n\n /**\n * Shows the label for the given mask, creating it if necessary and synchronizing its position.\n * \n * @param {fabric.Object} mask - The mask whose label should be shown.\n * @private\n */\n _showLabelForMask(mask) {\n if (!mask) return;\n if (!this.options.maskLabelOnSelect) return;\n if (!mask.__label) this._createLabelForMask(mask);\n mask.__label.set({ visible: true });\n this._syncMaskLabel(mask);\n }\n\n /**\n * Handles changes to the selection of canvas objects (masks),\n * updates mask stroke and label display, and syncs mask list selection.\n *\n * @param {Array<Object>} selected - The currently selected objects (e.g. [mask] or []).\n * @private\n */\n _handleSelectionChanged(selected) {\n const selectedMask = (selected || []).find(object => object.maskId);\n const masks = this.canvas.getObjects().filter(object => object.maskId);\n masks.forEach(mask => {\n if (mask !== selectedMask) {\n if (mask.__label) {\n try { this.canvas.remove(mask.__label); } catch (error) { void error; }\n delete mask.__label;\n }\n const originalStrokeWidth = Number(mask.originalStrokeWidth);\n mask.set({\n stroke: mask.originalStroke || '#ccc',\n strokeWidth: Number.isFinite(originalStrokeWidth) ? originalStrokeWidth : 1\n });\n } else {\n mask.set({ stroke: '#ff0000', strokeWidth: 1 });\n }\n });\n\n if (selectedMask) this._showLabelForMask(selectedMask);\n\n this._updateMaskListSelection(selectedMask);\n this.canvas.renderAll();\n this._updateUI();\n }\n\n /**\n * Updates the mask list in the DOM to reflect the current masks on the canvas.\n * Each list entry becomes a clickable element for mask selection.\n * @private\n */\n _updateMaskList() {\n const maskListElement = document.getElementById(this.elements.maskList);\n if (!maskListElement) return;\n maskListElement.innerHTML = '';\n const masks = this.canvas.getObjects().filter(object => object.maskId);\n masks.forEach(mask => {\n const listItemElement = document.createElement('li');\n listItemElement.className = 'list-group-item mask-item';\n listItemElement.textContent = mask.maskName;\n listItemElement.onclick = () => { this.canvas.setActiveObject(mask); this._handleSelectionChanged([mask]); };\n maskListElement.appendChild(listItemElement);\n });\n }\n\n /**\n * Updates the visual selection (CSS 'active') state for the mask list in the DOM.\n * \n * @param {Object|null} selectedMask - The currently selected mask, or null if none selected.\n * @private\n */\n _updateMaskListSelection(selectedMask) {\n const maskListElement = document.getElementById(this.elements.maskList);\n if (!maskListElement) return;\n const maskItems = maskListElement.querySelectorAll('.mask-item');\n maskItems.forEach(item => {\n const isSelected = !!selectedMask && item.textContent === selectedMask.maskName;\n item.classList.toggle('active', isSelected);\n });\n }\n\n /**\n * Merges current masks into the image: exports a masked/cropped image, removes all masks, and re-imports the merged image.\n * Will not run if no original image or no masks exist.\n * @async\n * @returns {Promise<void>} Resolves when merge and load are complete.\n */\n async mergeMasks() {\n if (!this.originalImage) return;\n const masks = this.canvas.getObjects().filter(object => object.maskId);\n if (!masks.length) return;\n\n this.canvas.discardActiveObject();\n this.canvas.renderAll();\n\n try {\n const beforeJson = this._serializeCanvasState();\n const merged = await this.exportImageBase64({ exportImageArea: true, multiplier: this.options.exportMultiplier });\n this.removeAllMasks({ saveHistory: false });\n await this.loadImage(merged);\n const afterJson = this._serializeCanvasState();\n this._pushStateTransition(beforeJson, afterJson);\n } catch (err) {\n this._reportError('merge error', err);\n }\n }\n\n /**\n * @deprecated Use mergeMasks() instead.\n */\n async merge() {\n return this.mergeMasks();\n }\n\n /**\n * Triggers a JPEG image download of the current canvas (image plus masks if configured).\n * The image area and multiplier are controlled by options.\n * @param {string} [fileName=this.options.defaultDownloadFileName] - Desired download file name.\n */\n downloadImage(fileName = this.options.defaultDownloadFileName) {\n if (!this.originalImage) return;\n const exportImageArea = this.options.exportImageAreaByDefault;\n this.exportImageBase64({ exportImageArea, multiplier: this.options.exportMultiplier })\n .then(base64 => {\n const link = document.createElement('a');\n link.download = fileName;\n link.href = base64;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n })\n .catch(err => this._reportError('download error', err));\n }\n\n /**\n * Exports the image as a Base64-encoded image data URL.\n * Can export either the original, or the current view including masks (clipped/cropped).\n * Will restore masks' state after temporary modifications for export.\n * @async\n * @param {Object} [options={}] - Export options.\n * @param {boolean} [options.exportImageArea] - If true, exports only the image bounding area with masks cropped and blended.\n * @param {number} [options.multiplier=1] - Scaling multiplier for output (resolution).\n * @param {number} [options.quality=0.92] - Image quality between 0 and 1 for lossy formats.\n * @param {string} [options.fileType='jpeg'] - Output file type ('jpeg' | 'png' | 'webp').\n * @returns {Promise<string>} Promise resolving to an image data URL.\n * @throws {Error} If there is no image loaded.\n */\n async exportImageBase64(options = {}) {\n if (!this.originalImage) throw new Error('No image loaded');\n const exportImageArea = typeof options.exportImageArea === 'boolean' ? options.exportImageArea : this.options.exportImageAreaByDefault;\n const multiplier = options.multiplier || this.options.exportMultiplier || 1;\n const quality = this._normalizeQuality(options.quality ?? this.options.downsampleQuality);\n const format = this._normalizeImageFormat(options.fileType || options.format);\n\n if (!exportImageArea) {\n const masks = this.canvas.getObjects().filter(object => object.maskId || object.maskLabel);\n const maskVisibilityBackups = masks.map(mask => ({ object: mask, visible: mask.visible }));\n\n try {\n masks.forEach(mask => { mask.set({ visible: false }); });\n this.canvas.discardActiveObject();\n this.canvas.renderAll();\n\n this.originalImage.setCoords();\n const imageBounds = this.originalImage.getBoundingRect(true, true);\n const { sx, sy, sw, sh } = this._getClampedCanvasRegion(imageBounds, { includePartialPixels: false });\n return await this._exportCanvasRegionToDataURL({\n sx,\n sy,\n sw,\n sh,\n multiplier,\n quality,\n format\n });\n } finally {\n maskVisibilityBackups.forEach(backup => {\n try { backup.object.set({ visible: backup.visible }); } catch (error) { void error; }\n });\n this.canvas.renderAll();\n }\n }\n\n // Export current scaled image area (masks clipped)\n const masks = this.canvas.getObjects().filter(object => object.maskId);\n const maskStyleBackups = masks.map(mask => ({\n object: mask,\n opacity: mask.opacity,\n fill: mask.fill,\n strokeWidth: mask.strokeWidth,\n stroke: mask.stroke,\n selectable: mask.selectable,\n lockRotation: mask.lockRotation\n }));\n\n let finalBase64;\n try {\n // Remove labels, deselect\n masks.forEach(mask => this._removeLabelForMask(mask));\n this.canvas.discardActiveObject();\n this.canvas.renderAll();\n\n // Set masks to opaque black no border\n masks.forEach(mask => {\n mask.set({ opacity: 1, fill: '#000000', strokeWidth: 0, stroke: null, selectable: false });\n mask.setCoords();\n });\n this.canvas.renderAll();\n\n // Compute integer bounding box for image\n this.originalImage.setCoords();\n const imageBounds = this.originalImage.getBoundingRect(true, true);\n const { sx, sy, sw, sh } = this._getClampedCanvasRegion(imageBounds, { includePartialPixels: false });\n\n // Crop precisely in offscreen canvas\n finalBase64 = await this._exportCanvasRegionToDataURL({\n sx,\n sy,\n sw,\n sh,\n multiplier,\n quality,\n format\n });\n } finally {\n maskStyleBackups.forEach(backup => {\n try {\n backup.object.set({\n opacity: backup.opacity,\n fill: backup.fill,\n strokeWidth: backup.strokeWidth,\n stroke: backup.stroke,\n selectable: backup.selectable,\n lockRotation: backup.lockRotation\n });\n backup.object.setCoords();\n } catch (error) { void error; }\n });\n\n this.canvas.renderAll();\n }\n\n return finalBase64;\n }\n\n /**\n * @deprecated Use exportImageBase64() instead.\n */\n async getImageBase64(options = {}) {\n return this.exportImageBase64(options);\n }\n\n /**\n * Exports the current canvas (with or without masks) as a File object.\n * Allows you to choose whether to merge masks and specify file type (jpeg/png/webp).\n * \n * @async\n * @param {Object} [options={}] - Export options.\n * @param {boolean} [options.mergeMask=true] - If true, export image area with masks merged; if false, export the plain image without masks.\n * @param {string} [options.fileType='jpeg'] - Output file type ('jpeg' | 'png' | 'webp'). Defaults to 'jpeg' on invalid input.\n * @param {number} [options.quality=0.92] - Image quality for lossy types (0-1, default based on options.downsampleQuality).\n * @param {number} [options.multiplier=1] - Output resolution multiplier.\n * @param {string} [options.fileName] - Optional file name (only used for download).\n * @returns {Promise<File>} Resolves with the exported image as a File object.\n * \n * @example\n * const file = await this.exportImageFile({ mergeMask: false, fileType: 'png' });\n */\n async exportImageFile(options = {}) {\n if (!this.originalImage) throw new Error('No image loaded');\n const {\n mergeMask = true,\n fileType = 'jpeg',\n quality = this.options.downsampleQuality ?? 0.92,\n multiplier = this.options.exportMultiplier ?? 1,\n fileName = this.options.defaultDownloadFileName ?? 'exported_image.jpg'\n } = options;\n\n const safeFileType = this._normalizeImageFormat(fileType);\n\n // Get Base64\n let base64;\n if (mergeMask) {\n base64 = await this.exportImageBase64({\n exportImageArea: true,\n multiplier,\n quality,\n fileType: safeFileType\n });\n } else {\n base64 = await this.exportImageBase64({\n exportImageArea: false,\n multiplier,\n quality,\n fileType: safeFileType\n });\n }\n\n // Convert to the required image format\n let imageDataUrl = base64;\n if (!imageDataUrl.startsWith(`data:image/${safeFileType}`)) {\n // Redraw if not required format\n imageDataUrl = await new Promise((resolve, reject) => {\n const imageElement = new window.Image();\n imageElement.crossOrigin = \"Anonymous\";\n imageElement.onload = () => {\n try {\n const offscreenCanvas = document.createElement('canvas');\n offscreenCanvas.width = imageElement.width;\n offscreenCanvas.height = imageElement.height;\n const context = offscreenCanvas.getContext('2d');\n context.drawImage(imageElement, 0, 0);\n const convertedDataUrl = offscreenCanvas.toDataURL(`image/${safeFileType}`, quality);\n resolve(convertedDataUrl);\n } catch (error) { reject(error); }\n };\n imageElement.onerror = reject;\n imageElement.src = base64;\n });\n }\n\n // Convert DataURL to Blob and then to File\n const binaryString = atob(imageDataUrl.split(',')[1]);\n const mime = `image/${safeFileType}`;\n let byteIndex = binaryString.length;\n const bytes = new Uint8Array(byteIndex);\n while (byteIndex--) {\n bytes[byteIndex] = binaryString.charCodeAt(byteIndex);\n }\n return new File([bytes], fileName, { type: mime });\n }\n\n _clearMaskPlacementMemory() {\n this._lastMask = null;\n this._lastMaskInitialLeft = null;\n this._lastMaskInitialTop = null;\n this._lastMaskInitialWidth = null;\n }\n\n async _restoreStateAfterCropFailure(beforeJson, message, error) {\n this._reportError(message, error);\n\n if (this._cropRect && this.canvas) this._removeCropRect();\n this._cropRect = null;\n this._cropMode = false;\n if (this.canvas && this._prevSelectionSetting !== undefined) {\n this.canvas.selection = !!this._prevSelectionSetting;\n }\n this._prevSelectionSetting = undefined;\n\n if (beforeJson) {\n try {\n await this.loadFromState(beforeJson);\n } catch (restoreError) {\n this._reportError('applyCrop: rollback failed', restoreError);\n }\n }\n\n this._updateUI();\n if (this.canvas) this.canvas.renderAll();\n }\n\n _restoreCropObjectState() {\n if (Array.isArray(this._cropPrevEvented)) {\n this._cropPrevEvented.forEach(state => {\n try {\n state.object.set({\n evented: state.evented,\n selectable: state.selectable,\n visible: state.visible\n });\n } catch (error) { void error; }\n });\n }\n this._cropPrevEvented = null;\n }\n\n _removeCropRect() {\n if (!this._cropRect) return;\n try {\n if (this._cropHandlers && this._cropHandlers.length) {\n this._cropHandlers.forEach(targetHandlers => {\n targetHandlers.handlers.forEach(handlerRecord => {\n targetHandlers.target.off(handlerRecord.eventName, handlerRecord.handler);\n });\n });\n }\n } catch (error) { void error; }\n\n try { this.canvas.remove(this._cropRect); } catch (error) { void error; }\n this._cropRect = null;\n this._cropHandlers = [];\n }\n\n /**\n * Enter crop mode: create a resizable/movable selection rect on top of the image.\n * @public\n */\n enterCropMode() {\n if (!this.canvas || !this.originalImage || this._cropMode) return;\n if (!this.isImageLoaded()) return;\n this._cropMode = true;\n\n // Disable canvas group selection to avoid accidental group selection while cropping\n this._prevSelectionSetting = this.canvas.selection;\n this.canvas.selection = false;\n\n // Make sure no active object\n this.canvas.discardActiveObject();\n\n // Create initial crop rect centered on the image bounding box\n this.originalImage.setCoords();\n const imageBounds = this.originalImage.getBoundingRect(true, true);\n // Provide small inset so user can see a margin\n const padding = (this.options.crop && this.options.crop.padding) ? this.options.crop.padding : 10;\n const left = Math.max(0, Math.floor(imageBounds.left + padding));\n const top = Math.max(0, Math.floor(imageBounds.top + padding));\n const width = Math.min(this.options.crop.minWidth || 50, Math.floor(imageBounds.width - padding * 2));\n const height = Math.min(this.options.crop.minHeight || 50, Math.floor(imageBounds.height - padding * 2));\n\n // Visual style: translucent fill + dashed stroke\n const cropRect = new fabric.Rect({\n left, top,\n width, height,\n fill: 'rgba(0,0,0,0.12)',\n stroke: '#00aaff',\n strokeDashArray: [6, 4],\n strokeWidth: 1,\n strokeUniform: true,\n selectable: true,\n hasRotatingPoint: !!(this.options.crop && this.options.crop.allowRotationOfCropRect),\n lockRotation: !(this.options.crop && this.options.crop.allowRotationOfCropRect),\n cornerSize: 8,\n objectCaching: false,\n originX: 'left',\n originY: 'top'\n });\n\n // Ensure the crop rect is above everything\n this.canvas.add(cropRect);\n cropRect.isCropRect = true;\n this.canvas.bringToFront(cropRect);\n this.canvas.setActiveObject(cropRect);\n\n // Keep reference\n this._cropRect = cropRect;\n\n // While in crop mode: we want only the cropRect to be interactive\n // but still allow moving/scaling it. To be safe, set other objects evented=false temporarily.\n this._cropPrevEvented = [];\n const shouldHideMasks = !!(this.options.crop && this.options.crop.hideMasksDuringCrop);\n this.canvas.getObjects().forEach(object => {\n if (object !== cropRect) {\n this._cropPrevEvented.push({ object, evented: object.evented, selectable: object.selectable, visible: object.visible });\n try {\n const updates = {\n evented: false,\n selectable: false\n };\n if (shouldHideMasks && (object.maskId || object.maskLabel)) updates.visible = false;\n object.set(updates);\n } catch (error) { void error; }\n }\n });\n\n // When the crop rect changes, re-render\n const handleCropRectModified = () => { try { cropRect.setCoords(); this.canvas.requestRenderAll(); } catch (error) { void error; } };\n cropRect.on('modified', handleCropRectModified);\n cropRect.on('moving', handleCropRectModified);\n cropRect.on('scaling', handleCropRectModified);\n\n // Keep handlers to remove later\n this._cropHandlers.push({\n target: cropRect,\n handlers: [\n { eventName: 'modified', handler: handleCropRectModified },\n { eventName: 'moving', handler: handleCropRectModified },\n { eventName: 'scaling', handler: handleCropRectModified }\n ]\n });\n\n this._updateUI();\n this.canvas.renderAll();\n }\n\n /**\n * Cancel crop mode and remove the temporary selection rect.\n * @public\n */\n cancelCrop() {\n if (!this.canvas || !this._cropMode) return;\n this._removeCropRect();\n this._restoreCropObjectState();\n this._cropMode = false;\n // restore selection setting\n this.canvas.selection = !!this._prevSelectionSetting;\n this._prevSelectionSetting = undefined;\n\n this.canvas.discardActiveObject();\n this._updateUI();\n this.canvas.renderAll();\n }\n\n /**\n * Apply the current crop rectangle.\n * remove all masks and export canvas snapshot and crop via offscreen canvas\n * @public\n */\n async applyCrop() {\n if (!this.canvas || !this._cropMode || !this._cropRect) return;\n\n // Ensure crop rect coords are fresh\n this._cropRect.setCoords();\n const rectBounds = this._cropRect.getBoundingRect(true, true);\n\n const { sx, sy, sw, sh } = this._getClampedCanvasRegion(rectBounds);\n const shouldPreserveMasks = !!(this.options.crop && this.options.crop.preserveMasksAfterCrop);\n\n this._restoreCropObjectState();\n\n let beforeJson = null;\n try {\n beforeJson = this._serializeCanvasState();\n } catch (error) {\n this._reportWarning('applyCrop: could not serialize before state', error);\n beforeJson = null;\n }\n\n const preservedMasks = [];\n\n try {\n const masks = this.canvas.getObjects().filter(object => object.maskId);\n if (masks && masks.length) {\n masks.forEach(mask => {\n try {\n mask.setCoords();\n const maskBounds = mask.getBoundingRect(true, true);\n const intersectsCrop =\n maskBounds.left < sx + sw &&\n maskBounds.left + maskBounds.width > sx &&\n maskBounds.top < sy + sh &&\n maskBounds.top + maskBounds.height > sy;\n this._removeLabelForMask(mask);\n this.canvas.remove(mask);\n if (shouldPreserveMasks && intersectsCrop) {\n mask.set({\n left: (mask.left || 0) - sx,\n top: (mask.top || 0) - sy,\n visible: true\n });\n mask.setCoords();\n preservedMasks.push(mask);\n }\n } catch (error) {\n this._reportWarning('applyCrop: failed to remove mask', error);\n }\n });\n this._clearMaskPlacementMemory();\n this.canvas.discardActiveObject();\n this.canvas.renderAll();\n }\n } catch (error) {\n this._reportWarning('applyCrop: error while removing masks', error);\n }\n\n this._removeCropRect();\n\n // End crop mode\n this._cropMode = false;\n this.canvas.selection = !!this._prevSelectionSetting;\n this._prevSelectionSetting = undefined;\n\n // Export full canvas and crop on offscreen canvas\n let croppedBase64;\n try {\n croppedBase64 = await this._exportCanvasRegionToDataURL({\n sx,\n sy,\n sw,\n sh,\n multiplier: 1,\n quality: this._normalizeQuality(this.options.downsampleQuality),\n format: 'jpeg'\n });\n } catch (error) {\n await this._restoreStateAfterCropFailure(beforeJson, 'applyCrop: failed to create cropped image', error);\n return;\n }\n\n // Load the cropped image as the new base image\n try {\n await this.loadImage(croppedBase64);\n if (preservedMasks.length) {\n preservedMasks.forEach(mask => {\n this._rebindMaskEvents(mask);\n this.canvas.add(mask);\n this.canvas.bringToFront(mask);\n });\n this._lastMask = preservedMasks[preservedMasks.length - 1];\n this.maskCounter = preservedMasks.reduce((max, mask) => Math.max(max, mask.maskId || 0), this.maskCounter);\n this._updateMaskList();\n this.canvas.renderAll();\n }\n } catch (e) {\n await this._restoreStateAfterCropFailure(beforeJson, 'applyCrop: loadImage(croppedBase64) failed', e);\n return;\n }\n\n // Create \"after\" snapshot (also exclude crop rect if any) and push history command\n let afterJson = null;\n try {\n afterJson = this._serializeCanvasState();\n } catch (e) {\n this._reportWarning('applyCrop: failed to serialize after state', e);\n afterJson = null;\n }\n\n try {\n this._pushStateTransition(beforeJson, afterJson);\n } catch (e) {\n this._reportWarning('applyCrop: failed to push history command', e);\n }\n\n // Final UI update\n this._updateUI();\n this.canvas.renderAll();\n }\n\n\n /* ---------- Misc / UI ---------- */\n\n /**\n * Updates the scale input field in the UI to reflect the current scale.\n * Sets the value (as percentage) if the element is present.\n * @private\n */\n _updateInputs() {\n const scaleInputElement = document.getElementById(this.elements.scaleRate);\n if (scaleInputElement) scaleInputElement.value = Math.round(this.currentScale * 100);\n }\n\n /**\n * Updates the enabled/disabled state of various UI controls (buttons)\n * based on the current application state (image/mask presence, animation, etc).\n * @private\n */\n _updateUI() {\n const hasImage = !!this.originalImage;\n const masks = hasImage ? this.canvas.getObjects().filter(object => object.maskId) : [];\n const hasMasks = masks.length > 0;\n const activeObject = this.canvas.getActiveObject();\n const hasSelectedMask = activeObject && activeObject.maskId;\n const isDefaultTransform = this.currentScale === 1 && this.currentRotation === 0;\n const canUndo = this.historyManager?.canUndo();\n const canRedo = this.historyManager?.canRedo();\n const isInCropMode = !!this._cropMode;\n\n if (isInCropMode) {\n // iterate all element keys and disable unless key is applyCropBtn or cancelCropBtn\n for (const key of Object.keys(this.elements || {})) {\n const element = document.getElementById(this.elements[key]);\n if (!element) continue;\n if (key === 'applyCropBtn' || key === 'cancelCropBtn') {\n this._setDisabled(key, false);\n } else {\n this._setDisabled(key, true);\n }\n }\n return;\n }\n\n this._setDisabled('zoomInBtn', !hasImage || this.isAnimating || this.currentScale >= this.options.maxScale);\n this._setDisabled('zoomOutBtn', !hasImage || this.isAnimating || this.currentScale <= this.options.minScale);\n this._setDisabled('rotateLeftBtn', !hasImage || this.isAnimating);\n this._setDisabled('rotateRightBtn', !hasImage || this.isAnimating);\n this._setDisabled('addMaskBtn', !hasImage || this.isAnimating);\n this._setDisabled('removeMaskBtn', !hasSelectedMask || this.isAnimating);\n this._setDisabled('removeAllMasksBtn', !hasMasks || this.isAnimating);\n this._setDisabled('mergeBtn', !hasImage || !hasMasks || this.isAnimating);\n this._setDisabled('downloadBtn', !hasImage || this.isAnimating);\n this._setDisabled('resetBtn', !hasImage || isDefaultTransform || this.isAnimating);\n this._setDisabled('undoBtn', !hasImage || this.isAnimating || !canUndo);\n this._setDisabled('redoBtn', !hasImage || this.isAnimating || !canRedo);\n this._setDisabled('cropBtn', !hasImage || this.isAnimating);\n this._setDisabled('applyCropBtn', true);\n this._setDisabled('cancelCropBtn', true);\n this._setDisabled('imageInput', this.isAnimating);\n this._setDisabled('uploadArea', this.isAnimating);\n }\n\n /**\n * Enables or disables a specific UI element (typically a button) by its key.\n * \n * @param {string} key - Key of the element in this.elements (e.g. 'zoomInBtn').\n * @param {boolean} disabled - If true, disables the element; otherwise enables.\n * @private\n */\n _setDisabled(key, disabled) {\n const element = document.getElementById(this.elements[key]);\n if (!element) return;\n if ('disabled' in element) {\n element.disabled = !!disabled;\n return;\n }\n\n if (disabled) {\n element.setAttribute('aria-disabled', 'true');\n element.style.pointerEvents = 'none';\n } else {\n element.removeAttribute('aria-disabled');\n element.style.pointerEvents = '';\n }\n }\n\n _isElementDisabled(element) {\n if (!element) return false;\n if ('disabled' in element) return !!element.disabled;\n return element.getAttribute('aria-disabled') === 'true';\n }\n\n /**\n * Automatically display and hide placeholders and containers based on the current image content\n * @private\n */\n _updatePlaceholderStatus() {\n if (!this.options.showPlaceholder) return;\n this._setPlaceholderVisible(!this.originalImage);\n }\n\n /**\n * Controls the display/hiding of the Placeholder and Canvas container.\n * @param {boolean} show - true displays the placeholder, false displays the canvas container\n * @private\n */\n _setPlaceholderVisible(show) {\n if (!this.placeholderElement) return;\n if (show) {\n this.placeholderElement.classList.remove('d-none');\n this.placeholderElement.classList.add('d-flex');\n this.containerElement.classList.add('d-none');\n } else {\n this.placeholderElement.classList.remove('d-flex');\n this.placeholderElement.classList.add('d-none');\n this.containerElement.classList.remove('d-none');\n }\n }\n\n /**\n * Cleans up and disposes of the canvas and related references.\n * Call this method to free memory and remove canvas listeners when the editor is no longer needed.\n * @public\n */\n dispose() {\n // Remove bound DOM event listeners\n try {\n for (const key in (this._handlersByElementKey || {})) {\n const handlers = this._handlersByElementKey[key] || [];\n const element = document.getElementById(this.elements[key]);\n if (!element) continue;\n handlers.forEach(handlerRecord => {\n try { element.removeEventListener(handlerRecord.eventName, handlerRecord.handler); } catch (error) { void error; }\n });\n }\n } catch (error) { void error; }\n\n if (this._cropRect) {\n try { this.canvas.remove(this._cropRect); } catch (e) { void e; }\n this._cropRect = null;\n }\n\n if (this.containerElement && this._containerOriginalOverflow !== undefined) {\n try { this.containerElement.style.overflow = this._containerOriginalOverflow; } catch (e) { void e; }\n }\n\n if (this.canvas) {\n try { this.canvas.dispose(); } catch (e) { void e; }\n this.canvas = null;\n this.canvasElement = null;\n this.isImageLoadedToCanvas = false;\n }\n this._handlersByElementKey = {};\n }\n }\n\n /**\n * A simple FIFO queue that guarantees animations are executed sequentially.\n * @class AnimationQueue\n */\n class AnimationQueue {\n /**\n * Creates a new AnimationQueue.\n *\n * @constructor\n */\n constructor() {\n /**\n * Internal queue holding animation descriptors.\n * @type {Array<{fn: Function, resolve: Function, reject: Function}>}\n */\n this.queue = [];\n /**\n * Flag indicating whether an animation is currently running.\n * @type {boolean}\n */\n this.running = false;\n }\n\n /**\n * Adds an animation function to the queue.\n *\n * @param {Function} animationFn A function that returns a Promise or any await-able.\n * @returns {Promise<*>} A Promise that resolves/rejects with the animation result.\n */\n async add(animationFn) {\n return new Promise((resolve, reject) => {\n // Push the animation into the queue.\n this.queue.push({ fn: animationFn, resolve, reject });\n // Start processing if it's not already running.\n if (!this.running) {\n this.processQueue();\n }\n });\n }\n\n /**\n * Internal helper that processes the animation queue sequentially until it is empty.\n *\n * @private\n * @returns {Promise<void>}\n */\n async processQueue() {\n if (this.queue.length === 0) {\n this.running = false;\n return;\n }\n\n this.running = true;\n const { fn, resolve, reject } = this.queue.shift();\n\n try {\n const result = await fn();\n resolve(result);\n } catch (error) {\n reject(error);\n }\n\n this.processQueue();\n }\n }\n\n /**\n * Command object encapsulating an executable action and its corresponding undo operation.\n * @class Command\n */\n class Command {\n /**\n * @param {Function} execute The function that performs the action.\n * @param {Function} undo The function that reverts the action.\n */\n constructor(execute, undo) {\n /**\n * Executes the command.\n * @type {Function}\n */\n this.execute = execute;\n /**\n * Undoes the command.\n * @type {Function}\n */\n this.undo = undo;\n }\n }\n\n /**\n * Manages a history of Command objects enabling undo/redo functionality.\n * @class HistoryManager\n */\n class HistoryManager {\n /**\n * @param {number} [maxSize=50] Maximum number of commands to keep in history.\n */\n constructor(maxSize = 50) {\n this.history = [];\n this.currentIndex = -1;\n this.maxSize = maxSize;\n this.pending = Promise.resolve();\n }\n\n enqueue(task) {\n const run = this.pending.then(task, task);\n this.pending = run.catch(() => {});\n return run;\n }\n\n /**\n * Executes a new command and pushes it onto the history stack.\n * Truncates any \"future\" history when branching.\n *\n * @param {Command} command The command to execute.\n * @returns {void}\n */\n execute(command) {\n // Perform the command.\n command.execute();\n this.push(command);\n }\n\n /**\n * Pushes an already-applied command onto the history stack.\n * Truncates any \"future\" history when branching.\n *\n * @param {Command} command The command to push.\n * @returns {void}\n */\n push(command) {\n // Remove any commands that are ahead of the current index.\n if (this.currentIndex < this.history.length - 1) {\n this.history = this.history.slice(0, this.currentIndex + 1);\n }\n\n // Add the new command.\n this.history.push(command);\n\n // Maintain the max size of the buffer.\n if (this.history.length > this.maxSize) {\n this.history.shift(); // Remove the oldest command.\n } else {\n this.currentIndex++;\n }\n }\n\n /**\n * Checks whether an undo operation is possible.\n *\n * @returns {boolean} True if undo can be performed.\n */\n canUndo() {\n return this.currentIndex >= 0;\n }\n\n /**\n * Checks whether a redo operation is possible.\n *\n * @returns {boolean} True if redo can be performed.\n */\n canRedo() {\n return this.currentIndex < this.history.length - 1;\n }\n\n /**\n * Undoes the last executed command if possible.\n *\n * @returns {void}\n */\n undo() {\n return this.enqueue(async () => {\n if (this.currentIndex >= 0) {\n const index = this.currentIndex;\n await this.history[index].undo();\n this.currentIndex = index - 1;\n }\n });\n }\n\n /**\n * Redoes the next command in history if possible.\n *\n * @returns {void}\n */\n redo() {\n return this.enqueue(async () => {\n if (this.currentIndex < this.history.length - 1) {\n const index = this.currentIndex + 1;\n await this.history[index].execute();\n this.currentIndex = index;\n }\n });\n }\n }\n\nexport { ImageEditor };\nexport default ImageEditor;\n"],
5
+ "mappings": "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",
6
+ "names": ["fabricModule", "fabric", "getGlobalScope", "getGlobalFabric", "scope", "setFabric", "fabricInstance", "ensureFabric", "ImageEditor", "options", "defaultLabel", "mask", "defaultCrop", "userLabel", "userCrop", "AnimationQueue", "HistoryManager", "value", "idMap", "defaults", "message", "error", "handler", "canvasElement", "containerElement", "initialWidth", "initialHeight", "containerWidth", "containerHeight", "event", "target", "masks", "objects", "object", "shouldResetScroll", "uploadAreaElement", "file", "rotationInputElement", "step", "parsedStep", "key", "eventName", "element", "reader", "imageBase64", "imageElement", "loadSource", "ratio", "targetWidth", "targetHeight", "resolve", "reject", "fabricImage", "imageWidth", "imageHeight", "viewport", "minWidth", "minHeight", "canvasWidth", "canvasHeight", "fitScale", "layout", "dataUrl", "quality", "offscreenCanvas", "w", "h", "iw", "ih", "numericValue", "roundedValue", "previousOverflow", "width", "height", "inlineOverflow", "inlineOverflowX", "inlineOverflowY", "computedOverflow", "computedOverflowX", "computedOverflowY", "style", "probe", "contentWidth", "contentHeight", "safetyMargin", "safeWidth", "safeHeight", "scrollbar", "hasVertical", "hasHorizontal", "effectiveWidth", "effectiveHeight", "i", "nextHasVertical", "nextHasHorizontal", "scale", "canvasSize", "strokeWidth", "opacity", "callback", "maskStyleBackups", "backup", "cornerSize", "jsonObject", "numericQuality", "format", "bounds", "left", "top", "roundEnd", "sourceX", "sourceY", "endX", "endY", "sourceWidth", "sourceHeight", "multiplier", "safeMultiplier", "scaledSourceX", "scaledSourceY", "scaledSourceWidth", "scaledSourceHeight", "sx", "sy", "sw", "sh", "fullDataUrl", "fabricObject", "coords", "boundingRect", "originX", "originY", "refPoint", "deltaX", "deltaY", "imageBounds", "size", "padding", "requiredWidth", "requiredHeight", "newWidth", "newHeight", "factor", "saveHistory", "targetScale", "topLeft", "scaleXAnimation", "scaleYAnimation", "degrees", "center", "newTopLeft", "before", "after", "err", "jsonString", "json", "canvasObjects", "baseScale", "imageScale", "max", "callbackError", "activeObject", "executedOnce", "command", "Command", "e", "metadata", "normalStyle", "hoverStyle", "mouseover", "mouseout", "config", "shapeType", "maskConfig", "firstOffset", "resolveValue", "fallback", "percent", "previousMask", "previousMaskRight", "polygonPoints", "point", "styles", "hasStyle", "property", "maskSettings", "maskId", "selectedMasks", "textObject", "labelText", "textOptions", "maskIndex", "label", "tl", "vx", "vy", "dist", "ux", "uy", "offset", "px", "py", "selected", "selectedMask", "originalStrokeWidth", "maskListElement", "listItemElement", "item", "isSelected", "beforeJson", "merged", "afterJson", "fileName", "exportImageArea", "base64", "link", "maskVisibilityBackups", "finalBase64", "mergeMask", "fileType", "safeFileType", "imageDataUrl", "convertedDataUrl", "binaryString", "mime", "byteIndex", "bytes", "restoreError", "state", "targetHandlers", "handlerRecord", "cropRect", "shouldHideMasks", "updates", "handleCropRectModified", "rectBounds", "shouldPreserveMasks", "preservedMasks", "maskBounds", "intersectsCrop", "croppedBase64", "scaleInputElement", "hasImage", "hasMasks", "hasSelectedMask", "isDefaultTransform", "canUndo", "canRedo", "disabled", "show", "handlers", "animationFn", "fn", "result", "execute", "undo", "maxSize", "task", "run", "index", "image_editor_default", "ImageEditor", "fabricInstance", "fabricModule", "setFabric", "esm_default", "image_editor_default"]
7
7
  }