{"version":3,"file":"EmailBuilder.js","sources":["../../src/js/DataTalksUtils/_fileReader.js","../../node_modules/lodash-es/_freeGlobal.js","../../node_modules/lodash-es/_root.js","../../node_modules/lodash-es/_Symbol.js","../../node_modules/lodash-es/_getRawTag.js","../../node_modules/lodash-es/_objectToString.js","../../node_modules/lodash-es/_baseGetTag.js","../../node_modules/lodash-es/isObjectLike.js","../../node_modules/lodash-es/isSymbol.js","../../node_modules/lodash-es/_arrayMap.js","../../node_modules/lodash-es/isArray.js","../../node_modules/lodash-es/_baseToString.js","../../node_modules/lodash-es/_trimmedEndIndex.js","../../node_modules/lodash-es/_baseTrim.js","../../node_modules/lodash-es/isObject.js","../../node_modules/lodash-es/toNumber.js","../../node_modules/lodash-es/identity.js","../../node_modules/lodash-es/isFunction.js","../../node_modules/lodash-es/_coreJsData.js","../../node_modules/lodash-es/_isMasked.js","../../node_modules/lodash-es/_toSource.js","../../node_modules/lodash-es/_baseIsNative.js","../../node_modules/lodash-es/_getValue.js","../../node_modules/lodash-es/_getNative.js","../../node_modules/lodash-es/_WeakMap.js","../../node_modules/lodash-es/_baseCreate.js","../../node_modules/lodash-es/_apply.js","../../node_modules/lodash-es/_copyArray.js","../../node_modules/lodash-es/_shortOut.js","../../node_modules/lodash-es/constant.js","../../node_modules/lodash-es/_defineProperty.js","../../node_modules/lodash-es/_baseSetToString.js","../../node_modules/lodash-es/_setToString.js","../../node_modules/lodash-es/_arrayEach.js","../../node_modules/lodash-es/_isIndex.js","../../node_modules/lodash-es/_baseAssignValue.js","../../node_modules/lodash-es/eq.js","../../node_modules/lodash-es/_assignValue.js","../../node_modules/lodash-es/_copyObject.js","../../node_modules/lodash-es/_overRest.js","../../node_modules/lodash-es/_baseRest.js","../../node_modules/lodash-es/isLength.js","../../node_modules/lodash-es/isArrayLike.js","../../node_modules/lodash-es/_isIterateeCall.js","../../node_modules/lodash-es/_createAssigner.js","../../node_modules/lodash-es/_isPrototype.js","../../node_modules/lodash-es/_baseTimes.js","../../node_modules/lodash-es/_baseIsArguments.js","../../node_modules/lodash-es/isArguments.js","../../node_modules/lodash-es/stubFalse.js","../../node_modules/lodash-es/isBuffer.js","../../node_modules/lodash-es/_baseIsTypedArray.js","../../node_modules/lodash-es/_baseUnary.js","../../node_modules/lodash-es/_nodeUtil.js","../../node_modules/lodash-es/isTypedArray.js","../../node_modules/lodash-es/_arrayLikeKeys.js","../../node_modules/lodash-es/_overArg.js","../../node_modules/lodash-es/_nativeKeys.js","../../node_modules/lodash-es/_baseKeys.js","../../node_modules/lodash-es/keys.js","../../node_modules/lodash-es/_nativeKeysIn.js","../../node_modules/lodash-es/_baseKeysIn.js","../../node_modules/lodash-es/keysIn.js","../../node_modules/lodash-es/_isKey.js","../../node_modules/lodash-es/_nativeCreate.js","../../node_modules/lodash-es/_hashClear.js","../../node_modules/lodash-es/_hashDelete.js","../../node_modules/lodash-es/_hashGet.js","../../node_modules/lodash-es/_hashHas.js","../../node_modules/lodash-es/_hashSet.js","../../node_modules/lodash-es/_Hash.js","../../node_modules/lodash-es/_listCacheClear.js","../../node_modules/lodash-es/_assocIndexOf.js","../../node_modules/lodash-es/_listCacheDelete.js","../../node_modules/lodash-es/_listCacheGet.js","../../node_modules/lodash-es/_listCacheHas.js","../../node_modules/lodash-es/_listCacheSet.js","../../node_modules/lodash-es/_ListCache.js","../../node_modules/lodash-es/_Map.js","../../node_modules/lodash-es/_mapCacheClear.js","../../node_modules/lodash-es/_isKeyable.js","../../node_modules/lodash-es/_getMapData.js","../../node_modules/lodash-es/_mapCacheDelete.js","../../node_modules/lodash-es/_mapCacheGet.js","../../node_modules/lodash-es/_mapCacheHas.js","../../node_modules/lodash-es/_mapCacheSet.js","../../node_modules/lodash-es/_MapCache.js","../../node_modules/lodash-es/memoize.js","../../node_modules/lodash-es/_memoizeCapped.js","../../node_modules/lodash-es/_stringToPath.js","../../node_modules/lodash-es/toString.js","../../node_modules/lodash-es/_castPath.js","../../node_modules/lodash-es/_toKey.js","../../node_modules/lodash-es/_baseGet.js","../../node_modules/lodash-es/get.js","../../node_modules/lodash-es/_arrayPush.js","../../node_modules/lodash-es/_getPrototype.js","../../node_modules/lodash-es/isPlainObject.js","../../node_modules/lodash-es/_baseSlice.js","../../node_modules/lodash-es/_castSlice.js","../../node_modules/lodash-es/_hasUnicode.js","../../node_modules/lodash-es/_asciiToArray.js","../../node_modules/lodash-es/_unicodeToArray.js","../../node_modules/lodash-es/_stringToArray.js","../../node_modules/lodash-es/_createCaseFirst.js","../../node_modules/lodash-es/upperFirst.js","../../node_modules/lodash-es/capitalize.js","../../node_modules/lodash-es/_arrayReduce.js","../../node_modules/lodash-es/_basePropertyOf.js","../../node_modules/lodash-es/_deburrLetter.js","../../node_modules/lodash-es/deburr.js","../../node_modules/lodash-es/_asciiWords.js","../../node_modules/lodash-es/_hasUnicodeWord.js","../../node_modules/lodash-es/_unicodeWords.js","../../node_modules/lodash-es/words.js","../../node_modules/lodash-es/_createCompounder.js","../../node_modules/lodash-es/camelCase.js","../../node_modules/lodash-es/_stackClear.js","../../node_modules/lodash-es/_stackDelete.js","../../node_modules/lodash-es/_stackGet.js","../../node_modules/lodash-es/_stackHas.js","../../node_modules/lodash-es/_stackSet.js","../../node_modules/lodash-es/_Stack.js","../../node_modules/lodash-es/_baseAssign.js","../../node_modules/lodash-es/_baseAssignIn.js","../../node_modules/lodash-es/_cloneBuffer.js","../../node_modules/lodash-es/_arrayFilter.js","../../node_modules/lodash-es/stubArray.js","../../node_modules/lodash-es/_getSymbols.js","../../node_modules/lodash-es/_copySymbols.js","../../node_modules/lodash-es/_getSymbolsIn.js","../../node_modules/lodash-es/_copySymbolsIn.js","../../node_modules/lodash-es/_baseGetAllKeys.js","../../node_modules/lodash-es/_getAllKeys.js","../../node_modules/lodash-es/_getAllKeysIn.js","../../node_modules/lodash-es/_DataView.js","../../node_modules/lodash-es/_Promise.js","../../node_modules/lodash-es/_Set.js","../../node_modules/lodash-es/_getTag.js","../../node_modules/lodash-es/_initCloneArray.js","../../node_modules/lodash-es/_Uint8Array.js","../../node_modules/lodash-es/_cloneArrayBuffer.js","../../node_modules/lodash-es/_cloneDataView.js","../../node_modules/lodash-es/_cloneRegExp.js","../../node_modules/lodash-es/_cloneSymbol.js","../../node_modules/lodash-es/_cloneTypedArray.js","../../node_modules/lodash-es/_initCloneByTag.js","../../node_modules/lodash-es/_initCloneObject.js","../../node_modules/lodash-es/_baseIsMap.js","../../node_modules/lodash-es/isMap.js","../../node_modules/lodash-es/_baseIsSet.js","../../node_modules/lodash-es/isSet.js","../../node_modules/lodash-es/_baseClone.js","../../node_modules/lodash-es/cloneDeep.js","../../node_modules/lodash-es/_setCacheAdd.js","../../node_modules/lodash-es/_setCacheHas.js","../../node_modules/lodash-es/_SetCache.js","../../node_modules/lodash-es/_arraySome.js","../../node_modules/lodash-es/_cacheHas.js","../../node_modules/lodash-es/_equalArrays.js","../../node_modules/lodash-es/_mapToArray.js","../../node_modules/lodash-es/_setToArray.js","../../node_modules/lodash-es/_equalByTag.js","../../node_modules/lodash-es/_equalObjects.js","../../node_modules/lodash-es/_baseIsEqualDeep.js","../../node_modules/lodash-es/_baseIsEqual.js","../../node_modules/lodash-es/_createBaseFor.js","../../node_modules/lodash-es/_baseFor.js","../../node_modules/lodash-es/now.js","../../node_modules/lodash-es/debounce.js","../../node_modules/lodash-es/_assignMergeValue.js","../../node_modules/lodash-es/isArrayLikeObject.js","../../node_modules/lodash-es/_safeGet.js","../../node_modules/lodash-es/toPlainObject.js","../../node_modules/lodash-es/_baseMergeDeep.js","../../node_modules/lodash-es/_baseMerge.js","../../node_modules/lodash-es/mergeWith.js","../../node_modules/lodash-es/last.js","../../node_modules/lodash-es/_parent.js","../../node_modules/lodash-es/isEqual.js","../../node_modules/lodash-es/kebabCase.js","../../node_modules/lodash-es/merge.js","../../node_modules/lodash-es/_baseUnset.js","../../node_modules/lodash-es/snakeCase.js","../../node_modules/lodash-es/startCase.js","../../node_modules/lodash-es/toLower.js","../../node_modules/lodash-es/unset.js","../../node_modules/color2k/dist/index.exports.import.es.mjs","../../src/js/DataTalksUtils/_utilFunctions.js","../../src/js/DataTalksUtils/_TranslationFramework.js","../../src/js/grapesjs/assets/common/functions/_utilFunctions.js","../../src/js/grapesjs/assets/components/_componentsUtils.js","../../src/js/grapesjs/config/_config.js","../../src/js/grapesjs/assets/components/ListItem/_render.js","../../src/js/grapesjs/assets/componentsDefaults/_listItemDefaults.js","../../src/js/grapesjs/assets/componentsDefaults/_button.js","../../src/js/grapesjs/assets/componentsDefaults/_imageWrapper.js","../../src/js/grapesjs/assets/componentsDefaults/_linksList.js","../../src/js/grapesjs/assets/componentsDefaults/_text.js","../../src/js/grapesjs/assets/componentsDefaults/_space.js","../../src/js/grapesjs/assets/componentsDefaults/_margins.js","../../src/js/grapesjs/assets/componentsDefaults/_common.js","../../src/js/grapesjs/assets/componentsDefaults/_componentsDefaults.js","../../src/js/grapesjs/assets/components/common/methods/_baseMethods.js","../../src/js/grapesjs/assets/components/ListItem/_toHtml.js","../../src/js/grapesjs/assets/components/ListItem/_build.js","../../src/js/grapesjs/assets/components/common/_updateCommonStyle.js","../../src/js/grapesjs/assets/components/List/_render.js","../../src/js/grapesjs/assets/components/List/_methods.js","../../src/js/grapesjs/assets/components/List/trait/_trait.js","../../src/js/grapesjs/assets/components/List/_buildTrait.js","../../src/js/grapesjs/assets/components/List/_getComputedStyle.js","../../src/js/grapesjs/assets/components/common/htmlTemplates/_margins.js","../../src/js/grapesjs/assets/components/List/_toHtml.js","../../src/js/grapesjs/assets/components/List/_build.js","../../src/js/grapesjs/assets/components/header/trait/_trait.js","../../src/js/grapesjs/assets/components/header/_render.js","../../src/js/grapesjs/assets/components/header/_getComputedStyle.js","../../src/js/grapesjs/assets/components/header/_toHtml.js","../../src/js/grapesjs/assets/components/header/_build.js","../../src/js/grapesjs/assets/components/LinksList/_render.js","../../src/js/grapesjs/assets/components/LinksList/_getComputedStyle.js","../../src/js/grapesjs/assets/components/LinksList/_toHtml.js","../../src/js/grapesjs/assets/components/LinksList/_build.js","../../src/js/grapesjs/assets/components/hero/trait/_trait.js","../../src/js/grapesjs/assets/components/hero/_render.js","../../src/js/grapesjs/assets/components/hero/_getComputedStyle.js","../../src/js/grapesjs/assets/components/hero/_toHtml.js","../../src/js/grapesjs/assets/components/hero/_build.js","../../src/js/grapesjs/assets/components/footer/_render.js","../../src/js/grapesjs/assets/components/footer/trait/_trait.js","../../src/js/grapesjs/assets/components/footer/_buildTrait.js","../../src/js/grapesjs/assets/components/footer/_methods.js","../../src/js/grapesjs/assets/components/footer/_getComputedStyle.js","../../src/js/grapesjs/assets/components/common/htmlTemplates/_borderWrapper.js","../../src/js/grapesjs/assets/components/footer/_toHtml.js","../../src/js/grapesjs/assets/components/footer/_build.js","../../src/js/grapesjs/assets/components/CallToAction/trait/_trait.js","../../src/js/grapesjs/assets/components/CallToAction/_render.js","../../src/js/grapesjs/assets/components/CallToAction/_getComputedStyle.js","../../src/js/grapesjs/assets/components/CallToAction/_toHtml.js","../../src/js/grapesjs/assets/components/CallToAction/_build.js","../../node_modules/html-to-image/es/util.js","../../node_modules/html-to-image/es/clone-pseudos.js","../../node_modules/html-to-image/es/mimes.js","../../node_modules/html-to-image/es/dataurl.js","../../node_modules/html-to-image/es/clone-node.js","../../node_modules/html-to-image/es/embed-resources.js","../../node_modules/html-to-image/es/embed-images.js","../../node_modules/html-to-image/es/apply-style.js","../../node_modules/html-to-image/es/embed-webfonts.js","../../node_modules/html-to-image/es/index.js","../../src/js/grapesjs/assets/components/ImagePlaceholder/_buildSvg.js","../../src/js/grapesjs/assets/components/ImagePlaceholder/_buildHtml.js","../../src/js/grapesjs/assets/components/ImagePlaceholder/_build.js","../../src/js/grapesjs/assets/components/atoms/button/_render.js","../../src/js/grapesjs/assets/components/atoms/button/_getComputedStyle.js","../../src/js/grapesjs/assets/components/atoms/button/_toHtml.js","../../src/js/grapesjs/assets/components/atoms/button/_build.js","../../src/js/grapesjs/assets/components/atoms/text/_render.js","../../src/js/grapesjs/assets/components/atoms/text/_getComputedStyle.js","../../src/js/grapesjs/assets/components/atoms/text/_toHtml.js","../../src/js/grapesjs/assets/components/atoms/text/_build.js","../../src/js/grapesjs/assets/components/atoms/imageWrapper/_render.js","../../src/js/grapesjs/assets/components/atoms/imageWrapper/_getComputedStyle.js","../../src/js/grapesjs/assets/components/atoms/imageWrapper/_toHtml.js","../../src/js/grapesjs/assets/components/atoms/imageWrapper/_build.js","../../src/js/grapesjs/assets/components/atoms/space/_render.js","../../src/js/grapesjs/assets/components/atoms/space/_toHtml.js","../../src/js/grapesjs/assets/components/atoms/space/_build.js","../../src/js/grapesjs/assets/components/atoms/link/_toHtml.js","../../src/js/grapesjs/assets/components/atoms/link/_build.js","../../src/js/grapesjs/assets/components/margins/_render.js","../../src/js/grapesjs/assets/components/margins/_getComputedStyle.js","../../src/js/grapesjs/assets/components/common/methods/_getInnerHTML.js","../../src/js/grapesjs/assets/components/margins/_toHtml.js","../../src/js/grapesjs/assets/components/margins/_build.js","../../src/js/grapesjs/assets/components/wrapper/_toHtml.js","../../src/js/grapesjs/assets/components/wrapper/_build.js","../../src/js/grapesjs/assets/components/_registerComponent.js","../../src/js/grapesjs/assets/components/_components.js","../../src/js/grapesjs/assets/blocks/icons/_icons.js","../../src/js/grapesjs/assets/blocks/_blocks.js","../../src/js/DataTalksUI/Dropdown/_dropdownItem.js","../../src/js/icons/_component.js","../../src/js/icons/_icons.js","../../node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs","../../node_modules/@floating-ui/core/dist/floating-ui.core.mjs","../../node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs","../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs","../../src/js/DataTalksUI/Dropdown/_dropdown.js","../../src/js/DataTalksUI/Dropdown/_DropdownButtonItem.js","../../src/js/DataTalksUI/Dropdown/_DropdownButton.js","../../node_modules/lexical/Lexical.dev.mjs","../../node_modules/lexical/Lexical.mjs","../../src/js/DataTalksUI/textEditor/_lexicalUtils.js","../../src/js/DataTalksUI/textEditor/_ParagraphNode.js","../../node_modules/@lexical/selection/LexicalSelection.dev.mjs","../../node_modules/@lexical/selection/LexicalSelection.mjs","../../node_modules/@lexical/utils/LexicalUtils.dev.mjs","../../node_modules/@lexical/utils/LexicalUtils.mjs","../../node_modules/@lexical/html/LexicalHtml.dev.mjs","../../node_modules/@lexical/html/LexicalHtml.mjs","../../node_modules/@lexical/link/LexicalLink.dev.mjs","../../node_modules/@lexical/link/LexicalLink.mjs","../../node_modules/@lexical/mark/LexicalMark.dev.mjs","../../node_modules/@lexical/mark/LexicalMark.mjs","../../node_modules/@lexical/clipboard/LexicalClipboard.dev.mjs","../../node_modules/@lexical/clipboard/LexicalClipboard.mjs","../../node_modules/@lexical/table/LexicalTable.dev.mjs","../../node_modules/@lexical/table/LexicalTable.mjs","../../src/js/DataTalksUI/textEditor/_TreeView.ts","../../node_modules/@lexical/history/LexicalHistory.dev.mjs","../../node_modules/@lexical/history/LexicalHistory.mjs","../../src/js/DataTalksUI/textEditor/_ObjectNode.js","../../src/js/DataTalksUI/textEditor/_LinkNode.js","../../node_modules/@lexical/rich-text/LexicalRichText.dev.mjs","../../node_modules/@lexical/rich-text/LexicalRichText.mjs","../../src/js/DataTalksUI/textEditor/_HeadingNode.js","../../node_modules/@lexical/plain-text/LexicalPlainText.dev.mjs","../../node_modules/@lexical/plain-text/LexicalPlainText.mjs","../../node_modules/prismjs/prism.js","../../node_modules/prismjs/components/prism-clike.js","../../node_modules/prismjs/components/prism-javascript.js","../../node_modules/prismjs/components/prism-markup.js","../../node_modules/prismjs/components/prism-markdown.js","../../node_modules/prismjs/components/prism-c.js","../../node_modules/prismjs/components/prism-css.js","../../node_modules/prismjs/components/prism-objectivec.js","../../node_modules/prismjs/components/prism-sql.js","../../node_modules/prismjs/components/prism-powershell.js","../../node_modules/prismjs/components/prism-python.js","../../node_modules/prismjs/components/prism-rust.js","../../node_modules/prismjs/components/prism-swift.js","../../node_modules/prismjs/components/prism-typescript.js","../../node_modules/prismjs/components/prism-java.js","../../node_modules/prismjs/components/prism-cpp.js","../../node_modules/@lexical/code/LexicalCode.dev.mjs","../../node_modules/@lexical/code/LexicalCode.prod.mjs","../../node_modules/@lexical/code/LexicalCode.mjs","../../node_modules/@lexical/list/LexicalList.dev.mjs","../../node_modules/@lexical/list/LexicalList.mjs","../../src/js/DataTalksUI/textEditor/_listPlugin.js","../../src/js/DataTalksUI/textEditor/_toggleLink.js","../../src/js/DataTalksUI/textEditor/_linkPlugin.js","../../src/js/DataTalksUI/textEditor/_theme.js","../../src/js/DataTalksUI/textEditor/_onChangePlugin.js","../../src/js/DataTalksUI/textEditor/_onSelectionChangePlugin.js","../../src/js/DataTalksUI/textEditor/_formatters.js","../../src/js/DataTalksUI/textEditor/_modifiers.js","../../src/js/DataTalksUI/textEditor/_utils.js","../../src/js/DataTalksUI/textEditor/_clearFormattingPlugin.js","../../src/js/DataTalksUI/textEditor/_TextEditorDropdown.js","../../src/js/DataTalksUI/textEditor/_TextEditorPopup.js","../../src/js/DataTalksUI/textEditor/_TextEditorObject.js","../../src/js/DataTalksUI/textEditor/_ToolbarObject.js","../../src/js/DataTalksUI/textEditor/_TextEditorToolbar.js","../../src/js/DataTalksUI/textEditor/_TextEditor.js","../../src/js/DataTalksUI/textEditor/_UrlEditor.js","../../src/js/DataTalksUI/alwan/constants/classnames.js","../../src/js/DataTalksUI/alwan/constants/globals.js","../../src/js/DataTalksUI/alwan/core/events/binder.js","../../src/js/DataTalksUI/alwan/utils/object.js","../../src/js/DataTalksUI/alwan/utils/is.js","../../src/js/DataTalksUI/alwan/utils/dom.js","../../src/js/DataTalksUI/alwan/components/reference.js","../../src/js/DataTalksUI/alwan/utils/number.js","../../src/js/DataTalksUI/alwan/lib/popover.js","../../src/js/DataTalksUI/alwan/components/App.js","../../src/js/DataTalksUI/alwan/assets/svg.js","../../src/js/DataTalksUI/alwan/colors/stringify.js","../../src/js/DataTalksUI/alwan/components/Inputs.js","../../src/js/DataTalksUI/alwan/components/Palette.js","../../src/js/DataTalksUI/alwan/components/Sliders.js","../../src/js/DataTalksUI/alwan/colors/parser.js","../../src/js/DataTalksUI/alwan/components/Swatches.js","../../src/js/DataTalksUI/alwan/components/Utility.js","../../src/js/DataTalksUI/alwan/core/component.js","../../src/js/DataTalksUI/alwan/colors/converter.js","../../src/js/DataTalksUI/alwan/core/color.js","../../src/js/DataTalksUI/alwan/core/events/dispatcher.js","../../src/js/DataTalksUI/alwan/constants/defaults.js","../../src/js/DataTalksUI/alwan/index.js","../../src/js/DataTalksUI/colorPicker/_colorPickerInputAlt.js","../../src/js/DataTalksUI/colorPicker/_colorPicker.js","../../src/js/DataTalksUI/_Input.js","../../src/js/DataTalksUI/_ToggleableSection.js","../../src/js/DataTalksUI/_ChoosableSection.js","../../src/js/DataTalksUI/_ToggleButton.js","../../src/js/DataTalksUI/_button.js","../../src/js/DataTalksUI/_InputNumber.js","../../src/js/DataTalksUI/_accordion.js","../../src/js/DataTalksUI/_LinkedInputs.js","../../src/js/DataTalksUI/_radioButtonGroupItem.js","../../src/js/DataTalksUI/_radioButtonGroup.js","../../src/js/DataTalksUI/_section.js","../../src/js/DataTalksUI/_SectionItem.js","../../src/js/DataTalksUI/_Tabs.js","../../src/js/DataTalksUI/_TabItem.js","../../src/js/DataTalksUI/_InputLabel.js","../../src/js/DataTalksUI/_Modal.js","../../src/js/DataTalksUI/_Alert.js","../../src/js/DataTalksUI/_Popup.js","../../src/js/grapesjs/_emailBuilderUI.js","../../src/js/grapesjs/assets/common/functions/_textEditorCommonActions.js","../../src/js/grapesjs/assets/traits/Header/components/contentTab/linksAccordion/_accordionContent.js","../../src/js/grapesjs/assets/traits/Header/components/contentTab/linksAccordion/_itemAccordionTitle.js","../../src/js/grapesjs/assets/traits/common/imgFileInput/_imgFileInputPreview.js","../../src/js/grapesjs/assets/traits/Footer/components/contentTab/linksAccordion/_accordionContent.js","../../src/js/grapesjs/assets/traits/Footer/components/contentTab/linksAccordion/_itemAccordionTitle.js","../../src/js/grapesjs/assets/traits/_traitsTypes.js","../../src/js/grapesjs/assets/traits/common/_localize.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_borderRadius.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_alignment.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_lineHeight.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/_button.js","../../src/js/grapesjs/assets/traits/atoms/Button/components/_styleTab.js","../../src/js/grapesjs/assets/traits/common/_buttonEditorCbs.js","../../src/js/grapesjs/assets/traits/Hero/components/contentTab/_buttonAccordion.js","../../src/js/grapesjs/assets/traits/atoms/Button/components/_contentTab.js","../../src/js/grapesjs/assets/traits/common/_styleTabOptions.js","../../src/js/grapesjs/assets/traits/Header/components/styleTab/_backgroundAccordion.js","../../src/js/grapesjs/assets/traits/Header/components/styleTab/marginsAccordion/_marginButtonsGroup.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_marginsColor.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_marginsController.js","../../src/js/grapesjs/assets/traits/Header/components/styleTab/_marginsAccordion.js","../../src/js/grapesjs/assets/traits/Hero/components/styleTab/buttonAccordion/_buttonBorderRadius.js","../../src/js/grapesjs/assets/traits/Hero/components/styleTab/buttonAccordion/_buttonAlignment.js","../../src/js/grapesjs/assets/traits/Hero/components/styleTab/_buttonAccordion.js","../../src/js/grapesjs/assets/traits/Hero/components/styleTab/_textAccordion.js","../../node_modules/nouislider/dist/nouislider.mjs","../../src/js/grapesjs/assets/traits/common/rangeSlider/_slider.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_slider.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_sliderOrInput.js","../../src/js/grapesjs/assets/traits/Hero/components/styleTab/_spacingAccordion.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/_border.js","../../src/js/grapesjs/assets/traits/CallToAction/components/_styleTab.js","../../src/js/grapesjs/assets/traits/Hero/components/contentTab/_textAccordion.js","../../src/js/grapesjs/assets/traits/CallToAction/components/_contentTab.js","../../src/js/grapesjs/assets/traits/Header/components/styleTab/linksAccordion/_letterSpacing.js","../../src/js/grapesjs/assets/traits/Header/components/styleTab/linksAccordion/_linksBorderRadius.js","../../src/js/grapesjs/assets/traits/Header/components/styleTab/_linksAccordion.js","../../src/js/grapesjs/assets/traits/Header/components/styleTab/spacingAccordion/_spacingInput.js","../../src/js/grapesjs/assets/traits/Header/components/styleTab/_spacingAccordion.js","../../src/js/grapesjs/assets/traits/Footer/components/styleTab/_layoutAccordion.js","../../src/js/grapesjs/assets/traits/Footer/components/styleTab/_listAccordion.js","../../src/js/grapesjs/assets/traits/Footer/components/_styleTab.js","../../src/js/grapesjs/assets/traits/Header/components/contentTab/linksAccordion/_items.js","../../node_modules/sortablejs/modular/sortable.esm.js","../../src/js/grapesjs/assets/traits/Header/components/contentTab/_linksAccordion.js","../../src/js/grapesjs/assets/traits/Footer/components/_contentTab.js","../../src/js/grapesjs/assets/traits/Header/components/styleTab/_imageAccordion.js","../../src/js/grapesjs/assets/traits/Header/components/_styleTab.js","../../src/js/grapesjs/assets/traits/Header/components/contentTab/_imageAccordion.js","../../src/js/grapesjs/assets/traits/Header/components/_contentTab.js","../../src/js/grapesjs/assets/traits/Hero/components/_styleTab.js","../../src/js/grapesjs/assets/traits/Hero/components/contentTab/_titleAccordion.js","../../src/js/grapesjs/assets/traits/Hero/components/_contentTab.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_margins.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/_margins.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_layout.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/_layout.js","../../src/js/grapesjs/assets/traits/List/components/styleTab/_spacingAccordion.js","../../src/js/grapesjs/assets/traits/List/components/styleTab/_alignmentAccordion.js","../../src/js/grapesjs/assets/traits/List/components/_styleTab.js","../../src/js/grapesjs/assets/traits/List/components/_contentTab.js","../../src/js/grapesjs/assets/traits/linksList/components/_styleTab.js","../../src/js/grapesjs/assets/traits/linksList/components/_contentTab.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/_image.js","../../src/js/grapesjs/assets/traits/atoms/ImageWrapper/components/_styleTab.js","../../src/js/grapesjs/assets/traits/commonAccordions/content/_image.js","../../src/js/grapesjs/assets/traits/atoms/ImageWrapper/components/_contentTab.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_color.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_fonts.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_weight.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_borderStyle.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/_text.js","../../src/js/grapesjs/assets/traits/atoms/Text/components/_styleTab.js","../../src/js/grapesjs/assets/traits/commonAccordions/content/_text.js","../../src/js/grapesjs/assets/traits/atoms/Text/components/_contentTab.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/_background.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/_spacing.js","../../src/js/grapesjs/assets/traits/base/components/_styleTab.js","../../src/js/grapesjs/assets/traits/base/components/_contentTab.js","../../src/js/grapesjs/assets/traits/atoms/Space/components/_styleTab.js","../../src/js/grapesjs/assets/traits/commonAccordions/style/common/_orientation.js","../../src/js/grapesjs/assets/traits/commonAccordions/content/_space.js","../../src/js/grapesjs/assets/traits/atoms/Space/components/_contentTab.js","../../src/js/grapesjs/assets/traits/_exportComponentTabs.js","../../src/js/grapesjs/assets/traits/Header/components/contentTab/linksAccordion/_createItem.js","../../src/js/grapesjs/assets/traits/abstracts/_headerItem.js","../../src/js/grapesjs/assets/traits/_itemsListMutation.js","../../src/js/grapesjs/assets/traits/List/components/contentTab/_accordionContent.js","../../src/js/grapesjs/assets/traits/List/components/contentTab/_itemAccordionTitle.js","../../src/js/grapesjs/assets/traits/_createInput.js","../../src/js/grapesjs/assets/traits/_build.js","../../src/js/grapesjs/assets/traits/_register.js","../../src/js/grapesjs/assets/traits/_traits.js","../../src/js/grapesjs/assets/commands/assetSet/_build.js","../../src/js/grapesjs/assets/commands/changeContext/_build.js","../../src/js/grapesjs/assets/commands/clearStorage/_build.js","../../src/js/grapesjs/assets/commands/exportAll/_build.js","../../src/js/_cssInliner.js","../../src/js/grapesjs/_responsiveEmailTemplate.js","../../src/js/grapesjs/assets/common/functions/_getEditorHtmlInlined.js","../../src/js/grapesjs/assets/commands/exportHtml/_build.js","../../src/js/grapesjs/assets/commands/openContentTraits/_build.js","../../src/js/grapesjs/assets/commands/openGeneral/_textAccordionContent.js","../../src/js/grapesjs/assets/commands/openGeneral/_textStylesAccordion.js","../../src/js/grapesjs/assets/commands/openGeneral/components/_buttonsAccordion.js","../../src/js/grapesjs/assets/commands/openGeneral/_build.js","../../src/js/grapesjs/assets/commands/openStyleTraits/_build.js","../../src/js/grapesjs/assets/commands/openTraitManager/_build.js","../../src/js/grapesjs/assets/commands/showMainViewPanel/_build.js","../../src/js/grapesjs/assets/commands/showSavePanel/_build.js","../../src/js/grapesjs/assets/commands/showTraitsViewPanel/_build.js","../../src/js/grapesjs/assets/common/_importConfig.js","../../src/js/grapesjs/assets/commands/importConfig/_openModal.js","../../src/js/grapesjs/assets/commands/importConfig/_build.js","../../src/js/grapesjs/assets/common/functions/_exportConfig.js","../../src/js/grapesjs/assets/commands/exportConfig/_build.js","../../src/js/grapesjs/assets/commands/_downloadTemplate.js","../../src/js/grapesjs/assets/common/functions/_styleDiffChecker.js","../../src/js/grapesjs/assets/common/functions/_storageDiffEditor.js","../../src/js/grapesjs/assets/commands/checkDiffStorage/_build.js","../../src/js/grapesjs/assets/commands/goBack/_build.js","../../src/js/grapesjs/assets/commands/previewEmail/_build.js","../../src/js/grapesjs/assets/commands/changeGeneralStyleProp/_build.js","../../src/js/grapesjs/assets/commands/_undo.js","../../src/js/grapesjs/assets/commands/_redo.js","../../src/js/grapesjs/assets/commands/_copy.js","../../src/js/grapesjs/assets/commands/_paste.js","../../src/js/grapesjs/assets/commands/htmlPreview/_openModal.js","../../src/js/grapesjs/assets/commands/htmlPreview/_build.js","../../src/js/grapesjs/assets/commands/_registerCommand.js","../../src/js/grapesjs/assets/commands/_commands.js","../../src/js/grapesjs/locale/en.js","../../src/js/grapesjs/assets/panels/assets/_actionsDropdown.js","../../src/js/grapesjs/assets/panels/assets/_titleInput.js","../../src/js/grapesjs/assets/panels/assets/_zoomSlider.js","../../src/js/grapesjs/_panelConfig.js","../../src/js/grapesjs/assets/components/_componentsRender.js","../../src/js/grapesjs/assets/_componentBuilderUtils.js","../../src/js/grapesjs/assets/components/_getComputedStyle.js","../../src/js/grapesjs/assets/components/_baseToHtml.js","../../src/js/grapesjs/assets/_componentBuilder.js","../../src/js/grapesjs/_customMethods.js","../../src/js/grapesjs/_customProps.js","../../src/js/grapesjs/assets/blocks/_blocksUi.js","../../src/js/grapesjs/eventListeners/_blockCustom.js","../../src/js/grapesjs/eventListeners/_components.js","../../src/js/grapesjs/assets/common/_loadData.js","../../src/js/grapesjs/assets/common/_importTemplate.js","../../src/js/grapesjs/assets/common/_editorDropConfigFile.js","../../src/js/grapesjs/eventListeners/_load.js","../../src/js/grapesjs/eventListeners/_commands.js","../../src/js/grapesjs/eventListeners/_update.js","../../src/js/grapesjs/eventListeners/_undoRedo.js","../../src/js/grapesjs/eventListeners/_storage.js","../../src/js/grapesjs/_eventListeners.js","../../src/js/grapesjs/ScopeManager/_scopeManager.js","../../src/js/grapesjs/_addDynamicLinks.js","../../src/js/grapesjs/assets/common/functions/_getImagesInfo.js","../../src/js/grapesjs/assets/common/functions/_isImagePlaceholder.js","../../src/js/grapesjs/_getDataToStore.js","../../src/js/grapesjs/_applyGeneralStyles.js","../../src/js/grapesjs/_getLegacyStyles.js","../../src/js/grapesjs/_customBlocks.js","../../src/js/grapesjs/customComponents/common/_handlebarsAttributesMapping.js","../../src/js/grapesjs/customComponents/orderSummary/_index.js","../../src/js/grapesjs/customComponents/orderInfo/_index.js","../../src/js/grapesjs/_editor.js"],"sourcesContent":["/**\n * FileReaderWrapper\n * @namespace FileReaderWrapper\n */\n\n/**\n * The result of the file reading.\n * @typedef { Object } FileReaderWrapperResult\n * @property { boolean } success - Whether or not the data is successfully read.\n * @property { string } errorMessage - The reason for the error to be thrown.\n * @property { ProgressEvent } e - The {@link https://developer.mozilla.org/en-US/docs/Web/API/FileReader/progress_event|progress event} that is fired periodically as the FileReader reads data.\n * @memberof FileReaderWrapper\n */\n\n/**\n * Callback to handle a FileReader event.\n * @callback FileReaderEventCallback\n * @param {FileReaderWrapperResult} result - The result object of the file reading.\n * @memberof FileReaderWrapper\n */\n\n/**\n * Callback to handle a FileReader event.\n * @callback FileReaderWrapperCallback\n * @param {FileReader} fileReader - The {@link https://developer.mozilla.org/en-US/docs/Web/API/FileReader|FileReader} object itself.\n * @memberof FileReaderWrapper\n */\n\n/**\n * The object containing the callbacks for the file reader events\n * @typedef { Object } FileReaderEventCallbacks\n * @property { FileReaderEventCallback } onload - Fired when a read has completed successfully.\n * @property { FileReaderEventCallback } onerror - Fired when the read failed due to an error.\n * @property { FileReaderEventCallback } onabort - Fired when a read has been aborted.\n * @property { FileReaderWrapperCallback } dataRead - Fired when the data has been read from the blob, but no result is given.\n * @memberof FileReaderWrapper\n */\n\n/**\n * The options to pass in the file reader function\n * @typedef { Object } FileReaderWrapperOptions\n * @property { string } readMethod - The method to use to read data from the blob.\n * @property { FileReaderEventCallbacks } callbacks - The object containing the callbacks for the file reader events.\n * @memberof FileReaderWrapper\n */\n\n/**\n * Creates a file reader and calls callback functions passed through options.\n * @param {Blob} file - The {@link https://developer.mozilla.org/en-US/docs/Web/API/Blob|Blob} to read data from.\n * @param {FileReaderWrapperOptions} options - The options object.\n * @memberof FileReaderWrapper\n */\n\nexport default (file, options) => {\n\tlet result = {\n\t\tsuccess: true,\n\t\terrorMessage: '',\n\t\te: null\n\t};\n\n\tconst fileReader = new FileReader();\n\tfileReader.onload = function (e) {\n\t\tresult = {\n\t\t\t...result,\n\t\t\te\n\t\t};\n\t\tif (typeof options.callbacks.onload === 'function') {\n\t\t\toptions.callbacks.onload.call(fileReader, result);\n\t\t}\n\t};\n\tfileReader.onerror = function (e) {\n\t\tresult = {\n\t\t\t...{\n\t\t\t\tsuccess: false,\n\t\t\t\terrorMessage: fileReader.error,\n\t\t\t\te\n\t\t\t}\n\t\t};\n\t\tif (typeof options.callbacks.onerror === 'function') {\n\t\t\toptions.callbacks.onerror.call(fileReader, result);\n\t\t}\n\t};\n\tfileReader.onabort = function (e) {\n\t\tresult = {\n\t\t\t...{\n\t\t\t\tsuccess: false,\n\t\t\t\terrorMessage: 'File upload aborted',\n\t\t\t\te\n\t\t\t}\n\t\t};\n\t\tif (typeof options.callbacks.onabort === 'function') {\n\t\t\toptions.callbacks.onabort.call(fileReader, result);\n\t\t}\n\t};\n\tfileReader.readAsDataURL(file);\n\tif (typeof options.callbacks.dataRead === 'function') {\n\t\toptions.callbacks.dataRead.call(fileReader, fileReader);\n\t}\n};\n","/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nexport default freeGlobal;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nexport default root;\n","import root from './_root.js';\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nexport default Symbol;\n","import Symbol from './_Symbol.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n}\n\nexport default getRawTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","import Symbol from './_Symbol.js';\nimport getRawTag from './_getRawTag.js';\nimport objectToString from './_objectToString.js';\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n}\n\nexport default baseGetTag;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && baseGetTag(value) == symbolTag);\n}\n\nexport default isSymbol;\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","import Symbol from './_Symbol.js';\nimport arrayMap from './_arrayMap.js';\nimport isArray from './isArray.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolToString = symbolProto ? symbolProto.toString : undefined;\n\n/**\n * The base implementation of `_.toString` which doesn't convert nullish\n * values to empty strings.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\nfunction baseToString(value) {\n // Exit early for strings to avoid a performance hit in some environments.\n if (typeof value == 'string') {\n return value;\n }\n if (isArray(value)) {\n // Recursively convert values (susceptible to call stack limits).\n return arrayMap(value, baseToString) + '';\n }\n if (isSymbol(value)) {\n return symbolToString ? symbolToString.call(value) : '';\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nexport default baseToString;\n","/** Used to match a single whitespace character. */\nvar reWhitespace = /\\s/;\n\n/**\n * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace\n * character of `string`.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {number} Returns the index of the last non-whitespace character.\n */\nfunction trimmedEndIndex(string) {\n var index = string.length;\n\n while (index-- && reWhitespace.test(string.charAt(index))) {}\n return index;\n}\n\nexport default trimmedEndIndex;\n","import trimmedEndIndex from './_trimmedEndIndex.js';\n\n/** Used to match leading whitespace. */\nvar reTrimStart = /^\\s+/;\n\n/**\n * The base implementation of `_.trim`.\n *\n * @private\n * @param {string} string The string to trim.\n * @returns {string} Returns the trimmed string.\n */\nfunction baseTrim(string) {\n return string\n ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')\n : string;\n}\n\nexport default baseTrim;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","import baseTrim from './_baseTrim.js';\nimport isObject from './isObject.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = baseTrim(value);\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nexport default toNumber;\n","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nexport default identity;\n","import baseGetTag from './_baseGetTag.js';\nimport isObject from './isObject.js';\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nexport default isFunction;\n","import root from './_root.js';\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nexport default coreJsData;\n","import coreJsData from './_coreJsData.js';\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nexport default isMasked;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nexport default toSource;\n","import isFunction from './isFunction.js';\nimport isMasked from './_isMasked.js';\nimport isObject from './isObject.js';\nimport toSource from './_toSource.js';\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nexport default baseIsNative;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nexport default getValue;\n","import baseIsNative from './_baseIsNative.js';\nimport getValue from './_getValue.js';\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nexport default getNative;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar WeakMap = getNative(root, 'WeakMap');\n\nexport default WeakMap;\n","import isObject from './isObject.js';\n\n/** Built-in value references. */\nvar objectCreate = Object.create;\n\n/**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} proto The object to inherit from.\n * @returns {Object} Returns the new object.\n */\nvar baseCreate = (function() {\n function object() {}\n return function(proto) {\n if (!isObject(proto)) {\n return {};\n }\n if (objectCreate) {\n return objectCreate(proto);\n }\n object.prototype = proto;\n var result = new object;\n object.prototype = undefined;\n return result;\n };\n}());\n\nexport default baseCreate;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nexport default apply;\n","/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction copyArray(source, array) {\n var index = -1,\n length = source.length;\n\n array || (array = Array(length));\n while (++index < length) {\n array[index] = source[index];\n }\n return array;\n}\n\nexport default copyArray;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nexport default shortOut;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nexport default constant;\n","import getNative from './_getNative.js';\n\nvar defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n}());\n\nexport default defineProperty;\n","import constant from './constant.js';\nimport defineProperty from './_defineProperty.js';\nimport identity from './identity.js';\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nexport default baseSetToString;\n","import baseSetToString from './_baseSetToString.js';\nimport shortOut from './_shortOut.js';\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nexport default setToString;\n","/**\n * A specialized version of `_.forEach` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\nfunction arrayEach(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (iteratee(array[index], index, array) === false) {\n break;\n }\n }\n return array;\n}\n\nexport default arrayEach;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n var type = typeof value;\n length = length == null ? MAX_SAFE_INTEGER : length;\n\n return !!length &&\n (type == 'number' ||\n (type != 'symbol' && reIsUint.test(value))) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\nexport default isIndex;\n","import defineProperty from './_defineProperty.js';\n\n/**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction baseAssignValue(object, key, value) {\n if (key == '__proto__' && defineProperty) {\n defineProperty(object, key, {\n 'configurable': true,\n 'enumerable': true,\n 'value': value,\n 'writable': true\n });\n } else {\n object[key] = value;\n }\n}\n\nexport default baseAssignValue;\n","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nexport default eq;\n","import baseAssignValue from './_baseAssignValue.js';\nimport eq from './eq.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nexport default assignValue;\n","import assignValue from './_assignValue.js';\nimport baseAssignValue from './_baseAssignValue.js';\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n var isNew = !object;\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n if (newValue === undefined) {\n newValue = source[key];\n }\n if (isNew) {\n baseAssignValue(object, key, newValue);\n } else {\n assignValue(object, key, newValue);\n }\n }\n return object;\n}\n\nexport default copyObject;\n","import apply from './_apply.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nexport default overRest;\n","import identity from './identity.js';\nimport overRest from './_overRest.js';\nimport setToString from './_setToString.js';\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nexport default baseRest;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nexport default isLength;\n","import isFunction from './isFunction.js';\nimport isLength from './isLength.js';\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\nexport default isArrayLike;\n","import eq from './eq.js';\nimport isArrayLike from './isArrayLike.js';\nimport isIndex from './_isIndex.js';\nimport isObject from './isObject.js';\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\nexport default isIterateeCall;\n","import baseRest from './_baseRest.js';\nimport isIterateeCall from './_isIterateeCall.js';\n\n/**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\nfunction createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n}\n\nexport default createAssigner;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\nexport default isPrototype;\n","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nexport default baseTimes;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]';\n\n/**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\nfunction baseIsArguments(value) {\n return isObjectLike(value) && baseGetTag(value) == argsTag;\n}\n\nexport default baseIsArguments;\n","import baseIsArguments from './_baseIsArguments.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nvar isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n};\n\nexport default isArguments;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nexport default stubFalse;\n","import root from './_root.js';\nimport stubFalse from './stubFalse.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;\n\n/**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\nvar isBuffer = nativeIsBuffer || stubFalse;\n\nexport default isBuffer;\n","import baseGetTag from './_baseGetTag.js';\nimport isLength from './isLength.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\ntypedArrayTags[errorTag] = typedArrayTags[funcTag] =\ntypedArrayTags[mapTag] = typedArrayTags[numberTag] =\ntypedArrayTags[objectTag] = typedArrayTags[regexpTag] =\ntypedArrayTags[setTag] = typedArrayTags[stringTag] =\ntypedArrayTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\nfunction baseIsTypedArray(value) {\n return isObjectLike(value) &&\n isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n}\n\nexport default baseIsTypedArray;\n","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n return function(value) {\n return func(value);\n };\n}\n\nexport default baseUnary;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Detect free variable `process` from Node.js. */\nvar freeProcess = moduleExports && freeGlobal.process;\n\n/** Used to access faster Node.js helpers. */\nvar nodeUtil = (function() {\n try {\n // Use `util.types` for Node.js 10+.\n var types = freeModule && freeModule.require && freeModule.require('util').types;\n\n if (types) {\n return types;\n }\n\n // Legacy `process.binding('util')` for Node.js < 10.\n return freeProcess && freeProcess.binding && freeProcess.binding('util');\n } catch (e) {}\n}());\n\nexport default nodeUtil;\n","import baseIsTypedArray from './_baseIsTypedArray.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nvar isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\nexport default isTypedArray;\n","import baseTimes from './_baseTimes.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isIndex from './_isIndex.js';\nimport isTypedArray from './isTypedArray.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n var isArr = isArray(value),\n isArg = !isArr && isArguments(value),\n isBuff = !isArr && !isArg && isBuffer(value),\n isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n skipIndexes = isArr || isArg || isBuff || isType,\n result = skipIndexes ? baseTimes(value.length, String) : [],\n length = result.length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (\n // Safari 9 has enumerable `arguments.length` in strict mode.\n key == 'length' ||\n // Node.js 0.10 has enumerable non-index properties on buffers.\n (isBuff && (key == 'offset' || key == 'parent')) ||\n // PhantomJS 2 has enumerable non-index properties on typed arrays.\n (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n // Skip index properties.\n isIndex(key, length)\n ))) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default arrayLikeKeys;\n","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nexport default overArg;\n","import overArg from './_overArg.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = overArg(Object.keys, Object);\n\nexport default nativeKeys;\n","import isPrototype from './_isPrototype.js';\nimport nativeKeys from './_nativeKeys.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeys(object) {\n if (!isPrototype(object)) {\n return nativeKeys(object);\n }\n var result = [];\n for (var key in Object(object)) {\n if (hasOwnProperty.call(object, key) && key != 'constructor') {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default baseKeys;\n","import arrayLikeKeys from './_arrayLikeKeys.js';\nimport baseKeys from './_baseKeys.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nfunction keys(object) {\n return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n}\n\nexport default keys;\n","/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default nativeKeysIn;\n","import isObject from './isObject.js';\nimport isPrototype from './_isPrototype.js';\nimport nativeKeysIn from './_nativeKeysIn.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeysIn(object) {\n if (!isObject(object)) {\n return nativeKeysIn(object);\n }\n var isProto = isPrototype(object),\n result = [];\n\n for (var key in object) {\n if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default baseKeysIn;\n","import arrayLikeKeys from './_arrayLikeKeys.js';\nimport baseKeysIn from './_baseKeysIn.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n}\n\nexport default keysIn;\n","import isArray from './isArray.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used to match property names within property paths. */\nvar reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,\n reIsPlainProp = /^\\w*$/;\n\n/**\n * Checks if `value` is a property name and not a property path.\n *\n * @private\n * @param {*} value The value to check.\n * @param {Object} [object] The object to query keys on.\n * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n */\nfunction isKey(value, object) {\n if (isArray(value)) {\n return false;\n }\n var type = typeof value;\n if (type == 'number' || type == 'symbol' || type == 'boolean' ||\n value == null || isSymbol(value)) {\n return true;\n }\n return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||\n (object != null && value in Object(object));\n}\n\nexport default isKey;\n","import getNative from './_getNative.js';\n\n/* Built-in method references that are verified to be native. */\nvar nativeCreate = getNative(Object, 'create');\n\nexport default nativeCreate;\n","import nativeCreate from './_nativeCreate.js';\n\n/**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\nfunction hashClear() {\n this.__data__ = nativeCreate ? nativeCreate(null) : {};\n this.size = 0;\n}\n\nexport default hashClear;\n","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default hashDelete;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction hashGet(key) {\n var data = this.__data__;\n if (nativeCreate) {\n var result = data[key];\n return result === HASH_UNDEFINED ? undefined : result;\n }\n return hasOwnProperty.call(data, key) ? data[key] : undefined;\n}\n\nexport default hashGet;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction hashHas(key) {\n var data = this.__data__;\n return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n}\n\nexport default hashHas;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\nfunction hashSet(key, value) {\n var data = this.__data__;\n this.size += this.has(key) ? 0 : 1;\n data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n return this;\n}\n\nexport default hashSet;\n","import hashClear from './_hashClear.js';\nimport hashDelete from './_hashDelete.js';\nimport hashGet from './_hashGet.js';\nimport hashHas from './_hashHas.js';\nimport hashSet from './_hashSet.js';\n\n/**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Hash(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `Hash`.\nHash.prototype.clear = hashClear;\nHash.prototype['delete'] = hashDelete;\nHash.prototype.get = hashGet;\nHash.prototype.has = hashHas;\nHash.prototype.set = hashSet;\n\nexport default Hash;\n","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n}\n\nexport default listCacheClear;\n","import eq from './eq.js';\n\n/**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction assocIndexOf(array, key) {\n var length = array.length;\n while (length--) {\n if (eq(array[length][0], key)) {\n return length;\n }\n }\n return -1;\n}\n\nexport default assocIndexOf;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction listCacheDelete(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n return false;\n }\n var lastIndex = data.length - 1;\n if (index == lastIndex) {\n data.pop();\n } else {\n splice.call(data, index, 1);\n }\n --this.size;\n return true;\n}\n\nexport default listCacheDelete;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction listCacheGet(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n return index < 0 ? undefined : data[index][1];\n}\n\nexport default listCacheGet;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction listCacheHas(key) {\n return assocIndexOf(this.__data__, key) > -1;\n}\n\nexport default listCacheHas;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\nfunction listCacheSet(key, value) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n ++this.size;\n data.push([key, value]);\n } else {\n data[index][1] = value;\n }\n return this;\n}\n\nexport default listCacheSet;\n","import listCacheClear from './_listCacheClear.js';\nimport listCacheDelete from './_listCacheDelete.js';\nimport listCacheGet from './_listCacheGet.js';\nimport listCacheHas from './_listCacheHas.js';\nimport listCacheSet from './_listCacheSet.js';\n\n/**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction ListCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `ListCache`.\nListCache.prototype.clear = listCacheClear;\nListCache.prototype['delete'] = listCacheDelete;\nListCache.prototype.get = listCacheGet;\nListCache.prototype.has = listCacheHas;\nListCache.prototype.set = listCacheSet;\n\nexport default ListCache;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Map = getNative(root, 'Map');\n\nexport default Map;\n","import Hash from './_Hash.js';\nimport ListCache from './_ListCache.js';\nimport Map from './_Map.js';\n\n/**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\nfunction mapCacheClear() {\n this.size = 0;\n this.__data__ = {\n 'hash': new Hash,\n 'map': new (Map || ListCache),\n 'string': new Hash\n };\n}\n\nexport default mapCacheClear;\n","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n}\n\nexport default isKeyable;\n","import isKeyable from './_isKeyable.js';\n\n/**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\nfunction getMapData(map, key) {\n var data = map.__data__;\n return isKeyable(key)\n ? data[typeof key == 'string' ? 'string' : 'hash']\n : data.map;\n}\n\nexport default getMapData;\n","import getMapData from './_getMapData.js';\n\n/**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction mapCacheDelete(key) {\n var result = getMapData(this, key)['delete'](key);\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default mapCacheDelete;\n","import getMapData from './_getMapData.js';\n\n/**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction mapCacheGet(key) {\n return getMapData(this, key).get(key);\n}\n\nexport default mapCacheGet;\n","import getMapData from './_getMapData.js';\n\n/**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction mapCacheHas(key) {\n return getMapData(this, key).has(key);\n}\n\nexport default mapCacheHas;\n","import getMapData from './_getMapData.js';\n\n/**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\nfunction mapCacheSet(key, value) {\n var data = getMapData(this, key),\n size = data.size;\n\n data.set(key, value);\n this.size += data.size == size ? 0 : 1;\n return this;\n}\n\nexport default mapCacheSet;\n","import mapCacheClear from './_mapCacheClear.js';\nimport mapCacheDelete from './_mapCacheDelete.js';\nimport mapCacheGet from './_mapCacheGet.js';\nimport mapCacheHas from './_mapCacheHas.js';\nimport mapCacheSet from './_mapCacheSet.js';\n\n/**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction MapCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `MapCache`.\nMapCache.prototype.clear = mapCacheClear;\nMapCache.prototype['delete'] = mapCacheDelete;\nMapCache.prototype.get = mapCacheGet;\nMapCache.prototype.has = mapCacheHas;\nMapCache.prototype.set = mapCacheSet;\n\nexport default MapCache;\n","import MapCache from './_MapCache.js';\n\n/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/**\n * Creates a function that memoizes the result of `func`. If `resolver` is\n * provided, it determines the cache key for storing the result based on the\n * arguments provided to the memoized function. By default, the first argument\n * provided to the memoized function is used as the map cache key. The `func`\n * is invoked with the `this` binding of the memoized function.\n *\n * **Note:** The cache is exposed as the `cache` property on the memoized\n * function. Its creation may be customized by replacing the `_.memoize.Cache`\n * constructor with one whose instances implement the\n * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)\n * method interface of `clear`, `delete`, `get`, `has`, and `set`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to have its output memoized.\n * @param {Function} [resolver] The function to resolve the cache key.\n * @returns {Function} Returns the new memoized function.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n * var other = { 'c': 3, 'd': 4 };\n *\n * var values = _.memoize(_.values);\n * values(object);\n * // => [1, 2]\n *\n * values(other);\n * // => [3, 4]\n *\n * object.a = 2;\n * values(object);\n * // => [1, 2]\n *\n * // Modify the result cache.\n * values.cache.set(object, ['a', 'b']);\n * values(object);\n * // => ['a', 'b']\n *\n * // Replace `_.memoize.Cache`.\n * _.memoize.Cache = WeakMap;\n */\nfunction memoize(func, resolver) {\n if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n var memoized = function() {\n var args = arguments,\n key = resolver ? resolver.apply(this, args) : args[0],\n cache = memoized.cache;\n\n if (cache.has(key)) {\n return cache.get(key);\n }\n var result = func.apply(this, args);\n memoized.cache = cache.set(key, result) || cache;\n return result;\n };\n memoized.cache = new (memoize.Cache || MapCache);\n return memoized;\n}\n\n// Expose `MapCache`.\nmemoize.Cache = MapCache;\n\nexport default memoize;\n","import memoize from './memoize.js';\n\n/** Used as the maximum memoize cache size. */\nvar MAX_MEMOIZE_SIZE = 500;\n\n/**\n * A specialized version of `_.memoize` which clears the memoized function's\n * cache when it exceeds `MAX_MEMOIZE_SIZE`.\n *\n * @private\n * @param {Function} func The function to have its output memoized.\n * @returns {Function} Returns the new memoized function.\n */\nfunction memoizeCapped(func) {\n var result = memoize(func, function(key) {\n if (cache.size === MAX_MEMOIZE_SIZE) {\n cache.clear();\n }\n return key;\n });\n\n var cache = result.cache;\n return result;\n}\n\nexport default memoizeCapped;\n","import memoizeCapped from './_memoizeCapped.js';\n\n/** Used to match property names within property paths. */\nvar rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g;\n\n/** Used to match backslashes in property paths. */\nvar reEscapeChar = /\\\\(\\\\)?/g;\n\n/**\n * Converts `string` to a property path array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the property path array.\n */\nvar stringToPath = memoizeCapped(function(string) {\n var result = [];\n if (string.charCodeAt(0) === 46 /* . */) {\n result.push('');\n }\n string.replace(rePropName, function(match, number, quote, subString) {\n result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));\n });\n return result;\n});\n\nexport default stringToPath;\n","import baseToString from './_baseToString.js';\n\n/**\n * Converts `value` to a string. An empty string is returned for `null`\n * and `undefined` values. The sign of `-0` is preserved.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.toString(null);\n * // => ''\n *\n * _.toString(-0);\n * // => '-0'\n *\n * _.toString([1, 2, 3]);\n * // => '1,2,3'\n */\nfunction toString(value) {\n return value == null ? '' : baseToString(value);\n}\n\nexport default toString;\n","import isArray from './isArray.js';\nimport isKey from './_isKey.js';\nimport stringToPath from './_stringToPath.js';\nimport toString from './toString.js';\n\n/**\n * Casts `value` to a path array if it's not one.\n *\n * @private\n * @param {*} value The value to inspect.\n * @param {Object} [object] The object to query keys on.\n * @returns {Array} Returns the cast property path array.\n */\nfunction castPath(value, object) {\n if (isArray(value)) {\n return value;\n }\n return isKey(value, object) ? [value] : stringToPath(toString(value));\n}\n\nexport default castPath;\n","import isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Converts `value` to a string key if it's not a string or symbol.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {string|symbol} Returns the key.\n */\nfunction toKey(value) {\n if (typeof value == 'string' || isSymbol(value)) {\n return value;\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nexport default toKey;\n","import castPath from './_castPath.js';\nimport toKey from './_toKey.js';\n\n/**\n * The base implementation of `_.get` without support for default values.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @returns {*} Returns the resolved value.\n */\nfunction baseGet(object, path) {\n path = castPath(path, object);\n\n var index = 0,\n length = path.length;\n\n while (object != null && index < length) {\n object = object[toKey(path[index++])];\n }\n return (index && index == length) ? object : undefined;\n}\n\nexport default baseGet;\n","import baseGet from './_baseGet.js';\n\n/**\n * Gets the value at `path` of `object`. If the resolved value is\n * `undefined`, the `defaultValue` is returned in its place.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.get(object, 'a[0].b.c');\n * // => 3\n *\n * _.get(object, ['a', '0', 'b', 'c']);\n * // => 3\n *\n * _.get(object, 'a.b.c', 'default');\n * // => 'default'\n */\nfunction get(object, path, defaultValue) {\n var result = object == null ? undefined : baseGet(object, path);\n return result === undefined ? defaultValue : result;\n}\n\nexport default get;\n","/**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\nfunction arrayPush(array, values) {\n var index = -1,\n length = values.length,\n offset = array.length;\n\n while (++index < length) {\n array[offset + index] = values[index];\n }\n return array;\n}\n\nexport default arrayPush;\n","import overArg from './_overArg.js';\n\n/** Built-in value references. */\nvar getPrototype = overArg(Object.getPrototypeOf, Object);\n\nexport default getPrototype;\n","import baseGetTag from './_baseGetTag.js';\nimport getPrototype from './_getPrototype.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to infer the `Object` constructor. */\nvar objectCtorString = funcToString.call(Object);\n\n/**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * @static\n * @memberOf _\n * @since 0.8.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\nfunction isPlainObject(value) {\n if (!isObjectLike(value) || baseGetTag(value) != objectTag) {\n return false;\n }\n var proto = getPrototype(value);\n if (proto === null) {\n return true;\n }\n var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n return typeof Ctor == 'function' && Ctor instanceof Ctor &&\n funcToString.call(Ctor) == objectCtorString;\n}\n\nexport default isPlainObject;\n","/**\n * The base implementation of `_.slice` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\nfunction baseSlice(array, start, end) {\n var index = -1,\n length = array.length;\n\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = end > length ? length : end;\n if (end < 0) {\n end += length;\n }\n length = start > end ? 0 : ((end - start) >>> 0);\n start >>>= 0;\n\n var result = Array(length);\n while (++index < length) {\n result[index] = array[index + start];\n }\n return result;\n}\n\nexport default baseSlice;\n","import baseSlice from './_baseSlice.js';\n\n/**\n * Casts `array` to a slice if it's needed.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {number} start The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the cast slice.\n */\nfunction castSlice(array, start, end) {\n var length = array.length;\n end = end === undefined ? length : end;\n return (!start && end >= length) ? array : baseSlice(array, start, end);\n}\n\nexport default castSlice;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsZWJ = '\\\\u200d';\n\n/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */\nvar reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');\n\n/**\n * Checks if `string` contains Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a symbol is found, else `false`.\n */\nfunction hasUnicode(string) {\n return reHasUnicode.test(string);\n}\n\nexport default hasUnicode;\n","/**\n * Converts an ASCII `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction asciiToArray(string) {\n return string.split('');\n}\n\nexport default asciiToArray;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsAstral = '[' + rsAstralRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsZWJ = '\\\\u200d';\n\n/** Used to compose unicode regexes. */\nvar reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';\n\n/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */\nvar reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');\n\n/**\n * Converts a Unicode `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction unicodeToArray(string) {\n return string.match(reUnicode) || [];\n}\n\nexport default unicodeToArray;\n","import asciiToArray from './_asciiToArray.js';\nimport hasUnicode from './_hasUnicode.js';\nimport unicodeToArray from './_unicodeToArray.js';\n\n/**\n * Converts `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction stringToArray(string) {\n return hasUnicode(string)\n ? unicodeToArray(string)\n : asciiToArray(string);\n}\n\nexport default stringToArray;\n","import castSlice from './_castSlice.js';\nimport hasUnicode from './_hasUnicode.js';\nimport stringToArray from './_stringToArray.js';\nimport toString from './toString.js';\n\n/**\n * Creates a function like `_.lowerFirst`.\n *\n * @private\n * @param {string} methodName The name of the `String` case method to use.\n * @returns {Function} Returns the new case function.\n */\nfunction createCaseFirst(methodName) {\n return function(string) {\n string = toString(string);\n\n var strSymbols = hasUnicode(string)\n ? stringToArray(string)\n : undefined;\n\n var chr = strSymbols\n ? strSymbols[0]\n : string.charAt(0);\n\n var trailing = strSymbols\n ? castSlice(strSymbols, 1).join('')\n : string.slice(1);\n\n return chr[methodName]() + trailing;\n };\n}\n\nexport default createCaseFirst;\n","import createCaseFirst from './_createCaseFirst.js';\n\n/**\n * Converts the first character of `string` to upper case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.upperFirst('fred');\n * // => 'Fred'\n *\n * _.upperFirst('FRED');\n * // => 'FRED'\n */\nvar upperFirst = createCaseFirst('toUpperCase');\n\nexport default upperFirst;\n","import toString from './toString.js';\nimport upperFirst from './upperFirst.js';\n\n/**\n * Converts the first character of `string` to upper case and the remaining\n * to lower case.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to capitalize.\n * @returns {string} Returns the capitalized string.\n * @example\n *\n * _.capitalize('FRED');\n * // => 'Fred'\n */\nfunction capitalize(string) {\n return upperFirst(toString(string).toLowerCase());\n}\n\nexport default capitalize;\n","/**\n * A specialized version of `_.reduce` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @param {boolean} [initAccum] Specify using the first element of `array` as\n * the initial value.\n * @returns {*} Returns the accumulated value.\n */\nfunction arrayReduce(array, iteratee, accumulator, initAccum) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n if (initAccum && length) {\n accumulator = array[++index];\n }\n while (++index < length) {\n accumulator = iteratee(accumulator, array[index], index, array);\n }\n return accumulator;\n}\n\nexport default arrayReduce;\n","/**\n * The base implementation of `_.propertyOf` without support for deep paths.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Function} Returns the new accessor function.\n */\nfunction basePropertyOf(object) {\n return function(key) {\n return object == null ? undefined : object[key];\n };\n}\n\nexport default basePropertyOf;\n","import basePropertyOf from './_basePropertyOf.js';\n\n/** Used to map Latin Unicode letters to basic Latin letters. */\nvar deburredLetters = {\n // Latin-1 Supplement block.\n '\\xc0': 'A', '\\xc1': 'A', '\\xc2': 'A', '\\xc3': 'A', '\\xc4': 'A', '\\xc5': 'A',\n '\\xe0': 'a', '\\xe1': 'a', '\\xe2': 'a', '\\xe3': 'a', '\\xe4': 'a', '\\xe5': 'a',\n '\\xc7': 'C', '\\xe7': 'c',\n '\\xd0': 'D', '\\xf0': 'd',\n '\\xc8': 'E', '\\xc9': 'E', '\\xca': 'E', '\\xcb': 'E',\n '\\xe8': 'e', '\\xe9': 'e', '\\xea': 'e', '\\xeb': 'e',\n '\\xcc': 'I', '\\xcd': 'I', '\\xce': 'I', '\\xcf': 'I',\n '\\xec': 'i', '\\xed': 'i', '\\xee': 'i', '\\xef': 'i',\n '\\xd1': 'N', '\\xf1': 'n',\n '\\xd2': 'O', '\\xd3': 'O', '\\xd4': 'O', '\\xd5': 'O', '\\xd6': 'O', '\\xd8': 'O',\n '\\xf2': 'o', '\\xf3': 'o', '\\xf4': 'o', '\\xf5': 'o', '\\xf6': 'o', '\\xf8': 'o',\n '\\xd9': 'U', '\\xda': 'U', '\\xdb': 'U', '\\xdc': 'U',\n '\\xf9': 'u', '\\xfa': 'u', '\\xfb': 'u', '\\xfc': 'u',\n '\\xdd': 'Y', '\\xfd': 'y', '\\xff': 'y',\n '\\xc6': 'Ae', '\\xe6': 'ae',\n '\\xde': 'Th', '\\xfe': 'th',\n '\\xdf': 'ss',\n // Latin Extended-A block.\n '\\u0100': 'A', '\\u0102': 'A', '\\u0104': 'A',\n '\\u0101': 'a', '\\u0103': 'a', '\\u0105': 'a',\n '\\u0106': 'C', '\\u0108': 'C', '\\u010a': 'C', '\\u010c': 'C',\n '\\u0107': 'c', '\\u0109': 'c', '\\u010b': 'c', '\\u010d': 'c',\n '\\u010e': 'D', '\\u0110': 'D', '\\u010f': 'd', '\\u0111': 'd',\n '\\u0112': 'E', '\\u0114': 'E', '\\u0116': 'E', '\\u0118': 'E', '\\u011a': 'E',\n '\\u0113': 'e', '\\u0115': 'e', '\\u0117': 'e', '\\u0119': 'e', '\\u011b': 'e',\n '\\u011c': 'G', '\\u011e': 'G', '\\u0120': 'G', '\\u0122': 'G',\n '\\u011d': 'g', '\\u011f': 'g', '\\u0121': 'g', '\\u0123': 'g',\n '\\u0124': 'H', '\\u0126': 'H', '\\u0125': 'h', '\\u0127': 'h',\n '\\u0128': 'I', '\\u012a': 'I', '\\u012c': 'I', '\\u012e': 'I', '\\u0130': 'I',\n '\\u0129': 'i', '\\u012b': 'i', '\\u012d': 'i', '\\u012f': 'i', '\\u0131': 'i',\n '\\u0134': 'J', '\\u0135': 'j',\n '\\u0136': 'K', '\\u0137': 'k', '\\u0138': 'k',\n '\\u0139': 'L', '\\u013b': 'L', '\\u013d': 'L', '\\u013f': 'L', '\\u0141': 'L',\n '\\u013a': 'l', '\\u013c': 'l', '\\u013e': 'l', '\\u0140': 'l', '\\u0142': 'l',\n '\\u0143': 'N', '\\u0145': 'N', '\\u0147': 'N', '\\u014a': 'N',\n '\\u0144': 'n', '\\u0146': 'n', '\\u0148': 'n', '\\u014b': 'n',\n '\\u014c': 'O', '\\u014e': 'O', '\\u0150': 'O',\n '\\u014d': 'o', '\\u014f': 'o', '\\u0151': 'o',\n '\\u0154': 'R', '\\u0156': 'R', '\\u0158': 'R',\n '\\u0155': 'r', '\\u0157': 'r', '\\u0159': 'r',\n '\\u015a': 'S', '\\u015c': 'S', '\\u015e': 'S', '\\u0160': 'S',\n '\\u015b': 's', '\\u015d': 's', '\\u015f': 's', '\\u0161': 's',\n '\\u0162': 'T', '\\u0164': 'T', '\\u0166': 'T',\n '\\u0163': 't', '\\u0165': 't', '\\u0167': 't',\n '\\u0168': 'U', '\\u016a': 'U', '\\u016c': 'U', '\\u016e': 'U', '\\u0170': 'U', '\\u0172': 'U',\n '\\u0169': 'u', '\\u016b': 'u', '\\u016d': 'u', '\\u016f': 'u', '\\u0171': 'u', '\\u0173': 'u',\n '\\u0174': 'W', '\\u0175': 'w',\n '\\u0176': 'Y', '\\u0177': 'y', '\\u0178': 'Y',\n '\\u0179': 'Z', '\\u017b': 'Z', '\\u017d': 'Z',\n '\\u017a': 'z', '\\u017c': 'z', '\\u017e': 'z',\n '\\u0132': 'IJ', '\\u0133': 'ij',\n '\\u0152': 'Oe', '\\u0153': 'oe',\n '\\u0149': \"'n\", '\\u017f': 's'\n};\n\n/**\n * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A\n * letters to basic Latin letters.\n *\n * @private\n * @param {string} letter The matched letter to deburr.\n * @returns {string} Returns the deburred letter.\n */\nvar deburrLetter = basePropertyOf(deburredLetters);\n\nexport default deburrLetter;\n","import deburrLetter from './_deburrLetter.js';\nimport toString from './toString.js';\n\n/** Used to match Latin Unicode letters (excluding mathematical operators). */\nvar reLatin = /[\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\xff\\u0100-\\u017f]/g;\n\n/** Used to compose unicode character classes. */\nvar rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange;\n\n/** Used to compose unicode capture groups. */\nvar rsCombo = '[' + rsComboRange + ']';\n\n/**\n * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and\n * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).\n */\nvar reComboMark = RegExp(rsCombo, 'g');\n\n/**\n * Deburrs `string` by converting\n * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)\n * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)\n * letters to basic Latin letters and removing\n * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to deburr.\n * @returns {string} Returns the deburred string.\n * @example\n *\n * _.deburr('déjà vu');\n * // => 'deja vu'\n */\nfunction deburr(string) {\n string = toString(string);\n return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');\n}\n\nexport default deburr;\n","/** Used to match words composed of alphanumeric characters. */\nvar reAsciiWord = /[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g;\n\n/**\n * Splits an ASCII `string` into an array of its words.\n *\n * @private\n * @param {string} The string to inspect.\n * @returns {Array} Returns the words of `string`.\n */\nfunction asciiWords(string) {\n return string.match(reAsciiWord) || [];\n}\n\nexport default asciiWords;\n","/** Used to detect strings that need a more robust regexp to match words. */\nvar reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;\n\n/**\n * Checks if `string` contains a word composed of Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a word is found, else `false`.\n */\nfunction hasUnicodeWord(string) {\n return reHasUnicodeWord.test(string);\n}\n\nexport default hasUnicodeWord;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsDingbatRange = '\\\\u2700-\\\\u27bf',\n rsLowerRange = 'a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff',\n rsMathOpRange = '\\\\xac\\\\xb1\\\\xd7\\\\xf7',\n rsNonCharRange = '\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf',\n rsPunctuationRange = '\\\\u2000-\\\\u206f',\n rsSpaceRange = ' \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000',\n rsUpperRange = 'A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde',\n rsVarRange = '\\\\ufe0e\\\\ufe0f',\n rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;\n\n/** Used to compose unicode capture groups. */\nvar rsApos = \"['\\u2019]\",\n rsBreak = '[' + rsBreakRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsDigits = '\\\\d+',\n rsDingbat = '[' + rsDingbatRange + ']',\n rsLower = '[' + rsLowerRange + ']',\n rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsUpper = '[' + rsUpperRange + ']',\n rsZWJ = '\\\\u200d';\n\n/** Used to compose unicode regexes. */\nvar rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',\n rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',\n rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',\n rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',\n reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsOrdLower = '\\\\d*(?:1st|2nd|3rd|(?![123])\\\\dth)(?=\\\\b|[A-Z_])',\n rsOrdUpper = '\\\\d*(?:1ST|2ND|3RD|(?![123])\\\\dTH)(?=\\\\b|[a-z_])',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq;\n\n/** Used to match complex or compound words. */\nvar reUnicodeWord = RegExp([\n rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',\n rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',\n rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,\n rsUpper + '+' + rsOptContrUpper,\n rsOrdUpper,\n rsOrdLower,\n rsDigits,\n rsEmoji\n].join('|'), 'g');\n\n/**\n * Splits a Unicode `string` into an array of its words.\n *\n * @private\n * @param {string} The string to inspect.\n * @returns {Array} Returns the words of `string`.\n */\nfunction unicodeWords(string) {\n return string.match(reUnicodeWord) || [];\n}\n\nexport default unicodeWords;\n","import asciiWords from './_asciiWords.js';\nimport hasUnicodeWord from './_hasUnicodeWord.js';\nimport toString from './toString.js';\nimport unicodeWords from './_unicodeWords.js';\n\n/**\n * Splits `string` into an array of its words.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {RegExp|string} [pattern] The pattern to match words.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the words of `string`.\n * @example\n *\n * _.words('fred, barney, & pebbles');\n * // => ['fred', 'barney', 'pebbles']\n *\n * _.words('fred, barney, & pebbles', /[^, ]+/g);\n * // => ['fred', 'barney', '&', 'pebbles']\n */\nfunction words(string, pattern, guard) {\n string = toString(string);\n pattern = guard ? undefined : pattern;\n\n if (pattern === undefined) {\n return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);\n }\n return string.match(pattern) || [];\n}\n\nexport default words;\n","import arrayReduce from './_arrayReduce.js';\nimport deburr from './deburr.js';\nimport words from './words.js';\n\n/** Used to compose unicode capture groups. */\nvar rsApos = \"['\\u2019]\";\n\n/** Used to match apostrophes. */\nvar reApos = RegExp(rsApos, 'g');\n\n/**\n * Creates a function like `_.camelCase`.\n *\n * @private\n * @param {Function} callback The function to combine each word.\n * @returns {Function} Returns the new compounder function.\n */\nfunction createCompounder(callback) {\n return function(string) {\n return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');\n };\n}\n\nexport default createCompounder;\n","import capitalize from './capitalize.js';\nimport createCompounder from './_createCompounder.js';\n\n/**\n * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the camel cased string.\n * @example\n *\n * _.camelCase('Foo Bar');\n * // => 'fooBar'\n *\n * _.camelCase('--foo-bar--');\n * // => 'fooBar'\n *\n * _.camelCase('__FOO_BAR__');\n * // => 'fooBar'\n */\nvar camelCase = createCompounder(function(result, word, index) {\n word = word.toLowerCase();\n return result + (index ? capitalize(word) : word);\n});\n\nexport default camelCase;\n","import ListCache from './_ListCache.js';\n\n/**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\nfunction stackClear() {\n this.__data__ = new ListCache;\n this.size = 0;\n}\n\nexport default stackClear;\n","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n}\n\nexport default stackDelete;\n","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n return this.__data__.get(key);\n}\n\nexport default stackGet;\n","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n return this.__data__.has(key);\n}\n\nexport default stackHas;\n","import ListCache from './_ListCache.js';\nimport Map from './_Map.js';\nimport MapCache from './_MapCache.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\nfunction stackSet(key, value) {\n var data = this.__data__;\n if (data instanceof ListCache) {\n var pairs = data.__data__;\n if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n pairs.push([key, value]);\n this.size = ++data.size;\n return this;\n }\n data = this.__data__ = new MapCache(pairs);\n }\n data.set(key, value);\n this.size = data.size;\n return this;\n}\n\nexport default stackSet;\n","import ListCache from './_ListCache.js';\nimport stackClear from './_stackClear.js';\nimport stackDelete from './_stackDelete.js';\nimport stackGet from './_stackGet.js';\nimport stackHas from './_stackHas.js';\nimport stackSet from './_stackSet.js';\n\n/**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Stack(entries) {\n var data = this.__data__ = new ListCache(entries);\n this.size = data.size;\n}\n\n// Add methods to `Stack`.\nStack.prototype.clear = stackClear;\nStack.prototype['delete'] = stackDelete;\nStack.prototype.get = stackGet;\nStack.prototype.has = stackHas;\nStack.prototype.set = stackSet;\n\nexport default Stack;\n","import copyObject from './_copyObject.js';\nimport keys from './keys.js';\n\n/**\n * The base implementation of `_.assign` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\nfunction baseAssign(object, source) {\n return object && copyObject(source, keys(source), object);\n}\n\nexport default baseAssign;\n","import copyObject from './_copyObject.js';\nimport keysIn from './keysIn.js';\n\n/**\n * The base implementation of `_.assignIn` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\nfunction baseAssignIn(object, source) {\n return object && copyObject(source, keysIn(source), object);\n}\n\nexport default baseAssignIn;\n","import root from './_root.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined,\n allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;\n\n/**\n * Creates a clone of `buffer`.\n *\n * @private\n * @param {Buffer} buffer The buffer to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Buffer} Returns the cloned buffer.\n */\nfunction cloneBuffer(buffer, isDeep) {\n if (isDeep) {\n return buffer.slice();\n }\n var length = buffer.length,\n result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n buffer.copy(result);\n return result;\n}\n\nexport default cloneBuffer;\n","/**\n * A specialized version of `_.filter` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nfunction arrayFilter(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (predicate(value, index, array)) {\n result[resIndex++] = value;\n }\n }\n return result;\n}\n\nexport default arrayFilter;\n","/**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\nfunction stubArray() {\n return [];\n}\n\nexport default stubArray;\n","import arrayFilter from './_arrayFilter.js';\nimport stubArray from './stubArray.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbols = !nativeGetSymbols ? stubArray : function(object) {\n if (object == null) {\n return [];\n }\n object = Object(object);\n return arrayFilter(nativeGetSymbols(object), function(symbol) {\n return propertyIsEnumerable.call(object, symbol);\n });\n};\n\nexport default getSymbols;\n","import copyObject from './_copyObject.js';\nimport getSymbols from './_getSymbols.js';\n\n/**\n * Copies own symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\nfunction copySymbols(source, object) {\n return copyObject(source, getSymbols(source), object);\n}\n\nexport default copySymbols;\n","import arrayPush from './_arrayPush.js';\nimport getPrototype from './_getPrototype.js';\nimport getSymbols from './_getSymbols.js';\nimport stubArray from './stubArray.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own and inherited enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {\n var result = [];\n while (object) {\n arrayPush(result, getSymbols(object));\n object = getPrototype(object);\n }\n return result;\n};\n\nexport default getSymbolsIn;\n","import copyObject from './_copyObject.js';\nimport getSymbolsIn from './_getSymbolsIn.js';\n\n/**\n * Copies own and inherited symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\nfunction copySymbolsIn(source, object) {\n return copyObject(source, getSymbolsIn(source), object);\n}\n\nexport default copySymbolsIn;\n","import arrayPush from './_arrayPush.js';\nimport isArray from './isArray.js';\n\n/**\n * The base implementation of `getAllKeys` and `getAllKeysIn` which uses\n * `keysFunc` and `symbolsFunc` to get the enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @param {Function} symbolsFunc The function to get the symbols of `object`.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction baseGetAllKeys(object, keysFunc, symbolsFunc) {\n var result = keysFunc(object);\n return isArray(object) ? result : arrayPush(result, symbolsFunc(object));\n}\n\nexport default baseGetAllKeys;\n","import baseGetAllKeys from './_baseGetAllKeys.js';\nimport getSymbols from './_getSymbols.js';\nimport keys from './keys.js';\n\n/**\n * Creates an array of own enumerable property names and symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeys(object) {\n return baseGetAllKeys(object, keys, getSymbols);\n}\n\nexport default getAllKeys;\n","import baseGetAllKeys from './_baseGetAllKeys.js';\nimport getSymbolsIn from './_getSymbolsIn.js';\nimport keysIn from './keysIn.js';\n\n/**\n * Creates an array of own and inherited enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeysIn(object) {\n return baseGetAllKeys(object, keysIn, getSymbolsIn);\n}\n\nexport default getAllKeysIn;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar DataView = getNative(root, 'DataView');\n\nexport default DataView;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Promise = getNative(root, 'Promise');\n\nexport default Promise;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Set = getNative(root, 'Set');\n\nexport default Set;\n","import DataView from './_DataView.js';\nimport Map from './_Map.js';\nimport Promise from './_Promise.js';\nimport Set from './_Set.js';\nimport WeakMap from './_WeakMap.js';\nimport baseGetTag from './_baseGetTag.js';\nimport toSource from './_toSource.js';\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]',\n objectTag = '[object Object]',\n promiseTag = '[object Promise]',\n setTag = '[object Set]',\n weakMapTag = '[object WeakMap]';\n\nvar dataViewTag = '[object DataView]';\n\n/** Used to detect maps, sets, and weakmaps. */\nvar dataViewCtorString = toSource(DataView),\n mapCtorString = toSource(Map),\n promiseCtorString = toSource(Promise),\n setCtorString = toSource(Set),\n weakMapCtorString = toSource(WeakMap);\n\n/**\n * Gets the `toStringTag` of `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nvar getTag = baseGetTag;\n\n// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.\nif ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||\n (Map && getTag(new Map) != mapTag) ||\n (Promise && getTag(Promise.resolve()) != promiseTag) ||\n (Set && getTag(new Set) != setTag) ||\n (WeakMap && getTag(new WeakMap) != weakMapTag)) {\n getTag = function(value) {\n var result = baseGetTag(value),\n Ctor = result == objectTag ? value.constructor : undefined,\n ctorString = Ctor ? toSource(Ctor) : '';\n\n if (ctorString) {\n switch (ctorString) {\n case dataViewCtorString: return dataViewTag;\n case mapCtorString: return mapTag;\n case promiseCtorString: return promiseTag;\n case setCtorString: return setTag;\n case weakMapCtorString: return weakMapTag;\n }\n }\n return result;\n };\n}\n\nexport default getTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Initializes an array clone.\n *\n * @private\n * @param {Array} array The array to clone.\n * @returns {Array} Returns the initialized clone.\n */\nfunction initCloneArray(array) {\n var length = array.length,\n result = new array.constructor(length);\n\n // Add properties assigned by `RegExp#exec`.\n if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n result.index = array.index;\n result.input = array.input;\n }\n return result;\n}\n\nexport default initCloneArray;\n","import root from './_root.js';\n\n/** Built-in value references. */\nvar Uint8Array = root.Uint8Array;\n\nexport default Uint8Array;\n","import Uint8Array from './_Uint8Array.js';\n\n/**\n * Creates a clone of `arrayBuffer`.\n *\n * @private\n * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\nfunction cloneArrayBuffer(arrayBuffer) {\n var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n return result;\n}\n\nexport default cloneArrayBuffer;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\n\n/**\n * Creates a clone of `dataView`.\n *\n * @private\n * @param {Object} dataView The data view to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned data view.\n */\nfunction cloneDataView(dataView, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;\n return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);\n}\n\nexport default cloneDataView;\n","/** Used to match `RegExp` flags from their coerced string values. */\nvar reFlags = /\\w*$/;\n\n/**\n * Creates a clone of `regexp`.\n *\n * @private\n * @param {Object} regexp The regexp to clone.\n * @returns {Object} Returns the cloned regexp.\n */\nfunction cloneRegExp(regexp) {\n var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));\n result.lastIndex = regexp.lastIndex;\n return result;\n}\n\nexport default cloneRegExp;\n","import Symbol from './_Symbol.js';\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * Creates a clone of the `symbol` object.\n *\n * @private\n * @param {Object} symbol The symbol object to clone.\n * @returns {Object} Returns the cloned symbol object.\n */\nfunction cloneSymbol(symbol) {\n return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};\n}\n\nexport default cloneSymbol;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\n\n/**\n * Creates a clone of `typedArray`.\n *\n * @private\n * @param {Object} typedArray The typed array to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned typed array.\n */\nfunction cloneTypedArray(typedArray, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n}\n\nexport default cloneTypedArray;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\nimport cloneDataView from './_cloneDataView.js';\nimport cloneRegExp from './_cloneRegExp.js';\nimport cloneSymbol from './_cloneSymbol.js';\nimport cloneTypedArray from './_cloneTypedArray.js';\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/**\n * Initializes an object clone based on its `toStringTag`.\n *\n * **Note:** This function only supports cloning values with tags of\n * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.\n *\n * @private\n * @param {Object} object The object to clone.\n * @param {string} tag The `toStringTag` of the object to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneByTag(object, tag, isDeep) {\n var Ctor = object.constructor;\n switch (tag) {\n case arrayBufferTag:\n return cloneArrayBuffer(object);\n\n case boolTag:\n case dateTag:\n return new Ctor(+object);\n\n case dataViewTag:\n return cloneDataView(object, isDeep);\n\n case float32Tag: case float64Tag:\n case int8Tag: case int16Tag: case int32Tag:\n case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n return cloneTypedArray(object, isDeep);\n\n case mapTag:\n return new Ctor;\n\n case numberTag:\n case stringTag:\n return new Ctor(object);\n\n case regexpTag:\n return cloneRegExp(object);\n\n case setTag:\n return new Ctor;\n\n case symbolTag:\n return cloneSymbol(object);\n }\n}\n\nexport default initCloneByTag;\n","import baseCreate from './_baseCreate.js';\nimport getPrototype from './_getPrototype.js';\nimport isPrototype from './_isPrototype.js';\n\n/**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneObject(object) {\n return (typeof object.constructor == 'function' && !isPrototype(object))\n ? baseCreate(getPrototype(object))\n : {};\n}\n\nexport default initCloneObject;\n","import getTag from './_getTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]';\n\n/**\n * The base implementation of `_.isMap` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n */\nfunction baseIsMap(value) {\n return isObjectLike(value) && getTag(value) == mapTag;\n}\n\nexport default baseIsMap;\n","import baseIsMap from './_baseIsMap.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsMap = nodeUtil && nodeUtil.isMap;\n\n/**\n * Checks if `value` is classified as a `Map` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n * @example\n *\n * _.isMap(new Map);\n * // => true\n *\n * _.isMap(new WeakMap);\n * // => false\n */\nvar isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;\n\nexport default isMap;\n","import getTag from './_getTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar setTag = '[object Set]';\n\n/**\n * The base implementation of `_.isSet` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n */\nfunction baseIsSet(value) {\n return isObjectLike(value) && getTag(value) == setTag;\n}\n\nexport default baseIsSet;\n","import baseIsSet from './_baseIsSet.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsSet = nodeUtil && nodeUtil.isSet;\n\n/**\n * Checks if `value` is classified as a `Set` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n * @example\n *\n * _.isSet(new Set);\n * // => true\n *\n * _.isSet(new WeakSet);\n * // => false\n */\nvar isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;\n\nexport default isSet;\n","import Stack from './_Stack.js';\nimport arrayEach from './_arrayEach.js';\nimport assignValue from './_assignValue.js';\nimport baseAssign from './_baseAssign.js';\nimport baseAssignIn from './_baseAssignIn.js';\nimport cloneBuffer from './_cloneBuffer.js';\nimport copyArray from './_copyArray.js';\nimport copySymbols from './_copySymbols.js';\nimport copySymbolsIn from './_copySymbolsIn.js';\nimport getAllKeys from './_getAllKeys.js';\nimport getAllKeysIn from './_getAllKeysIn.js';\nimport getTag from './_getTag.js';\nimport initCloneArray from './_initCloneArray.js';\nimport initCloneByTag from './_initCloneByTag.js';\nimport initCloneObject from './_initCloneObject.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isMap from './isMap.js';\nimport isObject from './isObject.js';\nimport isSet from './isSet.js';\nimport keys from './keys.js';\nimport keysIn from './keysIn.js';\n\n/** Used to compose bitmasks for cloning. */\nvar CLONE_DEEP_FLAG = 1,\n CLONE_FLAT_FLAG = 2,\n CLONE_SYMBOLS_FLAG = 4;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values supported by `_.clone`. */\nvar cloneableTags = {};\ncloneableTags[argsTag] = cloneableTags[arrayTag] =\ncloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =\ncloneableTags[boolTag] = cloneableTags[dateTag] =\ncloneableTags[float32Tag] = cloneableTags[float64Tag] =\ncloneableTags[int8Tag] = cloneableTags[int16Tag] =\ncloneableTags[int32Tag] = cloneableTags[mapTag] =\ncloneableTags[numberTag] = cloneableTags[objectTag] =\ncloneableTags[regexpTag] = cloneableTags[setTag] =\ncloneableTags[stringTag] = cloneableTags[symbolTag] =\ncloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\ncloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\ncloneableTags[errorTag] = cloneableTags[funcTag] =\ncloneableTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.clone` and `_.cloneDeep` which tracks\n * traversed objects.\n *\n * @private\n * @param {*} value The value to clone.\n * @param {boolean} bitmask The bitmask flags.\n * 1 - Deep clone\n * 2 - Flatten inherited properties\n * 4 - Clone symbols\n * @param {Function} [customizer] The function to customize cloning.\n * @param {string} [key] The key of `value`.\n * @param {Object} [object] The parent object of `value`.\n * @param {Object} [stack] Tracks traversed objects and their clone counterparts.\n * @returns {*} Returns the cloned value.\n */\nfunction baseClone(value, bitmask, customizer, key, object, stack) {\n var result,\n isDeep = bitmask & CLONE_DEEP_FLAG,\n isFlat = bitmask & CLONE_FLAT_FLAG,\n isFull = bitmask & CLONE_SYMBOLS_FLAG;\n\n if (customizer) {\n result = object ? customizer(value, key, object, stack) : customizer(value);\n }\n if (result !== undefined) {\n return result;\n }\n if (!isObject(value)) {\n return value;\n }\n var isArr = isArray(value);\n if (isArr) {\n result = initCloneArray(value);\n if (!isDeep) {\n return copyArray(value, result);\n }\n } else {\n var tag = getTag(value),\n isFunc = tag == funcTag || tag == genTag;\n\n if (isBuffer(value)) {\n return cloneBuffer(value, isDeep);\n }\n if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n result = (isFlat || isFunc) ? {} : initCloneObject(value);\n if (!isDeep) {\n return isFlat\n ? copySymbolsIn(value, baseAssignIn(result, value))\n : copySymbols(value, baseAssign(result, value));\n }\n } else {\n if (!cloneableTags[tag]) {\n return object ? value : {};\n }\n result = initCloneByTag(value, tag, isDeep);\n }\n }\n // Check for circular references and return its corresponding clone.\n stack || (stack = new Stack);\n var stacked = stack.get(value);\n if (stacked) {\n return stacked;\n }\n stack.set(value, result);\n\n if (isSet(value)) {\n value.forEach(function(subValue) {\n result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));\n });\n } else if (isMap(value)) {\n value.forEach(function(subValue, key) {\n result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));\n });\n }\n\n var keysFunc = isFull\n ? (isFlat ? getAllKeysIn : getAllKeys)\n : (isFlat ? keysIn : keys);\n\n var props = isArr ? undefined : keysFunc(value);\n arrayEach(props || value, function(subValue, key) {\n if (props) {\n key = subValue;\n subValue = value[key];\n }\n // Recursively populate clone (susceptible to call stack limits).\n assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));\n });\n return result;\n}\n\nexport default baseClone;\n","import baseClone from './_baseClone.js';\n\n/** Used to compose bitmasks for cloning. */\nvar CLONE_DEEP_FLAG = 1,\n CLONE_SYMBOLS_FLAG = 4;\n\n/**\n * This method is like `_.clone` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @returns {*} Returns the deep cloned value.\n * @see _.clone\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var deep = _.cloneDeep(objects);\n * console.log(deep[0] === objects[0]);\n * // => false\n */\nfunction cloneDeep(value) {\n return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);\n}\n\nexport default cloneDeep;\n","/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\nfunction setCacheAdd(value) {\n this.__data__.set(value, HASH_UNDEFINED);\n return this;\n}\n\nexport default setCacheAdd;\n","/**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n return this.__data__.has(value);\n}\n\nexport default setCacheHas;\n","import MapCache from './_MapCache.js';\nimport setCacheAdd from './_setCacheAdd.js';\nimport setCacheHas from './_setCacheHas.js';\n\n/**\n *\n * Creates an array cache object to store unique values.\n *\n * @private\n * @constructor\n * @param {Array} [values] The values to cache.\n */\nfunction SetCache(values) {\n var index = -1,\n length = values == null ? 0 : values.length;\n\n this.__data__ = new MapCache;\n while (++index < length) {\n this.add(values[index]);\n }\n}\n\n// Add methods to `SetCache`.\nSetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\nSetCache.prototype.has = setCacheHas;\n\nexport default SetCache;\n","/**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\nfunction arraySome(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n}\n\nexport default arraySome;\n","/**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction cacheHas(cache, key) {\n return cache.has(key);\n}\n\nexport default cacheHas;\n","import SetCache from './_SetCache.js';\nimport arraySome from './_arraySome.js';\nimport cacheHas from './_cacheHas.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `array` and `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\nfunction equalArrays(array, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n arrLength = array.length,\n othLength = other.length;\n\n if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n return false;\n }\n // Check that cyclic values are equal.\n var arrStacked = stack.get(array);\n var othStacked = stack.get(other);\n if (arrStacked && othStacked) {\n return arrStacked == other && othStacked == array;\n }\n var index = -1,\n result = true,\n seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;\n\n stack.set(array, other);\n stack.set(other, array);\n\n // Ignore non-index properties.\n while (++index < arrLength) {\n var arrValue = array[index],\n othValue = other[index];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, arrValue, index, other, array, stack)\n : customizer(arrValue, othValue, index, array, other, stack);\n }\n if (compared !== undefined) {\n if (compared) {\n continue;\n }\n result = false;\n break;\n }\n // Recursively compare arrays (susceptible to call stack limits).\n if (seen) {\n if (!arraySome(other, function(othValue, othIndex) {\n if (!cacheHas(seen, othIndex) &&\n (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {\n return seen.push(othIndex);\n }\n })) {\n result = false;\n break;\n }\n } else if (!(\n arrValue === othValue ||\n equalFunc(arrValue, othValue, bitmask, customizer, stack)\n )) {\n result = false;\n break;\n }\n }\n stack['delete'](array);\n stack['delete'](other);\n return result;\n}\n\nexport default equalArrays;\n","/**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\nfunction mapToArray(map) {\n var index = -1,\n result = Array(map.size);\n\n map.forEach(function(value, key) {\n result[++index] = [key, value];\n });\n return result;\n}\n\nexport default mapToArray;\n","/**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\nfunction setToArray(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = value;\n });\n return result;\n}\n\nexport default setToArray;\n","import Symbol from './_Symbol.js';\nimport Uint8Array from './_Uint8Array.js';\nimport eq from './eq.js';\nimport equalArrays from './_equalArrays.js';\nimport mapToArray from './_mapToArray.js';\nimport setToArray from './_setToArray.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]';\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {\n switch (tag) {\n case dataViewTag:\n if ((object.byteLength != other.byteLength) ||\n (object.byteOffset != other.byteOffset)) {\n return false;\n }\n object = object.buffer;\n other = other.buffer;\n\n case arrayBufferTag:\n if ((object.byteLength != other.byteLength) ||\n !equalFunc(new Uint8Array(object), new Uint8Array(other))) {\n return false;\n }\n return true;\n\n case boolTag:\n case dateTag:\n case numberTag:\n // Coerce booleans to `1` or `0` and dates to milliseconds.\n // Invalid dates are coerced to `NaN`.\n return eq(+object, +other);\n\n case errorTag:\n return object.name == other.name && object.message == other.message;\n\n case regexpTag:\n case stringTag:\n // Coerce regexes to strings and treat strings, primitives and objects,\n // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring\n // for more details.\n return object == (other + '');\n\n case mapTag:\n var convert = mapToArray;\n\n case setTag:\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG;\n convert || (convert = setToArray);\n\n if (object.size != other.size && !isPartial) {\n return false;\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked) {\n return stacked == other;\n }\n bitmask |= COMPARE_UNORDERED_FLAG;\n\n // Recursively compare objects (susceptible to call stack limits).\n stack.set(object, other);\n var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);\n stack['delete'](object);\n return result;\n\n case symbolTag:\n if (symbolValueOf) {\n return symbolValueOf.call(object) == symbolValueOf.call(other);\n }\n }\n return false;\n}\n\nexport default equalByTag;\n","import getAllKeys from './_getAllKeys.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalObjects(object, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n objProps = getAllKeys(object),\n objLength = objProps.length,\n othProps = getAllKeys(other),\n othLength = othProps.length;\n\n if (objLength != othLength && !isPartial) {\n return false;\n }\n var index = objLength;\n while (index--) {\n var key = objProps[index];\n if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {\n return false;\n }\n }\n // Check that cyclic values are equal.\n var objStacked = stack.get(object);\n var othStacked = stack.get(other);\n if (objStacked && othStacked) {\n return objStacked == other && othStacked == object;\n }\n var result = true;\n stack.set(object, other);\n stack.set(other, object);\n\n var skipCtor = isPartial;\n while (++index < objLength) {\n key = objProps[index];\n var objValue = object[key],\n othValue = other[key];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, objValue, key, other, object, stack)\n : customizer(objValue, othValue, key, object, other, stack);\n }\n // Recursively compare objects (susceptible to call stack limits).\n if (!(compared === undefined\n ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))\n : compared\n )) {\n result = false;\n break;\n }\n skipCtor || (skipCtor = key == 'constructor');\n }\n if (result && !skipCtor) {\n var objCtor = object.constructor,\n othCtor = other.constructor;\n\n // Non `Object` object instances with different constructors are not equal.\n if (objCtor != othCtor &&\n ('constructor' in object && 'constructor' in other) &&\n !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n result = false;\n }\n }\n stack['delete'](object);\n stack['delete'](other);\n return result;\n}\n\nexport default equalObjects;\n","import Stack from './_Stack.js';\nimport equalArrays from './_equalArrays.js';\nimport equalByTag from './_equalByTag.js';\nimport equalObjects from './_equalObjects.js';\nimport getTag from './_getTag.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isTypedArray from './isTypedArray.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} [stack] Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {\n var objIsArr = isArray(object),\n othIsArr = isArray(other),\n objTag = objIsArr ? arrayTag : getTag(object),\n othTag = othIsArr ? arrayTag : getTag(other);\n\n objTag = objTag == argsTag ? objectTag : objTag;\n othTag = othTag == argsTag ? objectTag : othTag;\n\n var objIsObj = objTag == objectTag,\n othIsObj = othTag == objectTag,\n isSameTag = objTag == othTag;\n\n if (isSameTag && isBuffer(object)) {\n if (!isBuffer(other)) {\n return false;\n }\n objIsArr = true;\n objIsObj = false;\n }\n if (isSameTag && !objIsObj) {\n stack || (stack = new Stack);\n return (objIsArr || isTypedArray(object))\n ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)\n : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);\n }\n if (!(bitmask & COMPARE_PARTIAL_FLAG)) {\n var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n if (objIsWrapped || othIsWrapped) {\n var objUnwrapped = objIsWrapped ? object.value() : object,\n othUnwrapped = othIsWrapped ? other.value() : other;\n\n stack || (stack = new Stack);\n return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);\n }\n }\n if (!isSameTag) {\n return false;\n }\n stack || (stack = new Stack);\n return equalObjects(object, other, bitmask, customizer, equalFunc, stack);\n}\n\nexport default baseIsEqualDeep;\n","import baseIsEqualDeep from './_baseIsEqualDeep.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * The base implementation of `_.isEqual` which supports partial comparisons\n * and tracks traversed objects.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {boolean} bitmask The bitmask flags.\n * 1 - Unordered comparison\n * 2 - Partial comparison\n * @param {Function} [customizer] The function to customize comparisons.\n * @param {Object} [stack] Tracks traversed `value` and `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\nfunction baseIsEqual(value, other, bitmask, customizer, stack) {\n if (value === other) {\n return true;\n }\n if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {\n return value !== value && other !== other;\n }\n return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);\n}\n\nexport default baseIsEqual;\n","/**\n * Creates a base function for methods like `_.forIn` and `_.forOwn`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseFor(fromRight) {\n return function(object, iteratee, keysFunc) {\n var index = -1,\n iterable = Object(object),\n props = keysFunc(object),\n length = props.length;\n\n while (length--) {\n var key = props[fromRight ? length : ++index];\n if (iteratee(iterable[key], key, iterable) === false) {\n break;\n }\n }\n return object;\n };\n}\n\nexport default createBaseFor;\n","import createBaseFor from './_createBaseFor.js';\n\n/**\n * The base implementation of `baseForOwn` which iterates over `object`\n * properties returned by `keysFunc` and invokes `iteratee` for each property.\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\nvar baseFor = createBaseFor();\n\nexport default baseFor;\n","import root from './_root.js';\n\n/**\n * Gets the timestamp of the number of milliseconds that have elapsed since\n * the Unix epoch (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Date\n * @returns {number} Returns the timestamp.\n * @example\n *\n * _.defer(function(stamp) {\n * console.log(_.now() - stamp);\n * }, _.now());\n * // => Logs the number of milliseconds it took for the deferred invocation.\n */\nvar now = function() {\n return root.Date.now();\n};\n\nexport default now;\n","import isObject from './isObject.js';\nimport now from './now.js';\nimport toNumber from './toNumber.js';\n\n/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max,\n nativeMin = Math.min;\n\n/**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel\n * delayed `func` invocations and a `flush` method to immediately invoke them.\n * Provide `options` to indicate whether `func` should be invoked on the\n * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n * with the last arguments provided to the debounced function. Subsequent\n * calls to the debounced function return the result of the last `func`\n * invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.debounce` and `_.throttle`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0] The number of milliseconds to delay.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', _.debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }));\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n * var source = new EventSource('/stream');\n * jQuery(source).on('message', debounced);\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel);\n */\nfunction debounce(func, wait, options) {\n var lastArgs,\n lastThis,\n maxWait,\n result,\n timerId,\n lastCallTime,\n lastInvokeTime = 0,\n leading = false,\n maxing = false,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n wait = toNumber(wait) || 0;\n if (isObject(options)) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n\n function invokeFunc(time) {\n var args = lastArgs,\n thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = setTimeout(timerExpired, wait);\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime,\n timeWaiting = wait - timeSinceLastCall;\n\n return maxing\n ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)\n : timeWaiting;\n }\n\n function shouldInvoke(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n }\n\n function timerExpired() {\n var time = now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(now());\n }\n\n function debounced() {\n var time = now(),\n isInvoking = shouldInvoke(time);\n\n lastArgs = arguments;\n lastThis = this;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n clearTimeout(timerId);\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n}\n\nexport default debounce;\n","import baseAssignValue from './_baseAssignValue.js';\nimport eq from './eq.js';\n\n/**\n * This function is like `assignValue` except that it doesn't assign\n * `undefined` values.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignMergeValue(object, key, value) {\n if ((value !== undefined && !eq(object[key], value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nexport default assignMergeValue;\n","import isArrayLike from './isArrayLike.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n}\n\nexport default isArrayLikeObject;\n","/**\n * Gets the value at `key`, unless `key` is \"__proto__\" or \"constructor\".\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction safeGet(object, key) {\n if (key === 'constructor' && typeof object[key] === 'function') {\n return;\n }\n\n if (key == '__proto__') {\n return;\n }\n\n return object[key];\n}\n\nexport default safeGet;\n","import copyObject from './_copyObject.js';\nimport keysIn from './keysIn.js';\n\n/**\n * Converts `value` to a plain object flattening inherited enumerable string\n * keyed properties of `value` to own properties of the plain object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Object} Returns the converted plain object.\n * @example\n *\n * function Foo() {\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.assign({ 'a': 1 }, new Foo);\n * // => { 'a': 1, 'b': 2 }\n *\n * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));\n * // => { 'a': 1, 'b': 2, 'c': 3 }\n */\nfunction toPlainObject(value) {\n return copyObject(value, keysIn(value));\n}\n\nexport default toPlainObject;\n","import assignMergeValue from './_assignMergeValue.js';\nimport cloneBuffer from './_cloneBuffer.js';\nimport cloneTypedArray from './_cloneTypedArray.js';\nimport copyArray from './_copyArray.js';\nimport initCloneObject from './_initCloneObject.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isArrayLikeObject from './isArrayLikeObject.js';\nimport isBuffer from './isBuffer.js';\nimport isFunction from './isFunction.js';\nimport isObject from './isObject.js';\nimport isPlainObject from './isPlainObject.js';\nimport isTypedArray from './isTypedArray.js';\nimport safeGet from './_safeGet.js';\nimport toPlainObject from './toPlainObject.js';\n\n/**\n * A specialized version of `baseMerge` for arrays and objects which performs\n * deep merges and tracks traversed objects enabling objects with circular\n * references to be merged.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {string} key The key of the value to merge.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} mergeFunc The function to merge values.\n * @param {Function} [customizer] The function to customize assigned values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\nfunction baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {\n var objValue = safeGet(object, key),\n srcValue = safeGet(source, key),\n stacked = stack.get(srcValue);\n\n if (stacked) {\n assignMergeValue(object, key, stacked);\n return;\n }\n var newValue = customizer\n ? customizer(objValue, srcValue, (key + ''), object, source, stack)\n : undefined;\n\n var isCommon = newValue === undefined;\n\n if (isCommon) {\n var isArr = isArray(srcValue),\n isBuff = !isArr && isBuffer(srcValue),\n isTyped = !isArr && !isBuff && isTypedArray(srcValue);\n\n newValue = srcValue;\n if (isArr || isBuff || isTyped) {\n if (isArray(objValue)) {\n newValue = objValue;\n }\n else if (isArrayLikeObject(objValue)) {\n newValue = copyArray(objValue);\n }\n else if (isBuff) {\n isCommon = false;\n newValue = cloneBuffer(srcValue, true);\n }\n else if (isTyped) {\n isCommon = false;\n newValue = cloneTypedArray(srcValue, true);\n }\n else {\n newValue = [];\n }\n }\n else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n newValue = objValue;\n if (isArguments(objValue)) {\n newValue = toPlainObject(objValue);\n }\n else if (!isObject(objValue) || isFunction(objValue)) {\n newValue = initCloneObject(srcValue);\n }\n }\n else {\n isCommon = false;\n }\n }\n if (isCommon) {\n // Recursively merge objects and arrays (susceptible to call stack limits).\n stack.set(srcValue, newValue);\n mergeFunc(newValue, srcValue, srcIndex, customizer, stack);\n stack['delete'](srcValue);\n }\n assignMergeValue(object, key, newValue);\n}\n\nexport default baseMergeDeep;\n","import Stack from './_Stack.js';\nimport assignMergeValue from './_assignMergeValue.js';\nimport baseFor from './_baseFor.js';\nimport baseMergeDeep from './_baseMergeDeep.js';\nimport isObject from './isObject.js';\nimport keysIn from './keysIn.js';\nimport safeGet from './_safeGet.js';\n\n/**\n * The base implementation of `_.merge` without support for multiple sources.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} [customizer] The function to customize merged values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\nfunction baseMerge(object, source, srcIndex, customizer, stack) {\n if (object === source) {\n return;\n }\n baseFor(source, function(srcValue, key) {\n stack || (stack = new Stack);\n if (isObject(srcValue)) {\n baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);\n }\n else {\n var newValue = customizer\n ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)\n : undefined;\n\n if (newValue === undefined) {\n newValue = srcValue;\n }\n assignMergeValue(object, key, newValue);\n }\n }, keysIn);\n}\n\nexport default baseMerge;\n","import baseMerge from './_baseMerge.js';\nimport createAssigner from './_createAssigner.js';\n\n/**\n * This method is like `_.merge` except that it accepts `customizer` which\n * is invoked to produce the merged values of the destination and source\n * properties. If `customizer` returns `undefined`, merging is handled by the\n * method instead. The `customizer` is invoked with six arguments:\n * (objValue, srcValue, key, object, source, stack).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} customizer The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * function customizer(objValue, srcValue) {\n * if (_.isArray(objValue)) {\n * return objValue.concat(srcValue);\n * }\n * }\n *\n * var object = { 'a': [1], 'b': [2] };\n * var other = { 'a': [3], 'b': [4] };\n *\n * _.mergeWith(object, other, customizer);\n * // => { 'a': [1, 3], 'b': [2, 4] }\n */\nvar mergeWith = createAssigner(function(object, source, srcIndex, customizer) {\n baseMerge(object, source, srcIndex, customizer);\n});\n\nexport default mergeWith;\n","/**\n * Gets the last element of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to query.\n * @returns {*} Returns the last element of `array`.\n * @example\n *\n * _.last([1, 2, 3]);\n * // => 3\n */\nfunction last(array) {\n var length = array == null ? 0 : array.length;\n return length ? array[length - 1] : undefined;\n}\n\nexport default last;\n","import baseGet from './_baseGet.js';\nimport baseSlice from './_baseSlice.js';\n\n/**\n * Gets the parent value at `path` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} path The path to get the parent value of.\n * @returns {*} Returns the parent value.\n */\nfunction parent(object, path) {\n return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));\n}\n\nexport default parent;\n","import baseIsEqual from './_baseIsEqual.js';\n\n/**\n * Performs a deep comparison between two values to determine if they are\n * equivalent.\n *\n * **Note:** This method supports comparing arrays, array buffers, booleans,\n * date objects, error objects, maps, numbers, `Object` objects, regexes,\n * sets, strings, symbols, and typed arrays. `Object` objects are compared\n * by their own, not inherited, enumerable properties. Functions and DOM\n * nodes are compared by strict equality, i.e. `===`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.isEqual(object, other);\n * // => true\n *\n * object === other;\n * // => false\n */\nfunction isEqual(value, other) {\n return baseIsEqual(value, other);\n}\n\nexport default isEqual;\n","import createCompounder from './_createCompounder.js';\n\n/**\n * Converts `string` to\n * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the kebab cased string.\n * @example\n *\n * _.kebabCase('Foo Bar');\n * // => 'foo-bar'\n *\n * _.kebabCase('fooBar');\n * // => 'foo-bar'\n *\n * _.kebabCase('__FOO_BAR__');\n * // => 'foo-bar'\n */\nvar kebabCase = createCompounder(function(result, word, index) {\n return result + (index ? '-' : '') + word.toLowerCase();\n});\n\nexport default kebabCase;\n","import baseMerge from './_baseMerge.js';\nimport createAssigner from './_createAssigner.js';\n\n/**\n * This method is like `_.assign` except that it recursively merges own and\n * inherited enumerable string keyed properties of source objects into the\n * destination object. Source properties that resolve to `undefined` are\n * skipped if a destination value exists. Array and plain object properties\n * are merged recursively. Other objects and value types are overridden by\n * assignment. Source objects are applied from left to right. Subsequent\n * sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 0.5.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {\n * 'a': [{ 'b': 2 }, { 'd': 4 }]\n * };\n *\n * var other = {\n * 'a': [{ 'c': 3 }, { 'e': 5 }]\n * };\n *\n * _.merge(object, other);\n * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }\n */\nvar merge = createAssigner(function(object, source, srcIndex) {\n baseMerge(object, source, srcIndex);\n});\n\nexport default merge;\n","import castPath from './_castPath.js';\nimport last from './last.js';\nimport parent from './_parent.js';\nimport toKey from './_toKey.js';\n\n/**\n * The base implementation of `_.unset`.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {Array|string} path The property path to unset.\n * @returns {boolean} Returns `true` if the property is deleted, else `false`.\n */\nfunction baseUnset(object, path) {\n path = castPath(path, object);\n object = parent(object, path);\n return object == null || delete object[toKey(last(path))];\n}\n\nexport default baseUnset;\n","import createCompounder from './_createCompounder.js';\n\n/**\n * Converts `string` to\n * [snake case](https://en.wikipedia.org/wiki/Snake_case).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the snake cased string.\n * @example\n *\n * _.snakeCase('Foo Bar');\n * // => 'foo_bar'\n *\n * _.snakeCase('fooBar');\n * // => 'foo_bar'\n *\n * _.snakeCase('--FOO-BAR--');\n * // => 'foo_bar'\n */\nvar snakeCase = createCompounder(function(result, word, index) {\n return result + (index ? '_' : '') + word.toLowerCase();\n});\n\nexport default snakeCase;\n","import createCompounder from './_createCompounder.js';\nimport upperFirst from './upperFirst.js';\n\n/**\n * Converts `string` to\n * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).\n *\n * @static\n * @memberOf _\n * @since 3.1.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the start cased string.\n * @example\n *\n * _.startCase('--foo-bar--');\n * // => 'Foo Bar'\n *\n * _.startCase('fooBar');\n * // => 'Foo Bar'\n *\n * _.startCase('__FOO_BAR__');\n * // => 'FOO BAR'\n */\nvar startCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + upperFirst(word);\n});\n\nexport default startCase;\n","import toString from './toString.js';\n\n/**\n * Converts `string`, as a whole, to lower case just like\n * [String#toLowerCase](https://mdn.io/toLowerCase).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the lower cased string.\n * @example\n *\n * _.toLower('--Foo-Bar--');\n * // => '--foo-bar--'\n *\n * _.toLower('fooBar');\n * // => 'foobar'\n *\n * _.toLower('__FOO_BAR__');\n * // => '__foo_bar__'\n */\nfunction toLower(value) {\n return toString(value).toLowerCase();\n}\n\nexport default toLower;\n","import baseUnset from './_baseUnset.js';\n\n/**\n * Removes the property at `path` of `object`.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to unset.\n * @returns {boolean} Returns `true` if the property is deleted, else `false`.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 7 } }] };\n * _.unset(object, 'a[0].b.c');\n * // => true\n *\n * console.log(object);\n * // => { 'a': [{ 'b': {} }] };\n *\n * _.unset(object, ['a', '0', 'b', 'c']);\n * // => true\n *\n * console.log(object);\n * // => { 'a': [{ 'b': {} }] };\n */\nfunction unset(object, path) {\n return object == null ? true : baseUnset(object, path);\n}\n\nexport default unset;\n","/**\n * A simple guard function:\n *\n * ```js\n * Math.min(Math.max(low, value), high)\n * ```\n */\nfunction guard(low, high, value) {\n return Math.min(Math.max(low, value), high);\n}\n\nclass ColorError extends Error {\n constructor(color) {\n super(`Failed to parse color: \"${color}\"`);\n }\n}\nvar ColorError$1 = ColorError;\n\n/**\n * Parses a color into red, gree, blue, alpha parts\n *\n * @param color the input color. Can be a RGB, RBGA, HSL, HSLA, or named color\n */\nfunction parseToRgba(color) {\n if (typeof color !== 'string') throw new ColorError$1(color);\n if (color.trim().toLowerCase() === 'transparent') return [0, 0, 0, 0];\n let normalizedColor = color.trim();\n normalizedColor = namedColorRegex.test(color) ? nameToHex(color) : color;\n const reducedHexMatch = reducedHexRegex.exec(normalizedColor);\n if (reducedHexMatch) {\n const arr = Array.from(reducedHexMatch).slice(1);\n return [...arr.slice(0, 3).map(x => parseInt(r(x, 2), 16)), parseInt(r(arr[3] || 'f', 2), 16) / 255];\n }\n const hexMatch = hexRegex.exec(normalizedColor);\n if (hexMatch) {\n const arr = Array.from(hexMatch).slice(1);\n return [...arr.slice(0, 3).map(x => parseInt(x, 16)), parseInt(arr[3] || 'ff', 16) / 255];\n }\n const rgbaMatch = rgbaRegex.exec(normalizedColor);\n if (rgbaMatch) {\n const arr = Array.from(rgbaMatch).slice(1);\n return [...arr.slice(0, 3).map(x => parseInt(x, 10)), parseFloat(arr[3] || '1')];\n }\n const hslaMatch = hslaRegex.exec(normalizedColor);\n if (hslaMatch) {\n const [h, s, l, a] = Array.from(hslaMatch).slice(1).map(parseFloat);\n if (guard(0, 100, s) !== s) throw new ColorError$1(color);\n if (guard(0, 100, l) !== l) throw new ColorError$1(color);\n return [...hslToRgb(h, s, l), Number.isNaN(a) ? 1 : a];\n }\n throw new ColorError$1(color);\n}\nfunction hash(str) {\n let hash = 5381;\n let i = str.length;\n while (i) {\n hash = hash * 33 ^ str.charCodeAt(--i);\n }\n\n /* JavaScript does bitwise operations (like XOR, above) on 32-bit signed\n * integers. Since we want the results to be always positive, convert the\n * signed int to an unsigned by doing an unsigned bitshift. */\n return (hash >>> 0) % 2341;\n}\nconst colorToInt = x => parseInt(x.replace(/_/g, ''), 36);\nconst compressedColorMap = '1q29ehhb 1n09sgk7 1kl1ekf_ _yl4zsno 16z9eiv3 1p29lhp8 _bd9zg04 17u0____ _iw9zhe5 _to73___ _r45e31e _7l6g016 _jh8ouiv _zn3qba8 1jy4zshs 11u87k0u 1ro9yvyo 1aj3xael 1gz9zjz0 _3w8l4xo 1bf1ekf_ _ke3v___ _4rrkb__ 13j776yz _646mbhl _nrjr4__ _le6mbhl 1n37ehkb _m75f91n _qj3bzfz 1939yygw 11i5z6x8 _1k5f8xs 1509441m 15t5lwgf _ae2th1n _tg1ugcv 1lp1ugcv 16e14up_ _h55rw7n _ny9yavn _7a11xb_ 1ih442g9 _pv442g9 1mv16xof 14e6y7tu 1oo9zkds 17d1cisi _4v9y70f _y98m8kc 1019pq0v 12o9zda8 _348j4f4 1et50i2o _8epa8__ _ts6senj 1o350i2o 1mi9eiuo 1259yrp0 1ln80gnw _632xcoy 1cn9zldc _f29edu4 1n490c8q _9f9ziet 1b94vk74 _m49zkct 1kz6s73a 1eu9dtog _q58s1rz 1dy9sjiq __u89jo3 _aj5nkwg _ld89jo3 13h9z6wx _qa9z2ii _l119xgq _bs5arju 1hj4nwk9 1qt4nwk9 1ge6wau6 14j9zlcw 11p1edc_ _ms1zcxe _439shk6 _jt9y70f _754zsow 1la40eju _oq5p___ _x279qkz 1fa5r3rv _yd2d9ip _424tcku _8y1di2_ _zi2uabw _yy7rn9h 12yz980_ __39ljp6 1b59zg0x _n39zfzp 1fy9zest _b33k___ _hp9wq92 1il50hz4 _io472ub _lj9z3eo 19z9ykg0 _8t8iu3a 12b9bl4a 1ak5yw0o _896v4ku _tb8k8lv _s59zi6t _c09ze0p 1lg80oqn 1id9z8wb _238nba5 1kq6wgdi _154zssg _tn3zk49 _da9y6tc 1sg7cv4f _r12jvtt 1gq5fmkz 1cs9rvci _lp9jn1c _xw1tdnb 13f9zje6 16f6973h _vo7ir40 _bt5arjf _rc45e4t _hr4e100 10v4e100 _hc9zke2 _w91egv_ _sj2r1kk 13c87yx8 _vqpds__ _ni8ggk8 _tj9yqfb 1ia2j4r4 _7x9b10u 1fc9ld4j 1eq9zldr _5j9lhpx _ez9zl6o _md61fzm'.split(' ').reduce((acc, next) => {\n const key = colorToInt(next.substring(0, 3));\n const hex = colorToInt(next.substring(3)).toString(16);\n\n // NOTE: padStart could be used here but it breaks Node 6 compat\n // https://github.com/ricokahler/color2k/issues/351\n let prefix = '';\n for (let i = 0; i < 6 - hex.length; i++) {\n prefix += '0';\n }\n acc[key] = `${prefix}${hex}`;\n return acc;\n}, {});\n\n/**\n * Checks if a string is a CSS named color and returns its equivalent hex value, otherwise returns the original color.\n */\nfunction nameToHex(color) {\n const normalizedColorName = color.toLowerCase().trim();\n const result = compressedColorMap[hash(normalizedColorName)];\n if (!result) throw new ColorError$1(color);\n return `#${result}`;\n}\nconst r = (str, amount) => Array.from(Array(amount)).map(() => str).join('');\nconst reducedHexRegex = new RegExp(`^#${r('([a-f0-9])', 3)}([a-f0-9])?$`, 'i');\nconst hexRegex = new RegExp(`^#${r('([a-f0-9]{2})', 3)}([a-f0-9]{2})?$`, 'i');\nconst rgbaRegex = new RegExp(`^rgba?\\\\(\\\\s*(\\\\d+)\\\\s*${r(',\\\\s*(\\\\d+)\\\\s*', 2)}(?:,\\\\s*([\\\\d.]+))?\\\\s*\\\\)$`, 'i');\nconst hslaRegex = /^hsla?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)%\\s*,\\s*([\\d.]+)%(?:\\s*,\\s*([\\d.]+))?\\s*\\)$/i;\nconst namedColorRegex = /^[a-z]+$/i;\nconst roundColor = color => {\n return Math.round(color * 255);\n};\nconst hslToRgb = (hue, saturation, lightness) => {\n let l = lightness / 100;\n if (saturation === 0) {\n // achromatic\n return [l, l, l].map(roundColor);\n }\n\n // formulae from https://en.wikipedia.org/wiki/HSL_and_HSV\n const huePrime = (hue % 360 + 360) % 360 / 60;\n const chroma = (1 - Math.abs(2 * l - 1)) * (saturation / 100);\n const secondComponent = chroma * (1 - Math.abs(huePrime % 2 - 1));\n let red = 0;\n let green = 0;\n let blue = 0;\n if (huePrime >= 0 && huePrime < 1) {\n red = chroma;\n green = secondComponent;\n } else if (huePrime >= 1 && huePrime < 2) {\n red = secondComponent;\n green = chroma;\n } else if (huePrime >= 2 && huePrime < 3) {\n green = chroma;\n blue = secondComponent;\n } else if (huePrime >= 3 && huePrime < 4) {\n green = secondComponent;\n blue = chroma;\n } else if (huePrime >= 4 && huePrime < 5) {\n red = secondComponent;\n blue = chroma;\n } else if (huePrime >= 5 && huePrime < 6) {\n red = chroma;\n blue = secondComponent;\n }\n const lightnessModification = l - chroma / 2;\n const finalRed = red + lightnessModification;\n const finalGreen = green + lightnessModification;\n const finalBlue = blue + lightnessModification;\n return [finalRed, finalGreen, finalBlue].map(roundColor);\n};\n\n// taken from:\n\n/**\n * Parses a color in hue, saturation, lightness, and the alpha channel.\n *\n * Hue is a number between 0 and 360, saturation, lightness, and alpha are\n * decimal percentages between 0 and 1\n */\nfunction parseToHsla(color) {\n const [red, green, blue, alpha] = parseToRgba(color).map((value, index) =>\n // 3rd index is alpha channel which is already normalized\n index === 3 ? value : value / 255);\n const max = Math.max(red, green, blue);\n const min = Math.min(red, green, blue);\n const lightness = (max + min) / 2;\n\n // achromatic\n if (max === min) return [0, 0, lightness, alpha];\n const delta = max - min;\n const saturation = lightness > 0.5 ? delta / (2 - max - min) : delta / (max + min);\n const hue = 60 * (red === max ? (green - blue) / delta + (green < blue ? 6 : 0) : green === max ? (blue - red) / delta + 2 : (red - green) / delta + 4);\n return [hue, saturation, lightness, alpha];\n}\n\n/**\n * Takes in hsla parts and constructs an hsla string\n *\n * @param hue The color circle (from 0 to 360) - 0 (or 360) is red, 120 is green, 240 is blue\n * @param saturation Percentage of saturation, given as a decimal between 0 and 1\n * @param lightness Percentage of lightness, given as a decimal between 0 and 1\n * @param alpha Percentage of opacity, given as a decimal between 0 and 1\n */\nfunction hsla(hue, saturation, lightness, alpha) {\n return `hsla(${(hue % 360).toFixed()}, ${guard(0, 100, saturation * 100).toFixed()}%, ${guard(0, 100, lightness * 100).toFixed()}%, ${parseFloat(guard(0, 1, alpha).toFixed(3))})`;\n}\n\n/**\n * Adjusts the current hue of the color by the given degrees. Wraps around when\n * over 360.\n *\n * @param color input color\n * @param degrees degrees to adjust the input color, accepts degree integers\n * (0 - 360) and wraps around on overflow\n */\nfunction adjustHue(color, degrees) {\n const [h, s, l, a] = parseToHsla(color);\n return hsla(h + degrees, s, l, a);\n}\n\n/**\n * Darkens using lightness. This is equivalent to subtracting the lightness\n * from the L in HSL.\n *\n * @param amount The amount to darken, given as a decimal between 0 and 1\n */\nfunction darken(color, amount) {\n const [hue, saturation, lightness, alpha] = parseToHsla(color);\n return hsla(hue, saturation, lightness - amount, alpha);\n}\n\n/**\n * Desaturates the input color by the given amount via subtracting from the `s`\n * in `hsla`.\n *\n * @param amount The amount to desaturate, given as a decimal between 0 and 1\n */\nfunction desaturate(color, amount) {\n const [h, s, l, a] = parseToHsla(color);\n return hsla(h, s - amount, l, a);\n}\n\n// taken from:\n// https://github.com/styled-components/polished/blob/0764c982551b487469043acb56281b0358b3107b/src/color/getLuminance.js\n\n/**\n * Returns a number (float) representing the luminance of a color.\n */\nfunction getLuminance(color) {\n if (color === 'transparent') return 0;\n function f(x) {\n const channel = x / 255;\n return channel <= 0.03928 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);\n }\n const [r, g, b] = parseToRgba(color);\n return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b);\n}\n\n// taken from:\n\n/**\n * Returns the contrast ratio between two colors based on\n * [W3's recommended equation for calculating contrast](http://www.w3.org/TR/WCAG20/#contrast-ratiodef).\n */\nfunction getContrast(color1, color2) {\n const luminance1 = getLuminance(color1);\n const luminance2 = getLuminance(color2);\n return luminance1 > luminance2 ? (luminance1 + 0.05) / (luminance2 + 0.05) : (luminance2 + 0.05) / (luminance1 + 0.05);\n}\n\n/**\n * Takes in rgba parts and returns an rgba string\n *\n * @param red The amount of red in the red channel, given in a number between 0 and 255 inclusive\n * @param green The amount of green in the red channel, given in a number between 0 and 255 inclusive\n * @param blue The amount of blue in the red channel, given in a number between 0 and 255 inclusive\n * @param alpha Percentage of opacity, given as a decimal between 0 and 1\n */\nfunction rgba(red, green, blue, alpha) {\n return `rgba(${guard(0, 255, red).toFixed()}, ${guard(0, 255, green).toFixed()}, ${guard(0, 255, blue).toFixed()}, ${parseFloat(guard(0, 1, alpha).toFixed(3))})`;\n}\n\n/**\n * Mixes two colors together. Taken from sass's implementation.\n */\nfunction mix(color1, color2, weight) {\n const normalize = (n, index) =>\n // 3rd index is alpha channel which is already normalized\n index === 3 ? n : n / 255;\n const [r1, g1, b1, a1] = parseToRgba(color1).map(normalize);\n const [r2, g2, b2, a2] = parseToRgba(color2).map(normalize);\n\n // The formula is copied from the original Sass implementation:\n // http://sass-lang.com/documentation/Sass/Script/Functions.html#mix-instance_method\n const alphaDelta = a2 - a1;\n const normalizedWeight = weight * 2 - 1;\n const combinedWeight = normalizedWeight * alphaDelta === -1 ? normalizedWeight : normalizedWeight + alphaDelta / (1 + normalizedWeight * alphaDelta);\n const weight2 = (combinedWeight + 1) / 2;\n const weight1 = 1 - weight2;\n const r = (r1 * weight1 + r2 * weight2) * 255;\n const g = (g1 * weight1 + g2 * weight2) * 255;\n const b = (b1 * weight1 + b2 * weight2) * 255;\n const a = a2 * weight + a1 * (1 - weight);\n return rgba(r, g, b, a);\n}\n\n/**\n * Given a series colors, this function will return a `scale(x)` function that\n * accepts a percentage as a decimal between 0 and 1 and returns the color at\n * that percentage in the scale.\n *\n * ```js\n * const scale = getScale('red', 'yellow', 'green');\n * console.log(scale(0)); // rgba(255, 0, 0, 1)\n * console.log(scale(0.5)); // rgba(255, 255, 0, 1)\n * console.log(scale(1)); // rgba(0, 128, 0, 1)\n * ```\n *\n * If you'd like to limit the domain and range like chroma-js, we recommend\n * wrapping scale again.\n *\n * ```js\n * const _scale = getScale('red', 'yellow', 'green');\n * const scale = x => _scale(x / 100);\n *\n * console.log(scale(0)); // rgba(255, 0, 0, 1)\n * console.log(scale(50)); // rgba(255, 255, 0, 1)\n * console.log(scale(100)); // rgba(0, 128, 0, 1)\n * ```\n */\nfunction getScale(...colors) {\n return n => {\n const lastIndex = colors.length - 1;\n const lowIndex = guard(0, lastIndex, Math.floor(n * lastIndex));\n const highIndex = guard(0, lastIndex, Math.ceil(n * lastIndex));\n const color1 = colors[lowIndex];\n const color2 = colors[highIndex];\n const unit = 1 / lastIndex;\n const weight = (n - unit * lowIndex) / unit;\n return mix(color1, color2, weight);\n };\n}\n\nconst guidelines = {\n decorative: 1.5,\n readable: 3,\n aa: 4.5,\n aaa: 7\n};\n\n/**\n * Returns whether or not a color has bad contrast against a background\n * according to a given standard.\n */\nfunction hasBadContrast(color, standard = 'aa', background = '#fff') {\n return getContrast(color, background) < guidelines[standard];\n}\n\n/**\n * Lightens a color by a given amount. This is equivalent to\n * `darken(color, -amount)`\n *\n * @param amount The amount to darken, given as a decimal between 0 and 1\n */\nfunction lighten(color, amount) {\n return darken(color, -amount);\n}\n\n/**\n * Takes in a color and makes it more transparent by convert to `rgba` and\n * decreasing the amount in the alpha channel.\n *\n * @param amount The amount to increase the transparency by, given as a decimal between 0 and 1\n */\nfunction transparentize(color, amount) {\n const [r, g, b, a] = parseToRgba(color);\n return rgba(r, g, b, a - amount);\n}\n\n/**\n * Takes a color and un-transparentizes it. Equivalent to\n * `transparentize(color, -amount)`\n *\n * @param amount The amount to increase the opacity by, given as a decimal between 0 and 1\n */\nfunction opacify(color, amount) {\n return transparentize(color, -amount);\n}\n\n/**\n * An alternative function to `readableColor`. Returns whether or not the \n * readable color (i.e. the color to be place on top the input color) should be\n * black.\n */\nfunction readableColorIsBlack(color) {\n return getLuminance(color) > 0.179;\n}\n\n/**\n * Returns black or white for best contrast depending on the luminosity of the\n * given color.\n */\nfunction readableColor(color) {\n return readableColorIsBlack(color) ? '#000' : '#fff';\n}\n\n/**\n * Saturates a color by converting it to `hsl` and increasing the saturation\n * amount. Equivalent to `desaturate(color, -amount)`\n * \n * @param color Input color\n * @param amount The amount to darken, given as a decimal between 0 and 1\n */\nfunction saturate(color, amount) {\n return desaturate(color, -amount);\n}\n\n/**\n * Takes in any color and returns it as a hex code.\n */\nfunction toHex(color) {\n const [r, g, b, a] = parseToRgba(color);\n let hex = x => {\n const h = guard(0, 255, x).toString(16);\n // NOTE: padStart could be used here but it breaks Node 6 compat\n // https://github.com/ricokahler/color2k/issues/351\n return h.length === 1 ? `0${h}` : h;\n };\n return `#${hex(r)}${hex(g)}${hex(b)}${a < 1 ? hex(Math.round(a * 255)) : ''}`;\n}\n\n/**\n * Takes in any color and returns it as an rgba string.\n */\nfunction toRgba(color) {\n return rgba(...parseToRgba(color));\n}\n\n/**\n * Takes in any color and returns it as an hsla string.\n */\nfunction toHsla(color) {\n return hsla(...parseToHsla(color));\n}\n\nexport { ColorError$1 as ColorError, adjustHue, darken, desaturate, getContrast, getLuminance, getScale, guard, hasBadContrast, hsla, lighten, mix, opacify, parseToHsla, parseToRgba, readableColor, readableColorIsBlack, rgba, saturate, toHex, toHsla, toRgba, transparentize };\n//# sourceMappingURL=index.exports.import.es.mjs.map\n","/**\n * A module with multiple util JS functions\n * @module UtilFunctions\n */\n\nimport {\n\tisEqual,\n\tmerge as _merge,\n\tmergeWith as _mergeWith,\n\tkebabCase\n} from 'lodash-es';\nimport { toHex } from 'color2k';\n\n// Constants\nconst NON_WORD_CHARS_REGEX = /\\W+|[_]+/;\nconst WHITE_SPACE_REGEX = /\\s+/;\nconst SUPPORTED_URL_PROTOCOLS = new Set([\n\t'http:',\n\t'https:',\n\t'mailto:',\n\t'sms:',\n\t'tel:'\n]);\n\nconst CREATE_ELEMENT_DEFAULTS = {\n\ttagName: 'div',\n\tclassName: null,\n\tid: null,\n\tattributes: {}\n};\n\nconst dataUnits = [\n\t'byte',\n\t'kilobyte',\n\t'megabyte',\n\t'gigabyte',\n\t'terabyte',\n\t'petabyte',\n\t'exabyte',\n\t'zettabyte',\n\t'yottabyte'\n];\n\nconst CssUnits = [\n\t'cm',\n\t'mm',\n\t'in',\n\t'px',\n\t'pt',\n\t'pc',\n\t'em',\n\t'ex',\n\t'ch',\n\t'rem',\n\t'vw',\n\t'vh',\n\t'vmin',\n\t'vmax',\n\t'%'\n];\n\nconst borderStyles = [\n\t'none',\n\t'hidden',\n\t'dotted',\n\t'dashed',\n\t'solid',\n\t'double',\n\t'groove',\n\t'ridge',\n\t'inset',\n\t'outset',\n\t'initial',\n\t'inherit'\n];\n\nconst genericFonts = [\n\t'cursive',\n\t'fantasy',\n\t'math',\n\t'monospace',\n\t'sans-serif',\n\t'serif'\n];\n\nconst webSafeFonts = [\n\t'Arial',\n\t'Brush Script MT',\n\t'Courier New',\n\t'Garamond',\n\t'Georgia',\n\t'Helvetica',\n\t'Tahoma',\n\t'Times New Roman',\n\t'Trebuchet MS',\n\t'Verdana'\n];\n\nconst webFonts = ['Calibri', 'Nova Square', 'Nunito', 'Poppins', 'Vina Sans'];\n\nconst windowsFonts = [\n\t'Arial',\n\t'Arial Black',\n\t'Bahnschrift',\n\t'Calibri',\n\t'Cambria',\n\t'Cambria Math',\n\t'Candara',\n\t'Cascadia Code',\n\t'Cascadia Mono',\n\t'Comic Sans MS',\n\t'Consolas',\n\t'Constantia',\n\t'Corbel',\n\t'Courier New',\n\t'Ebrima',\n\t'Franklin Gothic Medium',\n\t'Gabriola',\n\t'Gadugi',\n\t'Georgia',\n\t'HoloLens MDL2 Assets',\n\t'Impact',\n\t'Ink Free',\n\t'Javanese Text',\n\t'Leelawadee UI',\n\t'Lucida Console',\n\t'Lucida Sans Unicode',\n\t'Malgun Gothic',\n\t'Marlett',\n\t'Microsoft Himalaya',\n\t'Microsoft JhengHei',\n\t'Microsoft New Tai Lue',\n\t'Microsoft PhagsPa',\n\t'Microsoft Sans Serif',\n\t'Microsoft Tai Le',\n\t'Microsoft YaHei',\n\t'Microsoft Yi Baiti',\n\t'MingLiU-ExtB',\n\t'Mongolian Baiti',\n\t'MS Gothic',\n\t'MV Boli',\n\t'Myanmar Text',\n\t'Nirmala UI',\n\t'Palatino Linotype',\n\t'Segoe Fluent Icons',\n\t'Segoe MDL2 Assets',\n\t'Segoe Print',\n\t'Segoe Script',\n\t'Segoe UI',\n\t'Segoe UI Emoji',\n\t'Segoe UI Historic',\n\t'Segoe UI Symbol',\n\t'Segoe UI Variable',\n\t'SimSun',\n\t'Sitka',\n\t'Sylfaen',\n\t'Symbol',\n\t'Tahoma',\n\t'Times New Roman',\n\t'Trebuchet MS',\n\t'Verdana',\n\t'Webdings',\n\t'Wingdings',\n\t'Yu Gothic'\n];\n\nconst cssFontWeights = [\n\t'normal',\n\t'bold',\n\t'bolder',\n\t'lighter',\n\t'inherit',\n\t'initial',\n\t100,\n\t200,\n\t300,\n\t400,\n\t500,\n\t600,\n\t700,\n\t800,\n\t900\n];\n\nconst urlRegExp = new RegExp(\n\t/((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[-;:&=+$,\\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\\w]+@)[A-Za-z0-9.-]+)((?:\\/[+~%/.\\w-_]*)?\\??(?:[-+=&;%@.\\w_]*)#?(?:[\\w]*))?)/\n);\n\n/**\n * Checks if a JavaScript function has a non-empty body.\n *\n * @param {Function} func - The function to check.\n * @throws {Error} Throws an error if the input is not a function.\n * @return {boolean} Returns true if the function's body is not empty, otherwise false.\n *\n * @example\n * // Define an empty function\n * function emptyFunction() {}\n *\n * // Define a function with a non-empty body\n * function nonEmptyFunction() {\n * console.log('Hello, world!');\n * }\n *\n * console.log(functionHasBody(emptyFunction)); // false\n * console.log(functionHasBody(nonEmptyFunction)); // true\n */\nfunction functionHasBody(func) {\n\tif (typeof func !== 'function') {\n\t\tthrow new Error('Input is not a function');\n\t}\n\n\tconst funcStr = func.toString();\n\tconst bodyStartIndex = funcStr.indexOf('{');\n\tconst bodyEndIndex = funcStr.lastIndexOf('}');\n\n\tif (bodyStartIndex === -1 || bodyEndIndex === -1) {\n\t\treturn false; // Function doesn't have a body\n\t}\n\n\tconst bodyContent = funcStr.slice(bodyStartIndex + 1, bodyEndIndex).trim();\n\treturn bodyContent.length > 0;\n}\n\n/**\n * Converts an SVG string to a base64-encoded data URL.\n *\n * @param {string} svgString - The SVG string to convert.\n * @return {string} The base64-encoded data URL.\n */\nfunction svgToBase64(svgString) {\n\t// const svgData = encodeURIComponent(svgString);\n\tconst base64 = btoa(svgString);\n\tconst url = `data:image/svg+xml;base64,${base64}`;\n\treturn url;\n}\n\n/**\n * Downloads an HTML file with the specified HTML content.\n *\n * @param {string} htmlContent - The HTML content to be downloaded.\n * @param {object} options - The desired filename for the downloaded file (optional).\n */\nfunction downloadFile(\n\thtmlContent,\n\t{ fileName = 'file.html', type = 'text/html' }\n) {\n\tif (htmlContent) {\n\t\tconst blob = new Blob([htmlContent], { type });\n\t\tconst downloadUrl = URL.createObjectURL(blob);\n\t\tconst downloadLink = document.createElement('a');\n\t\tdownloadLink.href = downloadUrl;\n\t\tdownloadLink.download = fileName;\n\t\tdownloadLink.click();\n\t\tURL.revokeObjectURL(downloadUrl);\n\t}\n}\n\n/**\n * Debounce will prevent a function from being called twice in a given time.\n * The function called will be delayed by a giving time and if the function is called again, the previous function call is canceled\n * @param { function } cb - The function to call.\n * @param { number } delay - The delay to wait until the function is called again.\n * @return { function } - The given function to call.\n * @function\n */\nfunction debounce(cb, delay = 250) {\n\tlet timeout;\n\n\treturn (...args) => {\n\t\tclearTimeout(timeout);\n\t\ttimeout = setTimeout(() => {\n\t\t\tcb(...args);\n\t\t}, delay);\n\t};\n}\n\n/**\n * Throttle will call the function passed to it every time the delay ends as long\n * as the trigger for the function is still happening.\n * @param { function } cb - The function to call.\n * @param { number } delay - The delay to wait until the function is called again.\n * @return { function } - The given function to call.\n * @function\n */\nfunction throttle(cb, delay = 1000) {\n\tlet shouldWait = false;\n\tlet waitingArgs;\n\tconst timeoutFunc = () => {\n\t\tif (waitingArgs == null) {\n\t\t\tshouldWait = false;\n\t\t} else {\n\t\t\tcb(...waitingArgs);\n\t\t\twaitingArgs = null;\n\t\t\tsetTimeout(timeoutFunc, delay);\n\t\t}\n\t};\n\n\treturn (...args) => {\n\t\tif (shouldWait) {\n\t\t\twaitingArgs = args;\n\t\t\treturn;\n\t\t}\n\n\t\tcb(...args);\n\t\tshouldWait = true;\n\t\tsetTimeout(timeoutFunc, delay);\n\t};\n}\n\n/**\n * Transforms a string into a boolean.\n * @param { 'true' | 'false' } string - A string indicating the boolean value.\n * @return { boolean } - The evaluated boolean value.\n * @function\n */\nconst toBoolean = string => {\n\treturn string.toLowerCase().trim() === 'true' ? true : false;\n};\n\n/**\n * Convert string to camelCase text.\n * @param { string } text - The string to be converted.\n * @return { string } The given string in camelCase\n * @function\n */\nfunction camelCase(text) {\n\tconst formatCase = (word, index) => {\n\t\tconst formattedNonFirstWord =\n\t\t\tword.charAt(0).toUpperCase() + word.slice(1);\n\t\treturn index === 0 ? word.toLowerCase() : formattedNonFirstWord;\n\t};\n\n\treturn text\n\t\t.replace(NON_WORD_CHARS_REGEX, ' ')\n\t\t.split(WHITE_SPACE_REGEX)\n\t\t.map((word, index) => formatCase(word, index))\n\t\t.join('');\n}\n\n/**\n * Set the inner content of a container. Uses innerHTML prop or append method based on the type of content (string/element)\n * @param { HTMLElement } container - The container to add the content to.\n * @param { HTMLElement | HTMLString | (HTMLElement | HTMLString)[] } content - The content to add to the container.\n * @param { boolean } append - if true it would append the content to the container instead of replacing it.\n * @return { HTMLElement } The container with the new content\n * @function\n */\nfunction setContent(container, content, append) {\n\t/**\n\t * Set the inner content of a container. Uses innerHTML prop or append method based on the type of content (string/element)\n\t * @param { HTMLElement } container - The container to add the content to.\n\t * @param { HTMLElement | HTMLString | (HTMLElement | HTMLString) [] } content - The content to add to the container.\n\t * @param { boolean } append - if true it would append the content to the container instead of replacing it.\n\t * @function\n\t */\n\tfunction setContentInner(container, content, append) {\n\t\tif (isElement(content) || isComment(content)) {\n\t\t\tif (!append) container.innerHTML = '';\n\t\t\tcontainer.append(content);\n\t\t} else {\n\t\t\tif (!append) {\n\t\t\t\tcontainer.innerHTML = content;\n\t\t\t} else {\n\t\t\t\tconst auxEl = document.createElement('div');\n\t\t\t\tauxEl.innerHTML = content;\n\t\t\t\tcontainer.append(...auxEl.children);\n\t\t\t}\n\t\t}\n\t}\n\tif (Array.isArray(content) || content instanceof NodeList) {\n\t\tif (content instanceof NodeList) content = Array.from(content);\n\t\tcontent\n\t\t\t.filter(c => c !== null && c !== undefined && c !== false)\n\t\t\t.forEach((c, i) => {\n\t\t\t\tsetContentInner(container, c, i != 0 || append);\n\t\t\t});\n\t} else {\n\t\tsetContentInner(container, content, append);\n\t}\n\n\treturn container;\n}\n\n/**\n * Get the percentage of the element's width relative to its parent.\n * @param { HTMLElement } element - The element to get the width from.\n * @param { { numberOnly: boolean, parentEl: HTMLElement } } options - The options object.\n * @return { number | string } The percentage of the element's width comparing to its parent\n * @function\n */\nfunction getElementWidthPercentage(\n\telement,\n\toptions = { numberOnly: false, parentEl: null }\n) {\n\tconst defaults = {\n\t\tnumberOnly: false,\n\t\tparentEl: null\n\t};\n\n\toptions = merge(defaults, options);\n\n\tconst parent = isElement(options.parentEl)\n\t\t? options.parentEl\n\t\t: element.parentNode;\n\tif (!parent) {\n\t\tconsole.error(\n\t\t\t\"The element you're trying to get the width from doesn't have a parent element\"\n\t\t);\n\t}\n\tconst elementWidth = element.offsetWidth;\n\tconst parentWidth = parent.offsetWidth;\n\n\tconst percentage = (elementWidth / parentWidth) * 100;\n\tif (options.numberOnly) return percentage;\n\treturn `${percentage}%`;\n}\n\n/**\n * Adds multiple classes inside a string to an element.\n * @param { HTMLElement } element - The element to add the classes to.\n * @param { string } classes - The string with all the classes that need to be added.\n * @param { string } separator - The pattern describing where each split should occur,\n * in order to split 'classes' string into multiple classes.\n * @return { HTMLElement } The given element.\n * @function\n */\nfunction addClassesString(element, classes, separator = ' ') {\n\tif (classes) {\n\t\tif (separator != ' ') {\n\t\t\tseparator = separator.trim();\n\t\t\telement.classList.add(...trimAll(classes).split(separator));\n\t\t} else {\n\t\t\telement.classList.add(...classes.trim().split(separator));\n\t\t}\n\t}\n\treturn element;\n}\n\n/**\n * Returns the passed string without whitespace.\n * @param { string } str - The string to remove the whitespace from.\n * @return { string } The given string without whitespace.\n * @function\n */\nfunction trimAll(str) {\n\treturn str.replace(/\\s/g, '');\n}\n\n/**\n * Transforms HTML code in plain text.\n * @param { string } html - A string with valid HTML code.\n * @return { string } - The text that were inside the HTML code.\n * @function\n */\nconst htmlToPlainText = html => {\n\tconst tempDiv = document.createElement('div');\n\ttempDiv.innerHTML = html;\n\treturn tempDiv.textContent || tempDiv.innerText || '';\n};\n\n/**\n * Checks whether or not a givin object is an HTML element.\n * @param { any } el - The object to check if is element.\n * @return { boolean } Whether or not 'el' is an HTML element.\n * @function\n */\nconst isElement = el => {\n\treturn typeof HTMLElement === 'object'\n\t\t? el instanceof HTMLElement\n\t\t: el &&\n\t\t\t\ttypeof el === 'object' &&\n\t\t\t\tel !== null &&\n\t\t\t\tel.nodeType === 1 &&\n\t\t\t\ttypeof el.nodeName === 'string';\n};\n\n/**\n * Removes all the spaces of a string.\n * @param { string } string - The string to remove the spaces from.\n * @param { boolean } onlySpaceChar - If set to true it would only remove literal space characters.\n * @return { string } - The string without spaces.\n * @function\n */\nfunction removeSpaces(string, onlySpaceChar) {\n\treturn onlySpaceChar ? string.replace(/ /g, '') : string.replace(/\\s/g, '');\n}\n\n/**\n * Adds an event listener to the given DOM element and attaches the specified callback function to it.\n *\n * @param {HTMLElement} element - The DOM element to which the event listener will be attached.\n * @param {string} eventType - The type of the event to listen for (e.g., 'click', 'keydown', 'mouseover', etc.).\n * @param {Function} callback - The function to be executed when the specified event is triggered.\n * @param {Object|boolean} [options] - An optional object specifying listener options, such as 'capture', 'once', or 'passive',\n * or a boolean value indicating whether the event should be captured during the event's\n * capturing phase (true) or bubbling phase (false). Default is false.\n * @return {HTMLElement} The same DOM element that the event listener was added to.\n *\n * @example\n * // Adding a click event listener to a button element\n * const myButton = document.getElementById('my-button');\n * elementAddEvent(myButton, 'click', () => {\n * console.log('Button clicked!');\n * });\n */\nfunction elementAddEvent(element, eventType, callback, options) {\n\telement.addEventListener(eventType, callback, options);\n\treturn element;\n}\n\n/**\n * Finds the element where the caret is in at the moment of the call.\n * @param { HTMLElement } [parent=null] - If passed it would only return an element if is a descendent of the passed element.\n * @param { boolean } [directChild=false] - If true, the parent param needs to represent a direct parent, else just a ancestor.\n * @return { HTMLElement } - The Element where the caret is in.\n * @function\n */\nfunction getCaretElement(parent, directChild = false) {\n\tlet el = window.getSelection().getRangeAt(0).commonAncestorContainer;\n\tel = isElement(el) ? el : el.parentNode;\n\tif (parent) {\n\t\tif (\n\t\t\t(directChild && el.parentNode == parent) ||\n\t\t\t(!directChild && parent.contains(el))\n\t\t) {\n\t\t\treturn el;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t} else {\n\t\treturn el;\n\t}\n}\n\n/**\n * Moves an element of the given array from an index to another.\n * @param { Array } array - The array to operate in.\n * @param { number } from - the index of the item to move.\n * @param { number } to - The new index of the item.\n * @function\n */\nfunction arrayMove(array, from, to) {\n\tarray.splice(to, 0, array.splice(from, 1)[0]);\n}\n\n/**\n * Splits an array into multiple parts.\n *\n * @param {Array} array - The array to be split.\n * @param {number} parts - The number of parts to split the array into.\n * @return {Array} - An array containing the split parts of the original array.\n */\nfunction splitArrayIntoParts(array, parts) {\n\tconst result = [];\n\tfor (let i = 0; i < parts; i++) {\n\t\tconst start = Math.floor((i * array.length) / parts);\n\t\tconst end = Math.floor(((i + 1) * array.length) / parts);\n\t\tresult.push(array.slice(start, end));\n\t}\n\treturn result;\n}\n\n/**\n * Removes a given item from the given array.\n * @param { Array } array - The array to operate in.\n * @param { any } item - The item to be removed.\n * @function\n */\nfunction arrayRemove(array, item) {\n\tarray.splice(array.indexOf(item), 1);\n}\n\n/**\n * Converts an object in an array.\n * @param { object } object - The object to convert.\n * @param { boolean } includeObjectKey - Whether or not to include the keys of the object in the array. If set to\n * false, the value of each array item would be the value of each key, if set to true, each array item would be an\n * object. Defaults to false.\n * @return {Array } The object converted in an array.\n * @function\n */\nfunction objToArray(object, includeObjectKey = false) {\n\treturn Object.keys(object).map(function (key) {\n\t\tif (includeObjectKey) {\n\t\t\treturn { [key]: object[key] };\n\t\t} else {\n\t\t\treturn object[key];\n\t\t}\n\t});\n}\n\n/**\n * Returns a string with the unit of a given value. i.e: '100px' would return 'px'.\n * @param { string } value - The value to get the unit from (i.e. '100px').\n * @return { string } - The unit of the given value.\n * @function\n */\nfunction getUnit(value) {\n\tif (value?.trim) {\n\t\tconst match = value.trim().match(/[a-zA-Z%]+/);\n\t\treturn match ? match[0] : null;\n\t}\n\tconsole.error('getUnit: value must be a string');\n\treturn null;\n}\n\n/**\n * Returns the estimated image file size in bytes.\n * @param { number } width - The width of the image.\n * @param { number } height - The height of the image.\n * @param { number } colorDepth - The color depth of the image. Defaults to 24 [bits of color].\n * @param { number } compression - The compression rate of the image. Defaults to 20:1 => 0.05.\n * @return { number } - The image size in bytes.\n * @function\n */\nfunction getImageSize(width, height, colorDepth = 24, compression = 0.05) {\n\treturn (width * height * colorDepth) / 8 / compression;\n}\n\n/**\n * Converts a value between two data units.\n * @param { number } value - The value to convert.\n * @param { string } from - The unit of the value to convert from.\n * @param { string } to - The unit to convert the value to.\n * @param { boolean } binary - Whether or not to use Base 2 conversion.\n * @return { number } - The value converted.\n * @function\n */\nfunction convertDataUnit(value, from, to, binary = false) {\n\t// parameters validation\n\tif (dataUnits.indexOf(to) < 0)\n\t\tthrow new Error(`Couldn't resolve unit '${to}'`);\n\telse if (dataUnits.indexOf(from) < 0)\n\t\tthrow new Error(`Couldn't resolve unit '${from}'`);\n\telse if (isNaN(parseInt(value))) throw new Error('value must be a number');\n\n\tif (dataUnits.indexOf(to) > dataUnits.indexOf(from)) {\n\t\treturn (\n\t\t\tparseInt(value) /\n\t\t\tMath.pow(\n\t\t\t\tbinary ? 1024 : 1000,\n\t\t\t\tdataUnits.indexOf(to) - dataUnits.indexOf(from)\n\t\t\t)\n\t\t);\n\t} else {\n\t\treturn (\n\t\t\tparseInt(value) *\n\t\t\tMath.pow(\n\t\t\t\tbinary ? 1024 : 1000,\n\t\t\t\tdataUnits.indexOf(from) - dataUnits.indexOf(to)\n\t\t\t)\n\t\t);\n\t}\n}\n\n/**\n * Adds one or multiple classes to an element.\n * @param { Element } element - The element to add the css class(es) to.\n * @param { string | string[] } cssClass - The css class(es) to be applied\n * to the element. The strings should be valid css classes. Warning: Cannot\n * contain whitespace.\n * @return { Element } The given element.\n * @function\n */\nfunction addCssClass(element, cssClass) {\n\tif (Array.isArray(cssClass)) {\n\t\tif (\n\t\t\tcssClass.filter(str => {\n\t\t\t\treturn str.indexOf(' ') > -1;\n\t\t\t}).length\n\t\t) {\n\t\t\tcssClass.forEach((str, idx) => {\n\t\t\t\tcssClass[idx] = removeSpaces(cssClass[idx]);\n\t\t\t});\n\t\t\tconsole.error(\n\t\t\t\t'cssClass cannot contain white spaces in addCssClass'\n\t\t\t);\n\t\t}\n\n\t\telement.classList.add(...cssClass);\n\t} else {\n\t\tif (cssClass.indexOf(' ') > -1) {\n\t\t\tcssClass = removeSpaces(cssClass);\n\t\t\tconsole.error(\n\t\t\t\t'cssClass cannot contain white spaces in addCssClass'\n\t\t\t);\n\t\t}\n\n\t\telement.classList.add(cssClass);\n\t}\n\treturn element;\n}\n\n/**\n * Gets the first child of an element that isn't a textNode.\n * @param { Element } element - The element get the child from.\n * @return { Element } The first child of the given element excluding textNodes.\n * @function\n */\nfunction getFirstChild(element) {\n\tvar firstChild = element.firstChild;\n\twhile (firstChild != null && firstChild.nodeType == 3) {\n\t\tfirstChild = firstChild.nextSibling;\n\t}\n\treturn firstChild;\n}\n\n/**\n * TODO: docs for this one\n * @param { Element } node - The element get the child from.\n * @param { object } data - The element get the child from.\n * @param { boolean } useBracketsSearch - The element get the child from.\n * @return { Element } The first child of the given element excluding textNodes.\n * @function\n */\nfunction template(node, data, useBracketsSearch) {\n\treturn node.innerHTML.replace(\n\t\tuseBracketsSearch ? /%(\\w*)%/g : /{(\\w*)}/g, // or /{(\\w*)}/g for \"{this} instead of %this%\"\n\t\tfunction (m, key) {\n\t\t\treturn data.hasOwnProperty(key) ? data[key] : '';\n\t\t}\n\t);\n}\n\n/**\n * Creates a node element based on an options object\n * @param { CreateElementOptions } options - The options to config the creation of the element.\n * @return { Element } The element created with the given options.\n * @function\n */\nfunction createElement(options) {\n\toptions = {\n\t\t...CREATE_ELEMENT_DEFAULTS,\n\t\t...options\n\t};\n\n\tconst element = document.createElement(options.tagName);\n\tif (options.className) element.className = options.className;\n\tif (options.id) element.setAttribute('id', options.className);\n\tif (options.attributes) {\n\t\tfor (const attr in options.attributes) {\n\t\t\tif (options.attributes.hasOwnProperty(attr))\n\t\t\t\telement[attr] = options.attributes[attr];\n\t\t}\n\t}\n\n\treturn element;\n}\n\n/**\n * Converts an object with properties topLeft, topRight, bottomLeft, and bottomRight into a CSS string.\n * @param {Object} propsObj - The object containing the properties topLeft, topRight, bottomLeft, and bottomRight.\n * @return {string} The CSS string representing the converted properties.\n */\nfunction convertCornerPropsToCSS(propsObj) {\n\tconst { topLeft, topRight, bottomLeft, bottomRight } = propsObj;\n\treturn `${topLeft} ${topRight} ${bottomRight} ${bottomLeft}`;\n}\n\n/**\n * Converts a CSS string representing border radius into an object with properties topLeft, topRight, bottomLeft, and bottomRight.\n * @param {string} cssString - The CSS string representing border radius.\n * @return {Object} The object containing the properties topLeft, topRight, bottomLeft, and bottomRight.\n */\nfunction convertCssStringToObj(cssString) {\n\tconst values = cssString.split(' ');\n\tconst defaultProps = {\n\t\ttopLeft: '0',\n\t\ttopRight: '0',\n\t\tbottomLeft: '0',\n\t\tbottomRight: '0'\n\t};\n\n\tif (values.length === 1) {\n\t\treturn {\n\t\t\t...defaultProps,\n\t\t\ttopLeft: values[0],\n\t\t\ttopRight: values[0],\n\t\t\tbottomLeft: values[0],\n\t\t\tbottomRight: values[0]\n\t\t};\n\t} else if (values.length === 2) {\n\t\treturn {\n\t\t\t...defaultProps,\n\t\t\ttopLeft: values[0],\n\t\t\ttopRight: values[1],\n\t\t\tbottomLeft: values[0],\n\t\t\tbottomRight: values[1]\n\t\t};\n\t} else if (values.length === 3) {\n\t\treturn {\n\t\t\t...defaultProps,\n\t\t\ttopLeft: values[0],\n\t\t\ttopRight: values[1],\n\t\t\tbottomLeft: values[2],\n\t\t\tbottomRight: values[1]\n\t\t};\n\t} else if (values.length >= 4) {\n\t\treturn {\n\t\t\t...defaultProps,\n\t\t\ttopLeft: values[0],\n\t\t\ttopRight: values[1],\n\t\t\tbottomRight: values[2],\n\t\t\tbottomLeft: values[3]\n\t\t};\n\t}\n\n\treturn defaultProps;\n}\n\n/**\n * Returns a string without tabs or line-feed (newline) characters.\n * @param { string } str - The string to shallow.\n * @param { boolean } removeTabs - Whether or not to remove tabs. Defaults to true.\n * @return { string } The given string without tabs or line-feed (newline) characters.\n * @function\n */\nfunction shallowString(str, removeTabs = true) {\n\tstr = str.replace(/(\\r\\n|\\n|\\r)/gm, '');\n\tstr = removeTabs ? str.replace(/\\t/gm, '') : str;\n\treturn str;\n}\n\n/**\n * Converts an object into an array recursively.\n * @param { object } val - The object to operate in.\n * @return { Array } The given object converted in array.\n * @function\n */\nfunction propertiesToArray(val) {\n\t// By default (val is not object or array, return the original value)\n\tvar result = val;\n\t// If object passed the result is the return value of Object.entries()\n\tif (typeof val === 'object' && !Array.isArray(val)) {\n\t\tresult = Object.entries(val);\n\t\t// If one of the results is an array or object, run this function on them again recursively\n\t\tresult.forEach(attr => {\n\t\t\tattr[1] = propertiesToArray(attr[1]);\n\t\t});\n\t}\n\t// If array passed, run this function on each value in it recursively\n\telse if (Array.isArray(val)) {\n\t\tval.forEach((v, i, a) => {\n\t\t\ta[i] = propertiesToArray(v);\n\t\t});\n\t}\n\t// Return the result\n\treturn result;\n}\n\n/**\n * Searches for a given key recursively starting in a given object or array.\n * @param { object | Array } obj - The object to search the key in.\n * @param { string } key - The key to retrieve the value from.\n * @return { Any | null } The value for the given key if founded. Else returns null.\n * @function\n */\nfunction searchObjectRecursively(obj, key) {\n\tif (typeof obj === 'object' && !Array.isArray(obj)) {\n\t\tif (obj[key]) {\n\t\t\treturn obj[key];\n\t\t}\n\t} else if (Array.isArray(obj)) {\n\t\tlet result;\n\t\tobj.forEach(item => {\n\t\t\tif (searchObjectRecursively(item, key)) {\n\t\t\t\tresult = searchObjectRecursively(item, key);\n\t\t\t}\n\t\t});\n\t\tif (result) return result;\n\t}\n\n\treturn;\n}\n\n/**\n * Removes a tag and its content from an HTML string.\n * @param { string } tagName - The tag to remove.\n * @param { string } str - The string to remove from.\n * @return { string } The given HTML string without the tag and its content.\n * @function\n */\nfunction removeHtmlByTag(tagName, str) {\n\tconst regexBody = /(\\d*?|\\D*?)/gm;\n\tconst regex = new RegExp(\n\t\t'<' + tagName + '>' + regexBody.source + '',\n\t\t'gm'\n\t);\n\treturn str.replace(regex, '');\n}\n\n/**\n * A simple event emitter class that allows subscribing to\n * and emitting events.\n */\nclass EventEmitter {\n\t/**\n\t * Constructs a new EventEmitter instance.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * A dictionary that stores event names as keys,\n\t\t * and an array of associated callbacks as values.\n\t\t * @type {Object.}\n\t\t * @private\n\t\t */\n\t\tthis.events = {};\n\t}\n\n\t/**\n\t * Subscribes to an event with the provided callback.\n\t * @param {string} eventName - The name of the event to subscribe to.\n\t * @param {Function} callback - The callback function to be executed\n\t * when the event is emitted.\n\t */\n\ton(eventName, callback) {\n\t\tif (!this.events[eventName]) {\n\t\t\tthis.events[eventName] = [];\n\t\t}\n\t\tthis.events[eventName].push(callback);\n\t}\n\n\t/**\n\t * Unsubscribes from an event with the provided callback.\n\t * @param {string} eventName - The name of the event to unsubscribe from.\n\t * @param {Function} callback - The callback function to be removed.\n\t */\n\toff(eventName, callback) {\n\t\tif (!this.events[eventName]) {\n\t\t\treturn;\n\t\t}\n\t\tthis.events[eventName] = this.events[eventName].filter(\n\t\t\tcb => cb !== callback\n\t\t);\n\t}\n\n\t/**\n\t * Emits an event with the provided arguments, triggering all\n\t * associated callbacks.\n\t * @param {string} eventName - The name of the event to emit.\n\t * @param {...*} args - Arguments to be passed to the event callbacks.\n\t */\n\temit(eventName, ...args) {\n\t\tif (!this.events[eventName]) {\n\t\t\treturn;\n\t\t}\n\t\tthis.events[eventName].forEach(callback => {\n\t\t\tcallback(...args);\n\t\t});\n\t}\n}\n\n/**\n * Copies the specified text to the clipboard using the Clipboard API.\n *\n * @param {string} text - The text to be copied to the clipboard.\n * @return {Promise} - A Promise that resolves when the text is successfully copied to the clipboard.\n * If there's an error, the Promise is rejected with an error message.\n *\n * @example\n * // Usage example:\n * copyToClipboard('Hello, world!').then(() => {\n * console.log('Text copied to clipboard.');\n * }).catch((error) => {\n * console.error('Failed to copy text:', error);\n * });\n */\nfunction copyToClipboard(text) {\n\treturn navigator.clipboard.writeText(text);\n}\n\n/**\n * Recursively compares two JavaScript objects and logs the keys and values that are different.\n *\n * @param {Object} obj1 - The first JavaScript object to compare.\n * @param {Object} obj2 - The second JavaScript object to compare.\n * @param {string[]} [path=[]] - An optional array to keep track of the current path during recursion.\n * @return {boolean} Whether obj1 and obj2 are equal. Would return true if there's any difference between them.\n */\nfunction deepCompareAndLog(obj1, obj2, path = []) {\n\tconst keys1 = Object.keys(obj1);\n\tconst keys2 = Object.keys(obj2);\n\tconst allKeys = new Set([...keys1, ...keys2]);\n\tlet isEqual = true;\n\n\tfor (const key of allKeys) {\n\t\tconst newPath = path.concat(key);\n\t\tconst value1 = obj1[key];\n\t\tconst value2 = obj2[key];\n\n\t\tif (typeof value1 === 'object' && typeof value2 === 'object') {\n\t\t\tisEqual = deepCompareAndLog(value1, value2, newPath);\n\t\t} else {\n\t\t\tif (value1 !== value2) {\n\t\t\t\tconsole.log(`Difference found at path: ${newPath.join('.')}`);\n\t\t\t\tconsole.log(`Value 1: ${value1}`);\n\t\t\t\tconsole.log(`Value 2: ${value2}`);\n\t\t\t\tisEqual = false;\n\t\t\t}\n\t\t}\n\t}\n\treturn isEqual;\n}\n\n/**\n * Finds the differences between two objects or arrays and logs them to the console.\n * @param {Object|Array} obj1 - The first object or array to compare.\n * @param {Object|Array} obj2 - The second object or array to compare.\n */\nfunction findDifferences(obj1, obj2) {\n\tconst stack = [{ obj1, obj2 }];\n\tconst diffs = [];\n\n\twhile (stack.length > 0) {\n\t\tconst { obj1, obj2 } = stack.pop();\n\n\t\t// Check if the objects are arrays\n\t\tconst isArray = Array.isArray(obj1) && Array.isArray(obj2);\n\n\t\t// Check if the objects are equal\n\t\tif (isEqual(obj1, obj2)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Log the differences\n\t\tif (isArray) {\n\t\t\tobj1.forEach((item, index) => {\n\t\t\t\tstack.push({ obj1: item, obj2: obj2[index] });\n\t\t\t});\n\t\t} else {\n\t\t\tObject.keys(obj1).forEach(key => {\n\t\t\t\tif (!isEqual(obj1[key], obj2[key])) {\n\t\t\t\t\tdiffs.push({ key, obj1: obj1[key], obj2: obj2[key] });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tif (diffs.length) console.log('Differences:');\n\tdiffs.forEach(({ key, obj1, obj2 }) => {\n\t\tconsole.log(`Key: ${key}`);\n\t\tconsole.log('Object 1:', obj1);\n\t\tconsole.log('Object 2:', obj2);\n\t});\n}\n\n/**\n * Removes all occurrences of a specified word (substring) from a given string.\n *\n * @param {string} inputString - The input string from which to remove the word.\n * @param {string} substring - The substring to be removed from the input string.\n * @param {boolean} isWord - If the substring to be removed is a word or a simple substring.\n * @param {number} occurrences - The number of times it should do the removal (all by default). @default -1\n * @return {string} The modified string with the specified word removed.\n *\n * @example\n * const inputString = \"This is a sample sentence with a word to remove.\";\n * const wordToRemove = \"word\";\n * const modifiedString = removeWord(inputString, wordToRemove);\n * console.log(modifiedString);\n * // Output: \"This is a sample sentence with a to remove.\"\n */\nfunction removeWord(inputString, substring, isWord = false, occurrences = -1) {\n\tconst regex = new RegExp(isWord ? `\\\\b${substring}\\\\b` : substring, 'gi');\n\tlet resultString;\n\n\tif (occurrences < 1) {\n\t\tresultString = inputString.replace(regex, '');\n\t} else {\n\t\tconst matches = inputString.match(regex);\n\t\tfor (let i = 0; i < occurrences; i++) {\n\t\t\tinputString = removeFirstSubstring(inputString, matches[i]);\n\t\t}\n\t\tresultString = inputString;\n\t}\n\n\treturn resultString;\n}\n\n/**\n * Removes the first occurrence of a substring from a string using a regular expression.\n * @param {string} inputString - The input string to remove the substring from.\n * @param {string} substring - The substring to remove from the input string.\n * @return {string} The output string with the first occurrence of the substring removed.\n */\nfunction removeFirstSubstring(inputString, substring) {\n\tconst regex = new RegExp(substring);\n\tconst index = inputString.search(regex);\n\tif (index !== -1) {\n\t\treturn (\n\t\t\tinputString.slice(0, index) +\n\t\t\tinputString.slice(index + substring.length)\n\t\t);\n\t} else {\n\t\treturn inputString;\n\t}\n}\n\n/**\n * Removes quotation marks from a string.\n * @param {string} inputString - The string to remove quotation marks from.\n * @return {string} The input string without quotation marks.\n */\nfunction unquoteString(inputString) {\n\treturn inputString.replace(/['\"]+/g, '');\n}\n\n/**\n * Converts a string of HTML into a DOM element.\n *\n * @param {string} html - The HTML string to convert.\n * @param {Object} [options] - An optional object containing additional options.\n * @param {boolean} [options.returnMultiple=false] - Whether to return multiple elements or just the first one.\n * @return {Element} The resulting DOM element.\n */\nfunction htmlToElement(html, options = {}) {\n\tconst defaults = {\n\t\treturnMultiple: false\n\t};\n\n\toptions = merge(defaults, options);\n\n\tconst template = document.createElement('template');\n\ttemplate.innerHTML = html.trim();\n\treturn options.returnMultiple\n\t\t? template.content.childNodes\n\t\t: template.content.firstChild;\n}\n\n/**\n * Sanitizes a URL by checking if it is a supported URL protocol.\n * If the URL is not supported, it returns 'about:blank'.\n * @param {string} url - The URL to sanitize.\n * @return {string} - The sanitized URL.\n */\nfunction sanitizeUrl(url) {\n\ttry {\n\t\tconst parsedUrl = new URL(url);\n\t\t// eslint-disable-next-line no-script-url\n\t\tif (!SUPPORTED_URL_PROTOCOLS.has(parsedUrl.protocol)) {\n\t\t\treturn 'about:blank';\n\t\t}\n\t} catch {\n\t\treturn url;\n\t}\n\treturn url;\n}\n\n/**\n * Validates a URL.\n * @param {string} url - The URL to be validated.\n * @return {boolean} - Returns true if the URL is valid, otherwise false.\n */\nfunction validateUrl(url) {\n\treturn url === 'https://' || urlRegExp.test(url);\n}\n\n/**\n * Returns a string with the valid unit of a given value or the default unit if the unit cannot be resolved.\n *\n * @param {string} value - The string containing the unit.\n * @param {Object} options - The options for resolving the unit.\n * @param {Array} options.validUnits - An array of valid units.\n * @param {string|null} options.defaultUnit - The default unit to return if the unit cannot be resolved.\n * @param {boolean} options.isDebug - Flag indicating whether to log debug information.\n * @param {string} options.errorMessage - The error message to log if the unit cannot be resolved.\n * @return {string|null} The resolved unit or the default unit if the unit cannot be resolved.\n */\nfunction getValidUnit(value, options) {\n\tconst defaultOptions = {\n\t\tvalidUnits: CssUnits,\n\t\tdefaultUnit: null,\n\t\tisDebug: false,\n\t\terrorMessage: `Value should contain a valid unit or a default unit should be provided, ${value}`\n\t};\n\toptions = merge(defaultOptions, options);\n\n\tconst extractedUnit = getUnit(value);\n\tif (\n\t\textractedUnit &&\n\t\tisValidUnit(\n\t\t\textractedUnit,\n\t\t\tmerge(options, {\n\t\t\t\terrorMessage: `getValidUnit: Unit is not valid, ${extractedUnit}`\n\t\t\t})\n\t\t)\n\t) {\n\t\treturn extractedUnit;\n\t}\n\n\tif (options.isDebug) console.error('getValidUnit:', options.errorMessage);\n\treturn options.defaultUnit;\n}\n\n/**\n * Checks if a value contains a valid number or one of the acceptable values.\n *\n * @param {string|number} value - The value to be checked.\n * @param {Object} options - The options for validation.\n * @param {Array} options.acceptableValues - An array of acceptable values.\n * @param {boolean} options.isDebug - A flag indicating whether to enable debug mode.\n * @param {string} options.errorMessage - The error message to be displayed if the value is invalid.\n * @return {boolean} - Returns true if the value has a valid value or is one of the acceptable values, otherwise returns false.\n */\nfunction isValidValue(value, options) {\n\tconst defaultOptions = {\n\t\tacceptableValues: null,\n\t\tisDebug: false,\n\t\terrorMessage: `Value doesn't contain a valid number or is not one of the acceptable values, ${value}`\n\t};\n\toptions = merge(defaultOptions, options);\n\n\tif (\n\t\toptions.acceptableValues?.includes(value) ||\n\t\t(!isNaN(parseFloat(value)) && !String(value).includes('NaN'))\n\t) {\n\t\treturn true;\n\t}\n\n\tif (options.isDebug) {\n\t\tconsole.error('isValidValue:', options.errorMessage);\n\t}\n\n\treturn false;\n}\n\n/**\n * Checks if a value is a valid dimension or one of the acceptable values.\n *\n * @param {string} value - The value to be checked.\n * @param {Object} options - The options object.\n * @param {Array} options.acceptableValues - An array of acceptable values.\n * @param {Array} options.validUnits - An array of valid units.\n * @param {boolean} options.isDebug - Flag to enable debug mode.\n * @param {string} options.errorMessage - The error message to be displayed.\n * @return {boolean} - Returns true if the value is a valid dimension or one of the acceptable values, otherwise false.\n */\nfunction isValidDimension(value, options) {\n\tconst defaultOptions = {\n\t\tacceptableValues: null,\n\t\tvalidUnits: CssUnits,\n\t\tisDebug: false,\n\t\terrorMessage: `Value should be a valid dimension or one of the acceptable values, ${value}`\n\t};\n\toptions = merge(defaultOptions, options);\n\n\tif (\n\t\tisValidValue(value, options) &&\n\t\t(options.acceptableValues?.includes(value) ||\n\t\t\tisValidUnit(getUnit(value), options))\n\t) {\n\t\treturn true;\n\t}\n\n\tif (options.isDebug)\n\t\tconsole.error('isValidDimension:', options.errorMessage);\n\n\treturn false;\n}\n\n/**\n * Checks if a given unit is a valid unit. By default, all CSS units are considered valid.\n *\n * @param {string} unit - The unit to be checked.\n * @param {Object} options - The options for the validation.\n * @param {string[]} options.validUnits - An array of valid units. All CSS units are valid by default.\n * @param {boolean} [options.isDebug=false] - Whether to log an error message to the console in case of an invalid unit.\n * @param {string} [options.errorMessage] - The error message to be logged in case of an invalid unit.\n * @return {boolean} - Returns true if the unit is valid, false otherwise.\n */\nfunction isValidUnit(unit, options) {\n\tconst defaultOptions = {\n\t\tvalidUnits: CssUnits,\n\t\tisDebug: false,\n\t\terrorMessage: `Unit should be one of the valid units, ${unit}`\n\t};\n\toptions = merge(defaultOptions, options);\n\n\tif (!options.validUnits || options.validUnits.includes(unit)) return true;\n\n\tif (options.isDebug) console.error('isValidUnit:', options.errorMessage);\n\n\treturn false;\n}\n\n/**\n * Inserts an object after every item in the array except the last one.\n *\n * @param {Array} arr - The input array.\n * @param {*} obj - The object to be inserted after every item.\n * @return {Array} - The modified array with the object inserted after every item but the last.\n *\n * @example\n * // Example usage:\n * let originalArray = [1, 2, 3];\n * let newArray = insertAfterEveryItem(originalArray, 0);\n * console.log(newArray); // Output: [1, 0, 2, 0, 3]\n */\nfunction insertAfterEveryItem(arr, obj) {\n\treturn arr.reduce((result, current, index, array) => {\n\t\tresult.push(current);\n\t\tif (index < array.length - 1) {\n\t\t\tresult.push(obj);\n\t\t}\n\t\treturn result;\n\t}, []);\n}\n\n/**\n * Checks for circular dependencies in a JavaScript object.\n *\n * @param {Object} obj - The object to check for circular dependencies.\n * @param {Set} [seenObjects=new Set()] - A set to keep track of visited objects (used internally for recursion).\n * @param {string} [currentPath=''] - The current path in the object hierarchy (used internally for logging).\n * @return {boolean} - Returns `true` if a circular dependency is found, otherwise `false`.\n *\n * @example\n * const obj1 = { name: 'Object 1' };\n * const obj2 = { name: 'Object 2', child: obj1 };\n * obj1.parent = obj2;\n *\n * const hasCircularDep = hasCircularDependency(obj1);\n * if (!hasCircularDep) {\n * console.log('No circular dependency found.');\n * }\n */\nfunction hasCircularDependency(obj, seenObjects = new Set(), currentPath = '') {\n\tif (typeof obj !== 'object' || obj === null) {\n\t\t// Not an object, no circular dependency\n\t\treturn false;\n\t}\n\n\tif (seenObjects.has(obj)) {\n\t\tconsole.log(`Circular dependency found at path: ${currentPath}`);\n\t\treturn true;\n\t}\n\n\tseenObjects.add(obj);\n\n\tfor (const key in obj) {\n\t\tif (!obj.hasOwnProperty(key)) continue;\n\t\tconst nextPath = currentPath ? `${currentPath}.${key}` : key;\n\t\tif (hasCircularDependency(obj[key], seenObjects, nextPath)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tseenObjects.delete(obj);\n\treturn false;\n}\n\n/**\n * Merges multiple objects into a single object without mutating any of them.\n *\n * @param {...Object} sources - The objects to merge.\n * @return {Object} - The merged object.\n */\nfunction merge(...sources) {\n\treturn _merge({}, ...sources);\n}\n\n/**\n * Merges multiple objects into a single object using a customizer function.\n *\n * @param {Object} object - The destination object to merge into.\n * @param {...Object} sources - The objects to merge.\n * @param {Function} customizer - The function to customize the merging behavior. Should return the value\n * to keep. If it returns undefined, the default merging behavior will be used.\n * @return {Object} - A new object resulting of the merged objects.\n *\n * @example\n * const object = { a: [1,2,3] };\n * const source1 = { a: [9,8] };\n *\n * console.log(mergeWith(object, source1));\n * // Output: { a: [9, 8, 3] }\n *\n * console.log(mergeWith({a: arr1}, {a:arr2}, (objValue, srcValue) => {\n * if (Array.isArray(objValue)) {\n * return objValue.concat(srcValue);\n * }\n * }));\n * // Output: { a: [1, 2, 3, 9, 8] }\n *\n * console.log(mergeWith({a: arr1}, {a:arr2}, (objValue, srcValue) => {\n * if (Array.isArray(objValue)) {\n * return objValue;\n * }\n * }));\n * // Output: { a: [1, 2, 3] }\n *\n * console.log(mergeWith({a: arr1}, {a:arr2}, (objValue, srcValue) => {\n * if (Array.isArray(objValue)) {\n * return srcValue;\n * }\n * }));\n * // Output: { a: [9, 8] }\n */\nfunction mergeWith(object, ...sources) {\n\treturn _mergeWith({}, object, ...sources);\n}\n\n/**\n * Checks if the given value is an array.\n *\n * @param {*} obj - The value to check.\n * @return {boolean} - Returns true if the value is an array, otherwise returns false.\n */\nfunction isArray(obj) {\n\treturn Array.isArray(obj);\n}\n\n/**\n * Checks if the given value is an object.\n *\n * @param {*} obj - The value to be checked.\n * @return {boolean} - Returns true if the value is an object, otherwise returns false.\n */\nfunction isObject(obj) {\n\treturn typeof obj === 'object';\n}\n\n/**\n * Checks if the given value is a function.\n *\n * @param {any} obj - The value to check.\n * @return {boolean} - Returns true if the value is a function, otherwise returns false.\n */\nfunction isFunction(obj) {\n\treturn typeof obj === 'function';\n}\n\n/**\n * Executes a provided function once for each array element.\n *\n * @param {Array} array - The array to iterate over.\n * @param {Function} callback - The function to execute for each element.\n * @return {Array} - The original array (can be mutated).\n */\nfunction forEach(array, callback) {\n\tarray.forEach(callback);\n\treturn array;\n}\n\n/**\n * Checks if a value is undefined.\n * @param {*} obj - The value to check.\n * @return {boolean} - Returns true if the value is undefined, otherwise returns false.\n */\nfunction isUndefined(obj) {\n\treturn typeof obj === 'undefined';\n}\n\n/**\n * Checks if a value is a boolean.\n * @param {any} obj - The value to check.\n * @return {boolean} - Returns true if the value is a boolean, otherwise returns false.\n */\nfunction isBoolean(obj) {\n\treturn typeof obj === 'boolean';\n}\n\n/**\n * Checks if the given value is a string.\n *\n * @param {*} obj - The value to check.\n * @return {boolean} - Returns true if the value is a string, otherwise returns false.\n */\nfunction isString(obj) {\n\treturn typeof obj === 'string';\n}\n\n/**\n * Copies attributes from the source element to the target element.\n * @param {Element} sourceElement - The source element to copy attributes from.\n * @param {Element} targetElement - The target element to copy attributes to.\n * @return {Element} - The target element with copied attributes.\n */\nfunction copyAttributes(sourceElement, targetElement) {\n\tArray.from(sourceElement.attributes).forEach(attr => {\n\t\ttargetElement.setAttribute(attr.name, attr.value);\n\t});\n\n\treturn targetElement;\n}\n\n/**\n * Checks if a string contains HTML tags.\n * @param {string} str - The string to check.\n * @return {boolean} - True if the string contains HTML tags, false otherwise.\n */\nfunction isHTML(str) {\n\tvar doc = new DOMParser().parseFromString(str, 'text/html');\n\treturn Array.from(doc.body.childNodes).some(node => node.nodeType === 1);\n}\n\n/**\n * Retrieves the HTML tags from the given HTML string.\n * @param {string} htmlString - The HTML string to parse.\n * @param {boolean} onlyFirstLevel - Indicates whether to retrieve only the tags from the first level of the HTML structure.\n * @return {string[]} - An array of lowercase tag names.\n */\nfunction getHTMLTags(htmlString, onlyFirstLevel) {\n\tvar doc = new DOMParser().parseFromString(htmlString, 'text/html');\n\tif (onlyFirstLevel) {\n\t\treturn Array.from(doc.body.childNodes)\n\t\t\t.filter(node => node.nodeType === 1) // Node.ELEMENT_NODE\n\t\t\t.map(node => node.tagName.toLowerCase());\n\t} else {\n\t\tvar allElements = doc.getElementsByTagName('*');\n\t\treturn Array.from(allElements).map(node => node.tagName.toLowerCase());\n\t}\n}\n\n/**\n * Converts an object into a string of CSS variables.\n * @param {Object} obj - The object to convert.\n * @return {string} - The string of CSS variables.\n */\nfunction objToCSSVariables(obj) {\n\tlet cssVariables = '';\n\n\tfor (const key in obj) {\n\t\tif (typeof obj[key] === 'object') {\n\t\t\tfor (const subKey in obj[key]) {\n\t\t\t\tif (obj[key].hasOwnProperty(subKey))\n\t\t\t\t\tcssVariables += ` --${subKey}-${key}: '${obj[key][subKey]}';\\n`;\n\t\t\t}\n\t\t} else {\n\t\t\tcssVariables += ` --${key}: ${obj[key]};\\n`;\n\t\t}\n\t}\n\n\treturn cssVariables;\n}\n\n/**\n * Checks if all elements in an array are equal.\n *\n * @param {Array} arr - The array to check.\n * @return {boolean} - Returns true if all elements are equal, false otherwise.\n */\nfunction allEqual(arr) {\n\treturn arr.every(val => val === arr[0]);\n}\n\n/**\n * Maps the properties of an object using a provided mapping object.\n * @param {Object} obj - The object to be mapped.\n * @param {Object} map - The mapping object containing the property mappings.\n * @param {boolean} [keepUnmapped=true] - Whether to keep the unmapped properties in the resulting object.\n * @return {Object} - The mapped object.\n */\nfunction mapObject(obj, map, keepUnmapped = true) {\n\tconst result = {};\n\tfor (const key in obj) {\n\t\tif (obj.hasOwnProperty(key) && map.hasOwnProperty(key)) {\n\t\t\tresult[map[key]] = obj[key];\n\t\t} else if (keepUnmapped && obj.hasOwnProperty(key)) {\n\t\t\tresult[key] = obj[key];\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Checks if a color is valid.\n * @param {string} color - The color to be checked.\n * @param {Object} options - The options for the function.\n * @param {boolean} options.returnColor - Whether to return the parsed color or just a boolean indicating validity. Default is true.\n * @return {string|boolean} - The parsed color if returnColor is true and the color is valid, otherwise false.\n */\nfunction isValidColor(color, { returnColor = true } = {}) {\n\ttry {\n\t\tconst parsedColor = toHex(color);\n\t\tif (parsedColor) {\n\t\t\treturn returnColor ? parsedColor : true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t} catch (e) {\n\t\treturn false;\n\t}\n}\n\n/**\n * Adds one or more elements to the beginning of an array and returns the new length of the array.\n *\n * @param {Array} arr - The array to modify.\n * @param {...*} items - The elements to add to the beginning of the array.\n * @return {number} - The new length of the array.\n */\nfunction arrayUnshift(arr, ...items) {\n\treturn items.concat(arr);\n}\n\n/**\n * Checks if a string ends with a specified suffix.\n * @param {string} str - The string to check.\n * @param {string} suffix - The suffix to check for.\n * @param {boolean} caseSensitive - Whether the comparison should be case-sensitive.\n * @return {boolean} - True if the string ends with the suffix, false otherwise.\n */\nfunction endsWith(str, suffix, caseSensitive) {\n\tif (caseSensitive) {\n\t\treturn str.indexOf(suffix, str.length - suffix.length) !== -1;\n\t} else {\n\t\treturn (\n\t\t\tstr\n\t\t\t\t.toLowerCase()\n\t\t\t\t.indexOf(suffix.toLowerCase(), str.length - suffix.length) !==\n\t\t\t-1\n\t\t);\n\t}\n}\n\n/**\n * Converts a CSS value containing sides (i.e. margins or paddings) to\n * object notation.\n *\n * @param {string} string - The CSS sides string to convert.\n * @return {Object} - An object with individual side values (top, right, bottom, left).\n *\n * @example\n * // returns {top: 10, right: 10, bottom: 10, left: 10}\n * cssSidesToObject(\"10px\");\n *\n * @example\n * // returns {top: 10, right: 20, bottom: 10, left: 20}\n * cssSidesToObject(\"10px 20px\");\n *\n * @example\n * // returns {top: 10, right: 20, bottom: 30, left: 20}\n * cssSidesToObject(\"10px 20px 30px\");\n *\n * @example\n * // returns {top: 10, right: 20, bottom: 30, left: 40}\n * cssSidesToObject(\"10px 20px 30px 40px\");\n */\nfunction cssSidesToObject(string) {\n\tconst values = string.split(' ').map(p => parseFloat(p));\n\n\tlet top;\n\tlet right;\n\tlet bottom;\n\tlet left;\n\tif (values.length === 1) {\n\t\t[top, right, bottom, left] = [\n\t\t\tvalues[0],\n\t\t\tvalues[0],\n\t\t\tvalues[0],\n\t\t\tvalues[0]\n\t\t];\n\t} else if (values.length === 2) {\n\t\t[top, bottom] = [values[0], values[0]];\n\t\t[right, left] = [values[1], values[1]];\n\t} else if (values.length === 3) {\n\t\t[top, right, left] = [values[0], values[1], values[1]];\n\t\tbottom = values[2];\n\t} else if (values.length === 4) {\n\t\t[top, right, bottom, left] = values;\n\t}\n\n\treturn { top, right, bottom, left };\n}\n\n/**\n * Converts a CSS value containing corners shorthand or full notation to\n * object notation.\n *\n * @param {string} string - The CSS string to convert.\n * @return {Object} - An object with individual corner values (topLeft, topRight, bottomRight, bottomLeft).\n *\n * @example\n * // returns {topLeft: 10, topRight: 10, bottomRight: 10, bottomLeft: 10}\n * cssCornersToObject(\"10px\");\n *\n * @example\n * // returns {topLeft: 10, topRight: 20, bottomRight: 10, bottomLeft: 20}\n * cssCornersToObject(\"10px 20px\");\n *\n * @example\n * // returns {topLeft: 10, topRight: 20, bottomRight: 30, bottomLeft: 20}\n * cssCornersToObject(\"10px 20px 30px\");\n *\n * @example\n * // returns {topLeft: 10, topRight: 20, bottomRight: 30, bottomLeft: 40}\n * cssCornersToObject(\"10px 20px 30px 40px\");\n */\nfunction cssCornersToObject(string) {\n\tconst values = string.split(' ').map(p => Number(p.replace('px', '')));\n\n\tlet topLeft;\n\tlet topRight;\n\tlet bottomRight;\n\tlet bottomLeft;\n\tif (values.length === 1) {\n\t\t[topLeft, topRight, bottomRight, bottomLeft] = [\n\t\t\tvalues[0],\n\t\t\tvalues[0],\n\t\t\tvalues[0],\n\t\t\tvalues[0]\n\t\t];\n\t} else if (values.length === 2) {\n\t\t[topLeft, bottomRight] = [values[0], values[0]];\n\t\t[topRight, bottomLeft] = [values[1], values[1]];\n\t} else if (values.length === 3) {\n\t\t[topLeft, topRight, bottomLeft] = [values[0], values[1], values[1]];\n\t\tbottomRight = values[2];\n\t} else if (values.length === 4) {\n\t\t[topLeft, topRight, bottomRight, bottomLeft] = values;\n\t}\n\n\treturn { topLeft, topRight, bottomRight, bottomLeft };\n}\n\n/**\n * Calculates the average of an array of numbers.\n *\n * @param {Array} arr - The array of numbers.\n * @param {number} [decimalPlaces=0] - The number of decimal places for the average result.\n * @return {number} The average of the array.\n *\n * @example\n * // returns 3\n * calculateAverage([1, 2, 3, 4, 5]);\n *\n * @example\n * // returns 3.33\n * calculateAverage([1, 2, 3, 4, 5], 2);\n *\n * @example\n * // returns 2\n * calculateAverage(['1', '2', '3']);\n */\nfunction arrayAvg(arr, decimalPlaces = 0) {\n\tif (!Array.isArray(arr)) {\n\t\tthrow new Error('The first argument must be an array.');\n\t}\n\n\tif (typeof decimalPlaces !== 'number') {\n\t\tthrow new Error('The second argument must be a number.');\n\t}\n\n\tconst numbers = arr.map(Number);\n\tconst sum = numbers.reduce((a, b) => a + b, 0);\n\tconst average = sum / numbers.length;\n\n\treturn Number(average.toFixed(decimalPlaces));\n}\n\n/**\n * Calculates the average of a list of numbers.\n *\n * @param {...number} numbers - The numbers to calculate the average of.\n * @return {number} The average of the numbers.\n */\nfunction avg(...numbers) {\n\treturn arrayAvg(numbers, 2);\n}\n\n/**\n * Converts a CSS style object to a string representation.\n *\n * @param {Object} style - The CSS style object to convert.\n * @param {Object} options - The options for the conversion.\n * @param {boolean} [options.convertToKebabCase=true] - Whether to convert CSS property names to kebab case.\n * @param {boolean} [options.trim=true] - Whether to trim the resulting string.\n * @return {string} The string representation of the CSS style object.\n *\n * @example\n * const style = {\n * backgroundColor: 'red',\n * fontSize: '16px',\n * fontWeight: 'bold'\n * };\n *\n * const options = {\n * convertToKebabCase: true,\n * trim: false\n * };\n *\n * const result = cssStyleObjectToString(style, options);\n * console.log(result);\n * // Output: \"background-color: red; font-size: 16px; font-weight: bold;\"\n */\nfunction cssStyleObjectToString(style, options) {\n\tconst defaults = {\n\t\tconvertToKebabCase: true,\n\t\ttrim: true\n\t};\n\n\toptions = merge(defaults, options);\n\n\tconst { convertToKebabCase, trim } = options;\n\n\tlet result = '';\n\tfor (const prop in style) {\n\t\tif (style.hasOwnProperty(prop)) {\n\t\t\tresult += `${convertToKebabCase ? kebabCase(prop) : prop}: ${\n\t\t\t\tstyle[prop]\n\t\t\t}; `;\n\t\t}\n\t}\n\treturn trim ? result.trim() : result;\n}\n\n/**\n * Parses a CSS style string into an object.\n *\n * @param {string} styleString - The CSS style string.\n * @return {Object} The parsed style object.\n */\nfunction parseStyleString(styleString) {\n\tconst styleObject = {};\n\tconst declarations = styleString.split(';');\n\n\tdeclarations.forEach(declaration => {\n\t\tif (declaration.trim()) {\n\t\t\tconst [property, value] = declaration.split(':');\n\t\t\tif (property && value) {\n\t\t\t\tstyleObject[property.trim()] = value.trim();\n\t\t\t}\n\t\t}\n\t});\n\n\treturn styleObject;\n}\n\n/**\n * Deletes a given property or an array of properties from an object.\n * @param {Object} obj - The object from which to delete properties.\n * @param {(string|string[])} props - The property or properties to delete.\n * @param {boolean} [mutate=true] - Whether to mutate the original object or return a new one.\n * @return {Object} - The object after deleting the properties.\n * @throws {TypeError} - If the first argument is not an object or the second argument is not a string or an array of strings.\n * @example\n * const obj = { a: 1, b: 2, c: 3 };\n * deleteProps(obj, 'a', false); // returns a new object { b: 2, c: 3 }, obj is unchanged\n * deleteProps(obj, ['b', 'c'], true); // returns obj { a: 1 }, obj is changed\n */\nfunction deleteProps(obj, props, mutate = true) {\n\tif (typeof obj !== 'object' || obj === null) {\n\t\tthrow new TypeError('First argument must be an object.');\n\t}\n\tif (typeof props === 'string') {\n\t\tif (!mutate) {\n\t\t\tobj = { ...obj };\n\t\t}\n\t\tif (props in obj) {\n\t\t\tdelete obj[props];\n\t\t}\n\t} else if (Array.isArray(props)) {\n\t\tif (!mutate) {\n\t\t\tobj = { ...obj };\n\t\t}\n\t\tprops.forEach(prop => {\n\t\t\tif (typeof prop !== 'string') {\n\t\t\t\tthrow new TypeError(\n\t\t\t\t\t'All elements in the array must be strings.'\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (prop in obj) {\n\t\t\t\tdelete obj[prop];\n\t\t\t}\n\t\t});\n\t} else {\n\t\tthrow new TypeError(\n\t\t\t'Second argument must be a string or an array of strings.'\n\t\t);\n\t}\n\treturn obj;\n}\n\n/**\n * Set the style of a DOM node with a JavaScript object.\n *\n * @param {Node} node - The DOM node to style.\n * @param {Object} styleObj - The style object.\n *\n * @example\n * // Change the color and background color of a node with kebab-case properties\n * const node = document.querySelector('#myNode');\n * setNodeStyle(node, { color: 'red', 'background-color': 'black' });\n *\n * @example\n * // Change the color and background color of a node with camel-case properties\n * const node = document.querySelector('#myNode');\n * setNodeStyle(node, { fontWeight: 600, 'backgroundColor': 'black' });\n */\nfunction setNodeStyle(node, styleObj) {\n\tObject.keys(styleObj).forEach(key => {\n\t\tnode.style[camelCase(key)] = styleObj[key];\n\t});\n}\n\n/**\n * Returns the maximum value among the passed arguments.\n * If a string containing a number is passed, it will be converted to a number.\n *\n * @param {...any} args - The arguments to compare.\n * @return {number} The maximum value among the passed arguments.\n *\n * @example\n * // returns 5\n * max(1, '2', 3, '5', 4);\n *\n * @example\n * // returns 10\n * max('1', '10', '3', '5', '4');\n */\nfunction max(...args) {\n\treturn Math.max(...args.map(arg => Number(arg)));\n}\n\n/**\n * Creates and returns a comment with some content to be rendered conditionally in Outlook.\n *\n * @param {string} content - The content to be rendered inside the comment.\n * @return {Comment} The created comment element.\n */\nfunction outlookConditionalRenderComment(content) {\n\treturn document.createComment(`[if mso]>${content} v2, and 0 if they are equal.\n */\nfunction compareVersions(v1, v2) {\n\tconst parts1 = v1.split('.').map(Number);\n\tconst parts2 = v2.split('.').map(Number);\n\tconst maxLength = Math.max(parts1.length, parts2.length);\n\n\tfor (let i = 0; i < maxLength; i++) {\n\t\tconst part1 = parts1[i] || 0;\n\t\tconst part2 = parts2[i] || 0;\n\n\t\tif (part1 > part2) return 1;\n\t\tif (part1 < part2) return -1;\n\t}\n\n\treturn 0;\n}\n\n/**\n * Removes single quotes from a string.\n *\n * @param {string} str - The input string.\n * @return {string} The string with single quotes removed.\n *\n * @example\n * // Returns \"Hello World\"\n * removeSingleQuotes(\"'Hello World'\");\n *\n * @example\n * // Returns \"This is a test\"\n * removeSingleQuotes(\"This is a test'\");\n *\n * @example\n * // Returns \"I'm happy\"\n * removeSingleQuotes(\"I'm happy\");\n */\nfunction removeSingleQuotes(str) {\n\treturn str.replace(/^'|'$/g, '');\n}\n\n/**\n * Converts a CSSStyleDeclaration object to a JavaScript object.\n *\n * @param {CSSStyleDeclaration} style - The CSSStyleDeclaration object to convert.\n * @return {Object} - The converted JavaScript object.\n *\n * @example\n * const style = window.getComputedStyle(element);\n * const styleObj = cssStyleDeclarationToObject(style);\n * console.log(styleObj);\n * // Output: { backgroundColor: \"red\", fontSize: \"16px\", fontWeight: \"bold\" }\n */\nfunction cssStyleDeclarationToObject(style) {\n\tconst styleObj = {};\n\tfor (let i = 0; i < style.length; i++) {\n\t\tconst prop = style[i];\n\t\tstyleObj[prop] = style.getPropertyValue(prop);\n\t}\n\treturn styleObj;\n}\n\n/**\n * Wraps the provided content in an MSO conditional comment if `outlookDebug` is false.\n *\n * @param {string} content - The content to be conditionally wrapped.\n * @param {boolean} [outlookDebug=false] - Flag to determine if the content should be wrapped in an MSO conditional comment.\n * @return {string} - The original content or the content wrapped in an MSO conditional comment.\n */\nfunction renderMsoConditional(content, outlookDebug = false) {\n\treturn outlookDebug ? content : ``;\n}\n\n/**\n * Renders content conditionally based on whether the email client is Microsoft Outlook.\n *\n * @param {string} content - The HTML content to be conditionally rendered.\n * @param {boolean} [outlookDebug=false] - Flag to determine if the content should be rendered for debugging in Outlook.\n * @return {string} - The conditional HTML content.\n */\nfunction renderNotMsoConditional(content, outlookDebug = false) {\n\treturn outlookDebug ? '' : `${content}`;\n}\n\n/**\n * Returns a random number between the specified min and max values.\n *\n * @param {number} min - The minimum value (inclusive).\n * @param {number} max - The maximum value (inclusive).\n * @return {number} A random number between min and max.\n *\n * @example\n * // returns a random number between 1 and 10\n * const randomNum = getRandomNumberBetween(1, 10);\n * console.log(randomNum);\n *\n * @example\n * // returns a random number between -5 and 5\n * const randomNum = getRandomNumberBetween(-5, 5);\n * console.log(randomNum);\n */\nfunction getRandomNumberBetween(min, max) {\n\treturn Math.random() * (max - min) + min;\n}\n\n/**\n * Class to handle modifications to the CSS property `text-decoration-line`.\n */\nclass TextDecorationHandler {\n\t/**\n\t * Creates an instance of TextDecorationHandler.\n\t * @param {string} [initialDecoration=''] - Initial text decoration string.\n\t */\n\tconstructor(initialDecoration = '') {\n\t\tthis.validDecorations = new Set([\n\t\t\t'underline',\n\t\t\t'overline',\n\t\t\t'line-through'\n\t\t]);\n\t\tthis.decorations = new Set(\n\t\t\tinitialDecoration\n\t\t\t\t.split(' ')\n\t\t\t\t.filter(decoration => this.validDecorations.has(decoration))\n\t\t);\n\t}\n\n\t/**\n\t * Toggles the specified decoration.\n\t * @param {string} decoration - The decoration to toggle (e.g., 'underline', 'line-through').\n\t * @return {string|null} - The updated decoration string or null if no decorations are set.\n\t * @throws {Error} - If the decoration is not a valid CSS keyword for text-decoration-line.\n\t */\n\ttoggleDecoration(decoration) {\n\t\tif (!this.validDecorations.has(decoration)) {\n\t\t\tconsole.warn(`Invalid decoration: ${decoration}`);\n\t\t}\n\n\t\tif (this.decorations.has(decoration)) {\n\t\t\tthis.decorations.delete(decoration);\n\t\t} else {\n\t\t\tthis.decorations.add(decoration);\n\t\t}\n\t\treturn this.getDecorationString();\n\t}\n\n\t/**\n\t * Gets the current decoration string.\n\t * @return {string|null} - The current decoration string or null if no decorations are set.\n\t */\n\tgetDecorationString() {\n\t\treturn this.decorations.size > 0\n\t\t\t? Array.from(this.decorations).join(' ')\n\t\t\t: null;\n\t}\n}\n\n/**\n * Extracts all the plain text from an HTML string (without the tags and attributes).\n *\n * @param {string} htmlString - The HTML string to extract text from.\n * @return {string} The plain text extracted from the HTML string.\n */\nfunction extractPlainText(htmlString) {\n\tconst parser = new DOMParser();\n\tconst doc = parser.parseFromString(htmlString, 'text/html');\n\treturn doc.body.textContent || '';\n}\n\n/**\n * Capitalizes the first letter of the given string.\n *\n * @param {string} str - The string to be capitalized.\n * @return {string} The capitalized string.\n */\nfunction capitalize(str) {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nexport {\n\tremoveFirstSubstring,\n\tfunctionHasBody,\n\tsvgToBase64,\n\tdownloadFile,\n\taddCssClass,\n\taddClassesString,\n\ttrimAll,\n\tconvertDataUnit,\n\tgetImageSize,\n\tgetUnit,\n\tobjToArray,\n\tarrayMove,\n\tsplitArrayIntoParts,\n\tarrayRemove,\n\tremoveSpaces,\n\tgetCaretElement,\n\tisElement,\n\thtmlToPlainText,\n\tcamelCase,\n\ttoBoolean,\n\tgetFirstChild,\n\ttemplate,\n\tcreateElement,\n\tshallowString,\n\tpropertiesToArray,\n\tsearchObjectRecursively,\n\tremoveHtmlByTag,\n\tgetElementWidthPercentage,\n\tsetContent,\n\tthrottle,\n\tdebounce,\n\tconvertCornerPropsToCSS,\n\tconvertCssStringToObj,\n\tcopyToClipboard,\n\telementAddEvent,\n\tdeepCompareAndLog,\n\tfindDifferences,\n\tremoveWord,\n\thtmlToElement,\n\tunquoteString,\n\tsanitizeUrl,\n\tvalidateUrl,\n\tgetValidUnit,\n\tisValidValue,\n\tisValidDimension,\n\tisValidUnit,\n\tinsertAfterEveryItem,\n\thasCircularDependency,\n\tmerge,\n\tmergeWith,\n\tisArray,\n\tisObject,\n\tisFunction,\n\tforEach,\n\tisUndefined,\n\tisBoolean,\n\tisString,\n\tcopyAttributes,\n\tisHTML,\n\tgetHTMLTags,\n\tobjToCSSVariables,\n\tallEqual,\n\tmapObject,\n\tisValidColor,\n\tarrayUnshift,\n\tendsWith,\n\tcssSidesToObject,\n\tcssCornersToObject,\n\tarrayAvg,\n\tavg,\n\tcssStyleObjectToString,\n\tparseStyleString,\n\tdeleteProps,\n\tsetNodeStyle,\n\tmax,\n\toutlookConditionalRenderComment,\n\tisComment,\n\tcompareVersions,\n\tremoveSingleQuotes,\n\tcssStyleDeclarationToObject,\n\tgetRandomNumberBetween,\n\tEventEmitter,\n\tdataUnits,\n\tCssUnits,\n\tborderStyles,\n\tgenericFonts,\n\twebSafeFonts,\n\twindowsFonts,\n\twebFonts,\n\tcssFontWeights,\n\tshowEl,\n\thideEl,\n\trenderMsoConditional,\n\trenderNotMsoConditional,\n\tTextDecorationHandler,\n\textractPlainText,\n\tcapitalize\n};\n","import { get } from 'lodash-es';\nimport { merge } from 'datatalks-utils';\n\n/**\n * TranslationFramework class to manage multiple languages and translations.\n */\nexport default class TranslationFramework {\n\t/**\n\t * Creates an instance of TranslationFramework.\n\t * @param {Object} [options={}] - The options for the TranslationFramework.\n\t * @param {string} [options.defaultKey='terms'] - The default key for translations.\n\t * @param {string} [options.fallbackLanguage='en-US'] - The language to use as a fallback.\n\t * @param {string} [options.currentLanguage=null] - The current language to use for translations.\n\t * @param {Object} [options.languages={}] - An object containing key-value pairs of languages and translations.\n\t */\n\tconstructor(options = {}) {\n\t\tconst defaults = {\n\t\t\tdefaultKey: 'terms',\n\t\t\tfallbackLanguage: 'en-US',\n\t\t\tcurrentLanguage: null,\n\t\t\tlanguages: {},\n\t\t\tonKeyNotFound: null\n\t\t};\n\n\t\tthis.options = merge(defaults, options);\n\t\tthis.languages = this.options.languages;\n\t\tthis.currentLanguage = this.options.currentLanguage;\n\t\tthis.fallbackLanguage = this.options.fallbackLanguage;\n\t}\n\n\t/**\n\t * Adds new options to the existing options by merging them.\n\t *\n\t * @param {Object} options - The new options to be added.\n\t */\n\taddOptions(options) {\n\t\tthis.options = merge(this.options, options);\n\t}\n\n\t/**\n\t * Registers a language with its translations.\n\t * @param {string} languageCode - The code of the language to register (e.g., 'en', 'es').\n\t * @param {Object} [translations={}] - An object containing key-value pairs of translations.\n\t */\n\tregisterLanguage(languageCode, translations = {}) {\n\t\tthis.languages[languageCode] = translations;\n\t\tthis.languages[languageCode].unregistered = new Set();\n\t}\n\n\t/**\n\t * Sets the current language for translations.\n\t * @param {string} languageCode - The code of the language to set as current.\n\t */\n\tsetLanguage(languageCode) {\n\t\tif (this.languages[languageCode]) {\n\t\t\tthis.currentLanguage = languageCode;\n\t\t} else {\n\t\t\tconsole.warn(`Language ${languageCode} is not registered.`);\n\t\t}\n\t}\n\n\t/**\n\t * Adds a translation for a specific key in a given language.\n\t * @param {Object} options - The options for the translation.\n\t * @param {string} options.languageCode - The code of the language to add the translation to.\n\t * @param {string} options.key - The key for the translation.\n\t * @param {string} options.translation - The translation text.\n\t */\n\taddTranslation({ languageCode, key, translation }) {\n\t\tif (!translation) {\n\t\t\tconsole.warn(`No translation provided for the '${key}' key.`);\n\t\t\treturn;\n\t\t}\n\t\tlanguageCode =\n\t\t\tlanguageCode || this.currentLanguage || this.fallbackLanguage;\n\t\tkey = key || this.options.defaultKey || 'terms';\n\t\tif (!this.languages[languageCode]) {\n\t\t\tthis.languages[languageCode] = {};\n\t\t}\n\t\tthis.languages[languageCode][key] = translation;\n\t}\n\n\t/**\n\t * Gets the translation for a specific key in the current language.\n\t * @param {string} key - The key for the translation.\n\t * @return {string} - The translation text or a message if not found.\n\t * @param {boolean} [nullable=false] - Whether to return null or the key if the translation is not found.\n\t */\n\tgetTranslation(key, nullable = false) {\n\t\tif (this.currentLanguage && this.languages[this.currentLanguage]) {\n\t\t\tconst translation =\n\t\t\t\tthis.languages[this.currentLanguage][key] ||\n\t\t\t\tget(this.languages[this.currentLanguage], key) ||\n\t\t\t\tget(this.languages[this.currentLanguage].terms, key);\n\t\t\tif (translation) {\n\t\t\t\treturn translation;\n\t\t\t} else {\n\t\t\t\tthis.notifyUnregistered(key);\n\t\t\t\treturn (\n\t\t\t\t\tthis.languages[this.fallbackLanguage][key] ||\n\t\t\t\t\tget(this.languages[this.fallbackLanguage], key) ||\n\t\t\t\t\tget(this.languages[this.fallbackLanguage].terms, key) ||\n\t\t\t\t\t(nullable ? null : key)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn `No language set or translation for ${key} not found.`;\n\t}\n\n\t/**\n\t * Notifies that a translation key is unregistered for the current\n\t * language and stores it in the TranslationFramework instance.\n\t *\n\t * @param {string} key - The translation key that is unregistered.\n\t */\n\tnotifyUnregistered(key) {\n\t\tthis.languages[this.currentLanguage].unregistered.add(key);\n\t\tif (typeof this.options.onKeyNotFound === 'function') {\n\t\t\tthis.options.onKeyNotFound(this.currentLanguage, key);\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the specified language code exists in the languages object.\n\t *\n\t * @param {string} languageCode - The code of the language to check.\n\t * @return {boolean} - Returns true if the language exists, otherwise false.\n\t */\n\thasLanguage(languageCode) {\n\t\treturn !!this.languages[languageCode];\n\t}\n\n\t/**\n\t * Loads multiple translations for a specific language.\n\t * @param {string} languageCode - The code of the language to load translations for.\n\t * @param {Object} translations - An object containing key-value pairs of translations.\n\t */\n\tloadTranslations(languageCode, translations) {\n\t\tif (!this.languages[languageCode]) {\n\t\t\tthis.languages[languageCode] = {};\n\t\t}\n\t\tObject.assign(this.languages[languageCode], translations);\n\t}\n}\n","import { deleteProps, merge } from 'datatalks-utils';\n\n/**\n * Validates a style object by removing any properties with null values.\n * @param {Object} style - The style object to validate.\n * @return {Object} - The validated style object.\n */\nexport function validateStyleObj(style) {\n\tvar result = {};\n\tfor (var prop in style) {\n\t\tif (style[prop] != null) {\n\t\t\tresult[prop] = style[prop];\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Validates the border properties of a style object. If the border properties would make it invisible,\n * they are removed and `border:none` is set.\n * @param {Object} styleObject - The style object to validate.\n * @param {boolean} [mutate=false] - Indicates whether to mutate the style object or not.\n * @return {Object} - The updated style object if mutate is true, otherwise a copy of it.\n */\nexport function validateBorder(styleObject, mutate = false) {\n\tif (\n\t\t(styleObject['border-width'] &&\n\t\t\tparseFloat(styleObject['border-width']) < 0.1) ||\n\t\tstyleObject['border-color'] === 'transparent' ||\n\t\tstyleObject['border-style'] === 'none' ||\n\t\tstyleObject['border-style'] === 'hidden'\n\t) {\n\t\tif (mutate) {\n\t\t\tdeleteProps(\n\t\t\t\tstyleObject,\n\t\t\t\t['border-width', 'border-color', 'border-style'],\n\t\t\t\tmutate\n\t\t\t);\n\t\t\tstyleObject.border = 'none';\n\t\t\treturn styleObject;\n\t\t} else {\n\t\t\treturn deleteProps(\n\t\t\t\tstyleObject,\n\t\t\t\t['border-width', 'border-color', 'border-style'],\n\t\t\t\tmutate\n\t\t\t);\n\t\t}\n\t}\n\n\treturn mutate ? styleObject : merge({}, styleObject);\n}\n\nexport default {\n\tvalidateStyleObj,\n\tvalidateBorder\n};\n","import { merge } from 'datatalks-utils';\nimport { validateStyleObj } from '../common/functions/_utilFunctions';\n\n/* eslint-disable require-jsdoc */\nexport const noInteractionPreset = {\n\teditable: false,\n\tselectable: false,\n\thoverable: false,\n\tlayerable: false,\n\tdraggable: false,\n\thighlightable: false,\n\tlocked: true,\n\tdroppable: true,\n\tpropagate: [\n\t\t'editable',\n\t\t'selectable',\n\t\t'hoverable',\n\t\t'layerable',\n\t\t'draggable',\n\t\t'highlightable',\n\t\t'locked',\n\t\t'droppable'\n\t]\n};\n\nexport function addSpace(\n\tcomponent,\n\tisVertical = true,\n\tinnerComponentsArray,\n\tcomponentProperty = 'spacingBetweenElements'\n) {\n\tconst spaceComp = {\n\t\ttype: 'space',\n\t\tdimension: component.get(componentProperty || 'spacingBetweenElements'),\n\t\tisVertical: isVertical\n\t};\n\tif (Array.isArray(innerComponentsArray)) {\n\t\tinnerComponentsArray.push(spaceComp);\n\t} else {\n\t\tcomponent.append(spaceComp);\n\t}\n}\n","export const COMPONENTS_DEFAULTS = {\n\tremovable: true,\n\tdraggable: true,\n\tdroppable: false,\n\tbadgable: true,\n\thighlightable: true,\n\tcopyable: true,\n\tresizable: false,\n\teditable: false,\n\tlayerable: true,\n\tselectable: true,\n\thoverable: true,\n\tlocked: false\n};\n","import { noInteractionPreset } from '../_componentsUtils';\nimport { insertAfterEveryItem } from 'datatalks-utils';\nimport { validateStyleObj } from '../../common/functions/_utilFunctions';\n\n/**\n * Returns a component with a table structure with margin-cells all around the main content.\n * @param {Object} comp - The parent component to read the properties from.\n * @param {string} name - The name of the element.\n * @param {Object|string} inner - The inner content of the element.\n * @param {boolean} [innerIsComponent=false] - Indicates if the inner content is a component.\n * @param {string} [componentWidth='auto'] - The width of the component.\n * @return {Object} - The component with margins.\n */\nfunction element(\n\tcomp,\n\tname,\n\tinner,\n\tinnerIsComponent = false,\n\tcomponentWidth = 'auto'\n) {\n\treturn [\n\t\t{\n\t\t\ttype: 'margins',\n\t\t\tinnerComponents: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'row',\n\t\t\t\t\tcomponents: {\n\t\t\t\t\t\ttype: 'cell',\n\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\talign: comp.get(`${name}Alignment`)\n\t\t\t\t\t\t},\n\t\t\t\t\t\t[innerIsComponent ? 'components' : 'content']: inner\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\twrapInTable: true,\n\t\t\twidth: componentWidth,\n\t\t\thasMargins: comp.get(`${name}HasMargins`),\n\t\t\tmargins: {\n\t\t\t\ttop: comp.get(`${name}TopMargin`),\n\t\t\t\tright: comp.get(`${name}RightMargin`),\n\t\t\t\tbottom: comp.get(`${name}BottomMargin`),\n\t\t\t\tleft: comp.get(`${name}LeftMargin`)\n\t\t\t},\n\t\t\tmarginsColor: {\n\t\t\t\ttop: comp.get(`${name}TopMarginColor`),\n\t\t\t\tright: comp.get(`${name}RightMarginColor`),\n\t\t\t\tbottom: comp.get(`${name}BottomMarginColor`),\n\t\t\t\tleft: comp.get(`${name}LeftMarginColor`)\n\t\t\t}\n\t\t}\n\t];\n}\n\nexport default comp => {\n\tconst components = [];\n\tlet contentComponents = [];\n\n\tlet image = {\n\t\ttype: 'image-wrapper',\n\t\timgSrc: comp.attributes.imgSrc,\n\t\thref: comp.get('imageHref'),\n\t\thasLink: comp.get('imageHasLink'),\n\t\tstyle: validateStyleObj({\n\t\t\twidth: comp.get('imgWidth'),\n\t\t\t'border-radius': comp.get('imageUseBorderRadius')\n\t\t\t\t? Object.values(comp.get('imageBorderRadius')).join(' ')\n\t\t\t\t: null\n\t\t})\n\t};\n\n\timage = element(comp, 'image', image, true, 'auto');\n\n\tif (comp.get('displayTitle')) {\n\t\tcontentComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tcomponents: element(\n\t\t\t\t\tcomp,\n\t\t\t\t\t'title',\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: comp.attributes.title\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t\t'100%'\n\t\t\t\t)\n\t\t\t}\n\t\t});\n\t}\n\n\tif (comp.get('displayDescription')) {\n\t\tcontentComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tcomponents: element(\n\t\t\t\t\tcomp,\n\t\t\t\t\t'description',\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: comp.attributes.description\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t\t'100%'\n\t\t\t\t)\n\t\t\t}\n\t\t});\n\t}\n\n\tif (comp.get('displayButton')) {\n\t\tcontentComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tcomponents: element(\n\t\t\t\t\tcomp,\n\t\t\t\t\t'button',\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\ttext: comp.attributes.buttonText,\n\t\t\t\t\t\tbackgroundColor: comp.get('buttonBackgroundColor'),\n\t\t\t\t\t\theight: comp.get('buttonHeight'),\n\t\t\t\t\t\twidth: comp.get('buttonWidth'),\n\t\t\t\t\t\tfontFamily: comp.get('buttonFontFamily'),\n\t\t\t\t\t\tfontSize: comp.get('buttonFontSize'),\n\t\t\t\t\t\tfontStyle: comp.get('buttonFontStyle'),\n\t\t\t\t\t\tcolor: comp.get('buttonColor'),\n\t\t\t\t\t\tfontWeight: comp.get('buttonFontWeight'),\n\t\t\t\t\t\tborderWidth: comp.get('buttonBorderWidth'),\n\t\t\t\t\t\tborderStyle: comp.get('buttonBorderStyle'),\n\t\t\t\t\t\tborderColor: comp.get('buttonBorderColor'),\n\t\t\t\t\t\tborderRadius: comp.get('buttonBorderRadius'),\n\t\t\t\t\t\tuseBorderRadius: comp.get('buttonUseBorderRadius'),\n\t\t\t\t\t\tlineHeight: comp.get('buttonLineHeight'),\n\t\t\t\t\t\thref: comp.get('buttonHref'),\n\t\t\t\t\t\threfState: comp.get('buttonHrefState'),\n\t\t\t\t\t\ttextAlignment: comp.get('buttonTextAlignment'),\n\t\t\t\t\t\talignment: comp.get('buttonAlignment'),\n\t\t\t\t\t\ttextDecorationLine: comp.get('buttonTextDecorationLine')\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t\t'100%'\n\t\t\t\t)\n\t\t\t}\n\t\t});\n\t}\n\n\tcontentComponents = insertAfterEveryItem(contentComponents, {\n\t\ttype: 'space',\n\t\tisVertical: true,\n\t\tdimension: comp.get('verticalSpacingBetweenElements')\n\t});\n\n\tif (contentComponents.length) {\n\t\tif (\n\t\t\t['left', 'right'].includes(comp.get('imagePlacement')) &&\n\t\t\tcomp.get('displayImage')\n\t\t) {\n\t\t\tconst innerComponents = [\n\t\t\t\t{\n\t\t\t\t\ttype: 'cell',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\talign: comp.get('imageAlignment')\n\t\t\t\t\t},\n\t\t\t\t\tstyle: validateStyleObj({\n\t\t\t\t\t\twidth: `${comp.get('imageContentRatio') * 100}%`,\n\t\t\t\t\t\t'vertical-align':\n\t\t\t\t\t\t\tcomp.get('imageVAlignment') ||\n\t\t\t\t\t\t\tcomp.get('contentVAlignment')\n\t\t\t\t\t}),\n\t\t\t\t\tcomponents: image\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'space',\n\t\t\t\t\tisVertical: false,\n\t\t\t\t\tdimension: comp.get('horizontalSpacingBetweenElements')\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'cell',\n\t\t\t\t\tcomponents: {\n\t\t\t\t\t\ttype: 'table',\n\t\t\t\t\t\tcomponents: contentComponents,\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\twidth: '100%'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tstyle: validateStyleObj({\n\t\t\t\t\t\twidth: `${(1 - comp.get('imageContentRatio')) * 100}%`,\n\t\t\t\t\t\t'vertical-align':\n\t\t\t\t\t\t\tcomp.get('contentVAlignment') ||\n\t\t\t\t\t\t\tcomp.get('imageVAlignment')\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t];\n\t\t\tcomponents.push({\n\t\t\t\ttype: 'row',\n\t\t\t\tcomponents:\n\t\t\t\t\tcomp.get('imagePlacement') === 'right'\n\t\t\t\t\t\t? innerComponents.reverse()\n\t\t\t\t\t\t: innerComponents\n\t\t\t});\n\t\t} else {\n\t\t\tif (comp.get('displayImage'))\n\t\t\t\tcomponents.push(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'row',\n\t\t\t\t\t\tcomponents: {\n\t\t\t\t\t\t\ttype: 'cell',\n\t\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\t\talign: comp.get('imageAlignment')\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tcomponents: image\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'space',\n\t\t\t\t\t\tisVertical: true,\n\t\t\t\t\t\tdimension: comp.get('verticalSpacingBetweenElements')\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\tcomponents.push(...contentComponents);\n\t\t}\n\t} else {\n\t\tif (comp.get('displayImage'))\n\t\t\tcomponents.push({\n\t\t\t\ttype: 'row',\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'cell',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\talign: comp.get('imageAlignment')\n\t\t\t\t\t},\n\t\t\t\t\tcomponents: image\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tcomp.set(\n\t\t'style',\n\t\tvalidateStyleObj({\n\t\t\t...comp.getStyle(),\n\t\t\twidth: comp.attributes.width,\n\t\t\t['background-color']: comp.attributes.backgroundColor\n\t\t})\n\t);\n\n\treturn {\n\t\ttype: 'tbody',\n\t\tstyle: {\n\t\t\t'text-align': comp.attributes.textAlign\n\t\t},\n\t\t...noInteractionPreset,\n\t\tcomponents\n\t};\n};\n","export default {\n\tattributes: {},\n\tbackgroundColor: null,\n\tcssClass: 'gjs-comp-list-item',\n\timgSrc: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIHZpZXdCb3g9IjAgMCAyNCAyNCIgc3R5bGU9ImZpbGw6IHJnYmEoMCwwLDAsMC4xNSk7IHRyYW5zZm9ybTogc2NhbGUoMC43NSkiPgogICAgICAgIDxwYXRoIGQ9Ik04LjUgMTMuNWwyLjUgMyAzLjUtNC41IDQuNSA2SDVtMTYgMVY1YTIgMiAwIDAgMC0yLTJINWMtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxNGMxLjEgMCAyLS45IDItMnoiPjwvcGF0aD4KICAgICAgPC9zdmc+',\n\ttitle: '

Heading

',\n\talign: 'center',\n\tvAlign: 'middle',\n\ttextAlign: 'left',\n\tdescription: '

This is a placeholder for the description of the item

',\n\tbuttonText: 'Call to action',\n\timagePlacement: 'left',\n\timgWidth: '100%',\n\timageHasLink: false,\n\timageHref: null,\n\timageBorderRadius: {\n\t\ttopLeft: '0px',\n\t\ttopRight: '0px',\n\t\tbottomRight: '0px',\n\t\tbottomLeft: '0px'\n\t},\n\timageUseBorderRadius: false,\n\timageAlignment: 'left',\n\timageLeftMargin: '0px',\n\timageRightMargin: '0px',\n\timageTopMargin: '0px',\n\timageBottomMargin: '0px',\n\timageHasMargins: true,\n\twidth: '100%',\n\tname: 'List Item',\n\tdisplayImage: true,\n\tdisplayTitle: true,\n\ttitleLeftMargin: '0px',\n\ttitleRightMargin: '0px',\n\ttitleTopMargin: '0px',\n\ttitleBottomMargin: '0px',\n\ttitleHasMargins: true,\n\tdisplayDescription: true,\n\tdescriptionLeftMargin: '0px',\n\tdescriptionRightMargin: '0px',\n\tdescriptionTopMargin: '0px',\n\tdescriptionBottomMargin: '0px',\n\tdescriptionHasMargins: true,\n\tdisplayButton: true,\n\tbuttonPh: 'Button text',\n\tbuttonBackgroundColor: null,\n\tbuttonHeight: null,\n\tbuttonWidth: '100%',\n\tbuttonFontFamily: null,\n\tbuttonFontSize: null,\n\tbuttonFontStyle: 'normal',\n\tbuttonColor: null,\n\tbuttonFontWeight: null,\n\tbuttonBorderWidth: '0px',\n\tbuttonBorderStyle: 'solid',\n\tbuttonBorderColor: 'transparent',\n\tbuttonAlignment: 'center',\n\tbuttonTextAlignment: 'center',\n\tbuttonBorderRadius: {\n\t\ttopLeft: '0px',\n\t\ttopRight: '0px',\n\t\tbottomRight: '0px',\n\t\tbottomLeft: '0px'\n\t},\n\tbuttonLineHeight: null,\n\tbuttonUseBorderRadius: false,\n\tbuttonLetterSpacing: 'normal',\n\tbuttonNormalLetterSpacing: true,\n\tbuttonDefaultLetterSpacingLength: '0.1em',\n\tbuttonLeftMargin: '0px',\n\tbuttonRightMargin: '0px',\n\tbuttonTopMargin: '0px',\n\tbuttonBottomMargin: '0px',\n\tbuttonHasMargins: true,\n\tbuttonTextDecorationLine: null,\n\tverticalSpacingBetweenElements: '8px',\n\thorizontalSpacingBetweenElements: '16px',\n\timageContentRatio: 0.5,\n\ttoHtmlOptions: {},\n\timageVAlignment: 'middle',\n\tcontentVAlignment: 'middle'\n};\n","export default {\n\tattributes: {},\n\tcssClass: 'button',\n\talignment: 'center',\n\tletterSpacing: 'normal',\n\ttagName: 'button',\n\ttext: 'Button',\n\tname: 'Button',\n\tbackgroundColor: null,\n\theight: null,\n\twidth: '100%',\n\tcolor: null,\n\tfontFamily: null,\n\tfontSize: null,\n\tfontWeight: null,\n\tfontStyle: 'normal',\n\tborderWidth: '0px',\n\tborderStyle: 'solid',\n\tborderColor: 'transparent',\n\tborderRadius: {\n\t\ttopLeft: '0px',\n\t\ttopRight: '0px',\n\t\tbottomRight: '0px',\n\t\tbottomLeft: '0px'\n\t},\n\tuseBorderRadius: false,\n\ttextAlignment: 'center',\n\ttoHtmlOptions: {},\n\thref: null,\n\threfState: null,\n\tlineHeight: null,\n\thasOutlookBorderRadius: false,\n\toutlookWidth: '150px',\n\ttextDecorationLine: null\n};\n","const svgAttrs =\n\t'xmlns=\"http://www.w3.org/2000/svg\" width=\"100\" viewBox=\"0 0 24 24\" style=\"fill: rgba(0,0,0,0.15); transform: scale(0.75)\"';\n\nexport default {\n\talternateText: '',\n\tattributes: {},\n\tcssClass: 'gjs-comp-img',\n\tbackgroundColor: null,\n\timgWidth: '100%',\n\timgSrc: null,\n\tsrc: null,\n\tfallback: `\n\t\n `,\n\tname: 'image-wrapper',\n\timgName: 'Image placeholder',\n\ttagName: 'img',\n\tborderWidth: '0px',\n\tborderStyle: 'solid',\n\tborderColor: 'transparent',\n\tborderRadius: {\n\t\ttopLeft: '0px',\n\t\ttopRight: '0px',\n\t\tbottomRight: '0px',\n\t\tbottomLeft: '0px'\n\t},\n\tuseBorderRadius: true,\n\talignment: 'center',\n\thasLink: false,\n\thref: null,\n\ttoHtmlOptions: {}\n};\n","export default {\n\tattributes: {},\n\tcssClass: 'gjs-comp-link-list',\n\tlinksAlignment: 'center',\n\tlinksList: [\n\t\t{\n\t\t\tcontent: 'Title 1',\n\t\t\thref: 'http://www.title1.com',\n\t\t\ttarget: '_blank'\n\t\t},\n\t\t{\n\t\t\tcontent: 'Title',\n\t\t\thref: 'http://www.title2.com',\n\t\t\ttarget: '_blank'\n\t\t},\n\t\t{\n\t\t\tcontent: 'Title',\n\t\t\thref: 'http://www.title3.com',\n\t\t\ttarget: '_blank'\n\t\t}\n\t],\n\tlinksColor: null,\n\tlinksBackground: 'transparent',\n\tlinksFont: null,\n\tlinksWeight: 'normal',\n\tlinksHasMargins: false,\n\tlinksLeftMargin: '0px',\n\tlinksRightMargin: '0px',\n\tlinksTopMargin: '0px',\n\tlinksBottomMargin: '0px',\n\tlinksLetterSpacing: 'auto',\n\tgap: '20px',\n\tlistWidth: '100%',\n\tlistAlign: 'center',\n\ttagName: 'table',\n\tname: 'Links List',\n\tisTextList: false,\n\ttoHtmlOptions: {},\n\tisWrapable: true\n};\n","export default {\n\tattributes: {},\n\tcssClass: 'gjs-comp-text',\n\tletterSpacing: 'normal',\n\ttagName: 'p',\n\ttext: 'This is a text box',\n\tname: 'Text',\n\ttextAlign: 'left',\n\tbackgroundColor: 'transparent',\n\twidth: '100%',\n\talignment: 'center',\n\tfontFamily: null,\n\tcolor: null,\n\tfontWeight: null,\n\tborderWidth: '0px',\n\tborderStyle: 'solid',\n\tborderColor: 'transparent',\n\ttoHtmlOptions: {},\n\tuseBorderRadius: true,\n\tborderRadius: {\n\t\ttopLeft: '0px',\n\t\ttopRight: '0px',\n\t\tbottomRight: '0px',\n\t\tbottomLeft: '0px'\n\t}\n};\n","export default {\n\tcolor: 'transparent',\n\tbackgroundColor: 'transparent',\n\tdimension: '16px',\n\tcssClass: 'gjs-comp-space',\n\tisVertical: true,\n\tname: 'space',\n\ttagName: 'tr',\n\ttoHtmlOptions: {}\n};\n","export default {\n\ttagName: 'tr',\n\tcssClass: 'gjs-comp-margins',\n\tname: 'Component Margins',\n\tbackgroundColor: null,\n\tinnerComponents: [],\n\tinnerRenderType: null,\n\thasMargins: false,\n\tmargins: {\n\t\tleft: '0px',\n\t\tright: '0px',\n\t\ttop: '0px',\n\t\tbottom: '0px'\n\t},\n\tmarginsColor: {\n\t\tleft: 'transparent',\n\t\tright: 'transparent',\n\t\ttop: 'transparent',\n\t\tbottom: 'transparent'\n\t},\n\twrapInTable: false,\n\twidth: '100%',\n\ttoHtmlOptions: {}\n};\n","export default {\n\thasMargins: true,\n\tbackgroundColor: null,\n\tspacingBetweenElements: '12px',\n\tleftMargin: '15px',\n\trightMargin: '15px',\n\ttopMargin: '15px',\n\tbottomMargin: '15px',\n\tleftMarginColor: 'transparent',\n\trightMarginColor: 'transparent',\n\ttopMarginColor: 'transparent',\n\tbottomMarginColor: 'transparent',\n\tborderWidth: null,\n\tborderStyle: null,\n\tborderColor: null,\n\tborderRadius: {\n\t\ttopLeft: '0px',\n\t\ttopRight: '0px',\n\t\tbottomLeft: '0px',\n\t\tbottomRight: '0px'\n\t},\n\tuseBorderRadius: false\n};\n","/* eslint-disable require-jsdoc */\nimport { camelCase } from 'lodash-es';\nimport listItem from './_listItemDefaults';\nimport button from './_button';\nimport imageWrapper from './_imageWrapper';\nimport linksList from './_linksList';\nimport text from './_text';\nimport space from './_space';\nimport margins from './_margins';\nimport common from './_common';\n\nconst componentsDefaults = {\n\tlistItem,\n\tbutton,\n\timageWrapper,\n\tlinksList,\n\ttext,\n\tspace,\n\tmargins,\n\tcommon\n};\n\nexport function getComponentsDefaultsByType(type = 'common') {\n\treturn componentsDefaults[camelCase(type)];\n}\n\nexport default componentsDefaults;\n","import { debounce } from 'lodash-es';\nimport { merge } from 'datatalks-utils';\n\nexport default (componentOptions = {}, editor) => {\n\tconst debouncedRender = debounce(comp => {\n\t\tcomp.components(comp.componentRender(comp));\n\t}, editor.getEmailBuilder().getOptions().renderingDebounceTime);\n\n\treturn {\n\t\tgetEditor() {\n\t\t\treturn editor;\n\t\t},\n\n\t\tsetAndRerender(prop, value) {\n\t\t\t// TODO: create a class `ComponentEvent` to structure and standardize its methods and props\n\t\t\tconst ev = {\n\t\t\t\tstopPropagation: false\n\t\t\t};\n\t\t\tconst comp = this;\n\t\t\tcomp.set(prop, value);\n\t\t\tcomp.trigger(`change:attributes:${prop}`, { ev });\n\t\t\tif (ev.preventDefault) return;\n\t\t\tdebouncedRender(comp);\n\t\t},\n\n\t\tfindTypes(types) {\n\t\t\tconst comp = this;\n\t\t\tlet children = [];\n\t\t\ttypes.forEach(type => {\n\t\t\t\tchildren = children.concat(comp.findType(type));\n\t\t\t});\n\t\t\treturn children;\n\t\t},\n\n\t\trootComponentInitialized(options) {\n\t\t\tconst comp = this;\n\t\t\tconst defaults = {\n\t\t\t\trunInitMethod: false\n\t\t\t};\n\n\t\t\toptions = merge(defaults, options);\n\n\t\t\tif (options.runInitMethod) {\n\t\t\t\tcomp.init();\n\t\t\t}\n\n\t\t\tif (typeof comp.onRootComponentInitialized === 'function') {\n\t\t\t\tcomp.onRootComponentInitialized();\n\t\t\t}\n\t\t},\n\n\t\tlocalize(key, nullable = false) {\n\t\t\treturn editor\n\t\t\t\t.getEmailBuilder()\n\t\t\t\t.translationFramework.getTranslation(key, nullable);\n\t\t}\n\t};\n};\n","import {\n\tmerge,\n\tcssStyleObjectToString,\n\tisValidDimension\n} from 'datatalks-utils';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tparentWidth: null,\n\t\tisMobileOptimized: false\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst isMobileOptimized =\n\t\toptions.isMobileOptimized || typeof comp.getEditor === 'function'\n\t\t\t? comp\n\t\t\t\t\t.getEditor()\n\t\t\t\t\t.getEmailBuilder()\n\t\t\t\t\t.getAdvancedOption('isMobileOptimized')\n\t\t\t: false;\n\n\tconst align = comp.get('align') || 'center';\n\tconst imagePlacement = comp.get('imagePlacement');\n\tconst vAlign = comp.get('vAlign');\n\n\tconst imageSideRatio = comp.get('imageContentRatio');\n\n\tconst msoImageColWidth =\n\t\timagePlacement == 'top'\n\t\t\t? options.parentWidth\n\t\t\t: parseFloat(options.parentWidth) * imageSideRatio -\n\t\t\t parseFloat(comp.get('horizontalSpacingBetweenElements')) / 2 +\n\t\t\t 'px';\n\tconst msoSecondColWidth =\n\t\timagePlacement == 'top'\n\t\t\t? options.parentWidth\n\t\t\t: parseFloat(options.parentWidth) * (1 - imageSideRatio) -\n\t\t\t parseFloat(comp.get('horizontalSpacingBetweenElements')) / 2 +\n\t\t\t 'px';\n\n\t/**\n\t * Calculates the width of the image based on the parent width and other components margins.\n\t * @param {boolean} imageTop - Indicates whether the layout is with image on top.\n\t * @return {number} The calculated width of the image.\n\t */\n\tfunction getImageWidth(imageTop) {\n\t\tif (imageTop) {\n\t\t\treturn (\n\t\t\t\tparseFloat(options.parentWidth) -\n\t\t\t\tparseFloat(comp.get('imageLeftMargin')) -\n\t\t\t\tparseFloat(comp.get('imageRightMargin'))\n\t\t\t);\n\n\t\t\t// return parseFloat(options.parentWidth);\n\t\t} else {\n\t\t\t// return (\n\t\t\t// \t(parseFloat(options.parentWidth) -\n\t\t\t// \t\tparseFloat(comp.get('imageLeftMargin')) -\n\t\t\t// \t\tparseFloat(comp.get('imageRightMargin')) -\n\t\t\t// \t\tparseFloat(comp.get('horizontalSpacingBetweenElements')) /\n\t\t\t// \t\t\t2 -\n\t\t\t// \t\tmax(\n\t\t\t// \t\t\tparseFloat(comp.get('titleLeftMargin')) +\n\t\t\t// \t\t\t\tparseFloat(comp.get('titleRightMargin')),\n\t\t\t// \t\t\tparseFloat(comp.get('descriptionLeftMargin')) +\n\t\t\t// \t\t\t\tparseFloat(comp.get('descriptionRightMargin')),\n\t\t\t// \t\t\tparseFloat(comp.get('buttonLeftMargin')) +\n\t\t\t// \t\t\t\tparseFloat(comp.get('buttonRightMargin'))\n\t\t\t// \t\t)) *\n\t\t\t// \timageSideRatio\n\t\t\t// );\n\n\t\t\treturn (\n\t\t\t\t(parseFloat(options.parentWidth) -\n\t\t\t\t\tparseFloat(comp.get('horizontalSpacingBetweenElements')) /\n\t\t\t\t\t\t2 -\n\t\t\t\t\tparseFloat(comp.get('imageLeftMargin')) -\n\t\t\t\t\tparseFloat(comp.get('imageRightMargin'))) *\n\t\t\t\timageSideRatio\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Calculates the width of an element (button, title, description)\n\t * based on the layout (top view or side view).\n\t *\n\t * @param {string} elementName - The name of the element.\n\t * @param {boolean} imageTop - Indicates whether the layout is the image on top.\n\t * @return {number} The calculated width of the element.\n\t */\n\tfunction getElementWidth(elementName, imageTop) {\n\t\tif (imageTop) {\n\t\t\treturn (\n\t\t\t\tparseFloat(options.parentWidth) -\n\t\t\t\tparseFloat(comp.get(`${elementName}LeftMargin`)) -\n\t\t\t\tparseFloat(comp.get(`${elementName}RightMargin`))\n\t\t\t);\n\n\t\t\t// return parseFloat(options.parentWidth);\n\t\t} else {\n\t\t\t// return (\n\t\t\t// \t(parseFloat(options.parentWidth) -\n\t\t\t// \t\tparseFloat(comp.get('imageLeftMargin')) -\n\t\t\t// \t\tparseFloat(comp.get('imageRightMargin')) -\n\t\t\t// \t\tparseFloat(comp.get('horizontalSpacingBetweenElements')) /\n\t\t\t// \t\t\t2 -\n\t\t\t// \t\tparseFloat(comp.get(`${elementName}LeftMargin`)) -\n\t\t\t// \t\tparseFloat(comp.get(`${elementName}RightMargin`))) *\n\t\t\t// \t(1 - imageSideRatio)\n\t\t\t// );\n\n\t\t\treturn (\n\t\t\t\t(parseFloat(options.parentWidth) -\n\t\t\t\t\tparseFloat(comp.get('horizontalSpacingBetweenElements')) /\n\t\t\t\t\t\t2 -\n\t\t\t\t\tparseFloat(comp.get(`${elementName}LeftMargin`)) -\n\t\t\t\t\tparseFloat(comp.get(`${elementName}RightMargin`))) *\n\t\t\t\t(1 - imageSideRatio)\n\t\t\t);\n\t\t}\n\t}\n\n\tconst prettifyHorizontalSpace =\n\t\tisMobileOptimized &&\n\t\tisValidDimension(comp.get('horizontalSpacingBetweenElements'))\n\t\t\t? parseFloat(comp.get('horizontalSpacingBetweenElements')) / 2\n\t\t\t: 0;\n\tconst prettifyVerticalSpace =\n\t\tisMobileOptimized &&\n\t\tisValidDimension(comp.get('verticalSpacingBetweenElements'))\n\t\t\t? parseFloat(comp.get('verticalSpacingBetweenElements')) / 2\n\t\t\t: 0;\n\n\tconst direction = imagePlacement == 'right' ? 'rtl' : 'ltr';\n\tconst imageStyle = {\n\t\t'padding-left':\n\t\t\tparseFloat(comp.get(`imageLeftMargin`)) +\n\t\t\tprettifyHorizontalSpace +\n\t\t\t'px',\n\t\t'padding-right':\n\t\t\tparseFloat(comp.get(`imageRightMargin`)) +\n\t\t\tprettifyHorizontalSpace +\n\t\t\t'px',\n\t\t'padding-top':\n\t\t\tparseFloat(comp.get(`imageTopMargin`)) +\n\t\t\tprettifyVerticalSpace +\n\t\t\t'px',\n\t\t'padding-bottom':\n\t\t\tparseFloat(comp.get(`imageBottomMargin`)) +\n\t\t\tprettifyVerticalSpace +\n\t\t\t'px'\n\t};\n\n\tconst imageVAlign =\n\t\tcomp.get('imageVAlignment') || comp.get('contentVAlignment') || vAlign;\n\n\tconst column1 = comp.get('displayImage')\n\t\t? `\n\t\t\n\t\t\t
500\n\t\t\t\t\t\t\t\t? 'cover-'\n\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t }${Math.floor(imageSideRatio * 10) * 10}`\n\t\t\t\t\t: ''\n\t\t\t}\" style=\"width:100%;max-width:${msoImageColWidth};display:inline-block;vertical-align:${imageVAlign};direction:ltr;\">\n\t\t\t\t
\n\t\t\t\t\t

\n\t\t\t\t\t\t${comp.findType('image-wrapper')[0].toHTML({\n\t\t\t\t\t\t\tparentWidth: getImageWidth(imagePlacement == 'top'),\n\t\t\t\t\t\t\tstyle: { width: '100%' }\n\t\t\t\t\t\t})}\n\t\t\t\t\t

\n\t\t\t\t
\n\t\t\t
\n\t\t\n\t`\n\t\t: '';\n\n\t/**\n\t * Determines whether column containing the Title,\n\t * the Description and the Button of the list's item should render.\n\t * @return {boolean} True if column 2 should render, false otherwise.\n\t */\n\tfunction shouldColumn2Render() {\n\t\treturn (\n\t\t\tcomp.get('displayTitle') ||\n\t\t\tcomp.get('displayDescription') ||\n\t\t\tcomp.get('displayButton')\n\t\t);\n\t}\n\n\t/**\n\t * Returns the HTML representation of th column containing the Title,\n\t * the Description and the Button of the list's item.\n\t * @return {string} The HTML representation of the column.\n\t */\n\tfunction getColumn2Html() {\n\t\tlet marginString;\n\t\tif (comp.get('displayImage'))\n\t\t\tmarginString = isMobileOptimized\n\t\t\t\t? ''\n\t\t\t\t: comp.get('imagePlacement') === 'top'\n\t\t\t\t? `margin-top: ${comp.get('verticalSpacingBetweenElements')};`\n\t\t\t\t: `margin-${comp.get('imagePlacement')}: ${comp.get(\n\t\t\t\t\t\t'horizontalSpacingBetweenElements'\n\t\t\t\t )};`;\n\n\t\t/**\n\t\t * Creates a table row with padding and inserts the provided element,\n\t\t * getting the padding information about the element on the component props.\n\t\t *\n\t\t * @param {string} elementName - The name of the element.\n\t\t * @param {string} element - The HTML element to be inserted.\n\t\t * @return {string} The HTML representation of the table row.\n\t\t */\n\t\tfunction createRow(elementName, element) {\n\t\t\tconst padding = {\n\t\t\t\t'padding-left':\n\t\t\t\t\tparseFloat(comp.get(`${elementName}LeftMargin`)) +\n\t\t\t\t\tprettifyHorizontalSpace +\n\t\t\t\t\t'px',\n\t\t\t\t'padding-right':\n\t\t\t\t\tparseFloat(comp.get(`${elementName}RightMargin`)) +\n\t\t\t\t\tprettifyHorizontalSpace +\n\t\t\t\t\t'px',\n\t\t\t\t'padding-top':\n\t\t\t\t\tparseFloat(comp.get(`${elementName}TopMargin`)) +\n\t\t\t\t\tprettifyVerticalSpace +\n\t\t\t\t\t'px',\n\t\t\t\t'padding-bottom':\n\t\t\t\t\tparseFloat(comp.get(`${elementName}BottomMargin`)) +\n\t\t\t\t\tprettifyVerticalSpace +\n\t\t\t\t\t'px'\n\t\t\t};\n\n\t\t\tif (elementName == 'button') {\n\t\t\t\telement = `\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t\t\t${element}\n\t\t\t\t\t\t
`;\n\t\t\t}\n\n\t\t\treturn `\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t${element}\n\t\t\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
500\n\t\t\t\t\t\t\t\t\t? 'cover-'\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t }${100 - Math.floor(imageSideRatio * 10) * 10}`\n\t\t\t\t\t\t: ''\n\t\t\t\t}\" style=\"${\n\t\t\tmarginString || ''\n\t\t} width:100%;max-width:${msoSecondColWidth};display:inline-block;vertical-align:${contentVAlign};direction:ltr;\">\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\n\t\t`;\n\t}\n\n\tconst column2 = shouldColumn2Render() ? getColumn2Html() : '';\n\n\tconst msoHorizontalSpace =\n\t\tparseFloat(comp.get('horizontalSpacingBetweenElements')) > 0\n\t\t\t? `\n\t\n`\n\t\t\t: '';\n\n\tconst topView = `\n\t\t\n\t\t\t\t\t\t${column1}\n\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t${column2}\n\t\t\t\t\t\t\t\t\n\t`;\n\n\tconst html = `\n\t\t
\n\t\t\t\n\t\t\t\t${imagePlacement == 'top' ? topView : column1 + msoHorizontalSpace + column2}\n\t\t\t\n\t\t
\n\t`;\n\n\tif (options.debug) console.log('List Item HTML: ', html);\n\n\treturn html;\n};\n","import { noInteractionPreset } from '../_componentsUtils';\nimport { COMPONENTS_DEFAULTS } from '../../../config/_config';\nimport render from './_render';\nimport { getComponentsDefaultsByType } from '../../componentsDefaults/_componentsDefaults';\nimport baseMethods from '../common/methods/_baseMethods';\nimport toHtml from './_toHtml';\nimport { merge } from 'datatalks-utils';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = getComponentsDefaultsByType('list-item');\n\n\tconst options = {\n\t\t...COMPONENTS_DEFAULTS,\n\t\t...defaults,\n\t\t...componentOptions\n\t};\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\tisCompound: true,\n\t\t\t\t...options,\n\t\t\t\tname: options.name,\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: options.width,\n\t\t\t\t\t'table-layout': 'fixed'\n\t\t\t\t},\n\t\t\t\ttagName: 'table',\n\t\t\t\twidth: options.width,\n\t\t\t\talign: options.align,\n\t\t\t\tcomponents: comp => comp.componentRender(comp),\n\t\t\t\t...noInteractionPreset\n\t\t\t}),\n\t\t\tcomponentRender: render,\n\t\t\ttoHTML(toHtmlOptions = {}) {\n\t\t\t\treturn toHtml(\n\t\t\t\t\tthis,\n\t\t\t\t\tmerge(options.toHtmlOptions, toHtmlOptions)\n\t\t\t\t);\n\t\t\t},\n\t\t\t...baseMethods(componentOptions, editor)\n\t\t}\n\t};\n};\n","import { validateStyleObj } from '../../common/functions/_utilFunctions';\n/**\n * Updates the style of a component.\n * @param {Object} comp - The component to update the style for.\n */\nexport default function updateStyle(comp) {\n\tcomp.setStyle(\n\t\tvalidateStyleObj({\n\t\t\t...comp.getStyle(),\n\t\t\t'background-color': comp.get('backgroundColor'),\n\t\t\t'border-width': comp.get('borderWidth'),\n\t\t\t'border-style': comp.get('borderStyle'),\n\t\t\t'border-color': comp.get('borderColor'),\n\t\t\t'border-radius': comp.get('useBorderRadius')\n\t\t\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t\t\t: null\n\t\t})\n\t);\n}\n","// import { cloneDeep } from 'lodash-es';\nimport { merge, mapObject, insertAfterEveryItem } from 'datatalks-utils';\n\nimport { noInteractionPreset } from '../_componentsUtils';\nimport updateStyle from '../common/_updateCommonStyle';\n\nexport default parent => {\n\tlet itemsOptions = merge(\n\t\tparent.get('itemDefaultOptions'),\n\t\tparent.get('itemOptions')\n\t);\n\n\tif (parent.get('itemPropsMap'))\n\t\titemsOptions = mapObject(itemsOptions, parent.get('itemPropsMap'));\n\n\tparent.set('itemOptions', itemsOptions);\n\n\tconst getCell = item => {\n\t\treturn {\n\t\t\ttype: 'cell',\n\t\t\tattributes: {\n\t\t\t\talign: item.align || itemsOptions.align\n\t\t\t},\n\t\t\tstyle: {\n\t\t\t\t'vertical-align': item.vAlign || itemsOptions.vAlign,\n\t\t\t\twidth: `calc((100% - ${\n\t\t\t\t\tparseFloat(parent.get('spacingBetweenElements')) *\n\t\t\t\t\t(parent.attributes.items.length - 1)\n\t\t\t\t}px)/${parent.attributes.items.length})`,\n\t\t\t\toverflow: 'hidden'\n\t\t\t},\n\t\t\tcomponents: comp => {\n\t\t\t\treturn item;\n\t\t\t}\n\t\t};\n\t};\n\n\tconst innerComponents = [];\n\tif (parent.attributes.isVertical) {\n\t\tlet itemsList = [];\n\t\tparent.attributes.items.forEach(item => {\n\t\t\titemsList.push({\n\t\t\t\ttype: 'row',\n\t\t\t\tcomponents: getCell(item),\n\t\t\t\t...noInteractionPreset\n\t\t\t});\n\t\t});\n\n\t\titemsList = insertAfterEveryItem(itemsList, {\n\t\t\ttype: 'space',\n\t\t\tdimension: parent.get('spacingBetweenElements'),\n\t\t\tisVertical: true\n\t\t});\n\n\t\tinnerComponents.push(itemsList);\n\t} else {\n\t\tinnerComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'table',\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\t'table-layout': 'fixed',\n\t\t\t\t\t\twidth: '100%'\n\t\t\t\t\t},\n\t\t\t\t\tcomponents: {\n\t\t\t\t\t\ttype: 'row',\n\t\t\t\t\t\tcomponents: comp => {\n\t\t\t\t\t\t\treturn insertAfterEveryItem(\n\t\t\t\t\t\t\t\tparent.attributes.items.map(item =>\n\t\t\t\t\t\t\t\t\tgetCell(item)\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: 'space',\n\t\t\t\t\t\t\t\t\tdimension: parent.get(\n\t\t\t\t\t\t\t\t\t\t'spacingBetweenElements'\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tisVertical: false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t...noInteractionPreset\n\t\t});\n\t}\n\n\t// TODO: add an option to skip style update on render\n\tupdateStyle(parent);\n\n\treturn [\n\t\t{\n\t\t\ttype: 'margins',\n\t\t\tinnerComponents,\n\t\t\thasMargins: parent.get('hasMargins'),\n\t\t\tmargins: {\n\t\t\t\ttop: parent.get('topMargin'),\n\t\t\t\tright: parent.get('rightMargin'),\n\t\t\t\tbottom: parent.get('bottomMargin'),\n\t\t\t\tleft: parent.get('leftMargin')\n\t\t\t},\n\t\t\tmarginsColor: {\n\t\t\t\ttop: parent.get('topMarginColor'),\n\t\t\t\tright: parent.get('rightMarginColor'),\n\t\t\t\tbottom: parent.get('bottomMarginColor'),\n\t\t\t\tleft: parent.get('leftMarginColor')\n\t\t\t}\n\t\t}\n\t];\n};\n","import { cloneDeep, debounce } from 'lodash-es';\nimport { arrayMove, arrayRemove } from 'datatalks-utils';\nimport baseMethods from '../common/methods/_baseMethods';\n\nexport default (componentOptions, editor) => {\n\tconst debouncedRender = debounce(comp => {\n\t\tcomp.components(comp.componentRender(comp));\n\t}, editor.getEmailBuilder().getOptions().renderingDebounceTime);\n\n\treturn {\n\t\tinit() {\n\t\t\tthis.setStyle({\n\t\t\t\t...this.getStyle(),\n\t\t\t\twidth: this.get('width')\n\t\t\t});\n\t\t\tif (!this.get('items').length) {\n\t\t\t\tthis.set(\n\t\t\t\t\t'items',\n\t\t\t\t\tArray(this.get('numberOfStartingItems'))\n\t\t\t\t\t\t.fill({})\n\t\t\t\t\t\t.map(item =>\n\t\t\t\t\t\t\tcloneDeep({\n\t\t\t\t\t\t\t\ttype: this.get('itemType'),\n\t\t\t\t\t\t\t\t...this.get('itemDefaultOptions'),\n\t\t\t\t\t\t\t\t...this.get('itemOptions')\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t\tthis.rerender();\n\t\t\t}\n\t\t},\n\t\tsetAndRerender(attr, value, forceItemsRerender = true) {\n\t\t\tthis.set(attr, value);\n\t\t\tthis.rerender(forceItemsRerender);\n\t\t},\n\n\t\taddItem(itemOptions = {}) {\n\t\t\tconst newItem = {\n\t\t\t\ttype: this.get('itemType'),\n\t\t\t\t...this.get('itemDefaultOptions'),\n\t\t\t\t...this.get('itemOptions'),\n\t\t\t\t...itemOptions\n\t\t\t};\n\t\t\tthis.get('items').push(newItem);\n\t\t\tthis.rerender();\n\n\t\t\tthis.get('getCustomTrait')().draw();\n\n\t\t\treturn newItem;\n\t\t},\n\n\t\tcanAddMoreItems() {\n\t\t\treturn this.get('items').length < this.get('maxItems');\n\t\t},\n\n\t\tdeleteItem(item, callback) {\n\t\t\tarrayRemove(this.get('items'), item);\n\n\t\t\tif (!this.get('items').length) {\n\t\t\t\tthis.remove();\n\t\t\t} else {\n\t\t\t\tthis.rerender(true);\n\t\t\t}\n\n\t\t\tthis.get('getCustomTrait')().draw();\n\n\t\t\tif (typeof callback === 'function') {\n\t\t\t\tcallback();\n\t\t\t}\n\t\t},\n\n\t\tchangeItemsOrder(oldIndex, newIndex, forceItemsRerender = true) {\n\t\t\tarrayMove(this.get('items'), oldIndex, newIndex);\n\t\t\tthis.rerender(forceItemsRerender);\n\t\t},\n\n\t\tchangeItemProp(target, propName, value, rerender = true, callback) {\n\t\t\tif (this.get('itemPropsMap'))\n\t\t\t\tpropName = this.get('itemPropsMap')[propName] || propName;\n\n\t\t\tif (target) {\n\t\t\t\tconst item = this.get('items').filter(\n\t\t\t\t\titem => item == target\n\t\t\t\t)[0];\n\t\t\t\titem[propName] = value;\n\t\t\t\tif (rerender) this.rerender();\n\t\t\t\tthis.emitUpdate(`item:${propName}`, item, value);\n\t\t\t\tthis.emitUpdate('item', item);\n\t\t\t}\n\n\t\t\tif (typeof callback === 'function') {\n\t\t\t\tcallback();\n\t\t\t}\n\t\t},\n\n\t\tchangeItemsProp(propName, value, changeItemsOptions = true) {\n\t\t\tif (this.get('itemPropsMap'))\n\t\t\t\tpropName = this.get('itemPropsMap')[propName] || propName;\n\n\t\t\tif (changeItemsOptions) {\n\t\t\t\tthis.set('itemOptions', {\n\t\t\t\t\t...this.get('itemOptions'),\n\t\t\t\t\t[propName]: value\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.get('items').forEach(item => {\n\t\t\t\titem[propName] = value;\n\t\t\t\tthis.emitUpdate(`item:${propName}`, item, value);\n\t\t\t\tthis.emitUpdate('item', item);\n\t\t\t});\n\t\t\tthis.rerender();\n\t\t\tthis.emitUpdate('items', this.get('items'));\n\t\t},\n\n\t\tgetItemsProp(prop) {\n\t\t\tif (this.get('itemPropsMap'))\n\t\t\t\tprop = this.get('itemPropsMap')[prop] || prop;\n\n\t\t\treturn this.get('items')[0][prop];\n\t\t},\n\n\t\tgetItemProp(target, prop) {\n\t\t\tif (this.get('itemPropsMap'))\n\t\t\t\tprop = this.get('itemPropsMap')[prop] || prop;\n\n\t\t\tif (target) {\n\t\t\t\tconst item = this.get('items').filter(\n\t\t\t\t\tcomp => comp == target\n\t\t\t\t)[0];\n\t\t\t\treturn item[prop];\n\t\t\t} else {\n\t\t\t\tconsole.error(`Item doesn't contain a property called ${prop}`);\n\t\t\t}\n\t\t},\n\n\t\trerender() {\n\t\t\tdebouncedRender(this);\n\t\t},\n\t\t...baseMethods(componentOptions, editor)\n\t};\n};\n","/**\n * The object containing the options to configure the list trait\n * @typedef { Object } ListTraitOptions\n * @property { string } cssClass - The base class to apply to the wrapper container of the list trait.\n * @property { string } extendedClasses - Other classes to apply to the wrapper container of the list trait (i.e. utility classes).\n */\n\n/**\n * Creates a trait of the type 'list' configured with the passed options\n * @param {ListTraitOptions} options - The options to configure the list trait.\n */\n\nexport default (options = {}) => {\n\treturn {\n\t\ttype: 'list',\n\t\toptions\n\t};\n};\n","import { merge } from 'datatalks-utils';\nimport listTrait from './trait/_trait';\n\nexport default comp => {\n\tconst traitOptions = merge(\n\t\tcomp.get('traitDefaultOptions') || {},\n\t\tcomp.get('traitOptions') || {}\n\t);\n\n\tconst result = [listTrait(traitOptions)];\n\n\treturn result;\n};\n","import { validateStyleObj } from '../../common/functions/_utilFunctions';\n\nexport default comp => {\n\tconst getGeneralStyle = comp\n\t\t.getEditor()\n\t\t.getStyleRules.bind(comp.getEditor(), 'component');\n\n\tconst borderRadius = comp.get('useBorderRadius')\n\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t: [\n\t\t\t\tgetGeneralStyle('border-top-left-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-top-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-left-radius') || 0\n\t\t ].join(' ');\n\n\treturn validateStyleObj({\n\t\t'background-color':\n\t\t\tcomp.get('backgroundColor') || getGeneralStyle('background-color'),\n\t\twidth: comp.get('width'),\n\t\t'border-radius': borderRadius\n\t});\n};\n","import { merge, cssStyleObjectToString } from 'datatalks-utils';\n\nimport { validateStyleObj } from '../../../common/functions/_utilFunctions';\n\nexport default (innerHtml, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\ttopMargin: '0px',\n\t\trightMargin: '0px',\n\t\tbottomMargin: '0px',\n\t\tleftMargin: '0px',\n\t\thasMargins: false,\n\t\twidth: '100%',\n\t\tbackgroundColor: null\n\t};\n\n\toptions = merge(defaults, options);\n\n\tconst tableStyle = {\n\t\twidth: options.width\n\t};\n\n\tconst cellStyle = {\n\t\t'background-color': options.backgroundColor,\n\t\t'padding-top': options.hasMargins ? options.topMargin || 0 : 0,\n\t\t'padding-right': options.hasMargins ? options.rightMargin || 0 : 0,\n\t\t'padding-bottom': options.hasMargins ? options.bottomMargin || 0 : 0,\n\t\t'padding-left': options.hasMargins ? options.leftMargin || 0 : 0\n\t};\n\n\tconst html = `\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t
\n\t\t\t\t\t${innerHtml}\n\t\t\t\t
\n\t`;\n\n\tif (options.debug) console.log('Margins common template HTML: ', html);\n\n\treturn html;\n};\n","import { merge, cssStyleObjectToString, getUnit } from 'datatalks-utils';\n\nimport getComputedStyle from './_getComputedStyle';\nimport margins from '../common/htmlTemplates/_margins';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tparentWidth: null,\n\t\tstyle: getComputedStyle(comp),\n\t\tspace: comp.get('spacingBetweenElements')\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst isMobileOptimized = comp\n\t\t.getEditor()\n\t\t.getEmailBuilder()\n\t\t.getAdvancedOption('isMobileOptimized');\n\tconst nColumns = comp.get('items')?.length;\n\tconst align = comp.get('align') || 'center';\n\toptions.space =\n\t\tparseFloat(options.space) -\n\t\t(isMobileOptimized && comp.get('itemType') !== 'list-item'\n\t\t\t? parseFloat(\n\t\t\t\t\tcomp?.get('itemOptions')\n\t\t\t\t\t\t?.horizontalSpacingBetweenElements || 0\n\t\t\t )\n\t\t\t: 0) +\n\t\t'px';\n\tconst colPadding =\n\t\tisMobileOptimized && !isNaN(parseFloat(options.space))\n\t\t\t? parseFloat(options.space) / 2 + 'px'\n\t\t\t: 0;\n\tconst parentWidth = options.parentWidth;\n\tconst itemsVerticalAlignment = comp.getItemsProp('vAlign');\n\tconst itemsBackgroundColor = comp.getItemsProp('backgroundColor');\n\n\tconst marginsWidth = comp.get('hasMargins')\n\t\t? parseFloat(comp.get('leftMargin')) +\n\t\t parseFloat(comp.get('rightMargin')) +\n\t\t 'px'\n\t\t: 0;\n\n\t/**\n\t * Calculates the width of the list item based on the parent width, provided options and number of columns.\n\t * @return {number} The width of the parent element.\n\t */\n\tfunction getParentWidth() {\n\t\tif (\n\t\t\tcomp.getItemsProp('width') != 'auto' &&\n\t\t\tgetUnit(comp.getItemsProp('width')) == 'px'\n\t\t)\n\t\t\treturn parseFloat(comp.getItemsProp('width'));\n\t\tif (!comp.get('isVertical'))\n\t\t\treturn (\n\t\t\t\t(parseFloat(options.parentWidth) -\n\t\t\t\t\tparseFloat(marginsWidth) -\n\t\t\t\t\tparseFloat(options.space) *\n\t\t\t\t\t\t(nColumns - (isMobileOptimized ? 0 : 1))) /\n\t\t\t\tnColumns\n\t\t\t);\n\t\telse return parseFloat(options.parentWidth) - parseFloat(marginsWidth);\n\t}\n\n\t/**\n\t * Get the HTML representation of a list item at the specified index.\n\t * @param {number} index - The index of the list's item.\n\t * @return {string} The HTML representation of the list item.\n\t */\n\tfunction getItem(index) {\n\t\treturn comp.findType(comp.get('itemType'))[index]?.toHTML({\n\t\t\tparentWidth: `${getParentWidth()}px`,\n\t\t\tisMobileOptimized\n\t\t});\n\t}\n\n\tconst debugStrStart = options.debug ? 'data-eb-name=\"list-first\"' : '';\n\tconst debugStrEnd = options.debug ? 'data-eb-name=\"list-last\"' : '';\n\n\tconst itemsBackgroundStyle =\n\t\titemsBackgroundColor && itemsBackgroundColor != 'transparent'\n\t\t\t? `background:${itemsBackgroundColor};`\n\t\t\t: '';\n\n\tconst itemsBackgroundAttr =\n\t\titemsBackgroundColor && itemsBackgroundColor != 'transparent'\n\t\t\t? `bgcolor=\"${itemsBackgroundColor}\"`\n\t\t\t: '';\n\n\tconst verticalInnerHtml = `\n\t\t\n\t\t\t${comp\n\t\t\t\t.get('items')\n\t\t\t\t.map(\n\t\t\t\t\t(item, index) => `\n\t\t\t\t\t\t${\n\t\t\t\t\t\t\tindex !== 0\n\t\t\t\t\t\t\t\t? ``\n\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t`\n\t\t\t\t)\n\t\t\t\t.join('')}\n\t\t
\n\t\t\t\t\t\t\t\t${getItem(index)}\n\t\t\t\t\t\t\t
\n\t`;\n\n\tconst horizontalInnerHtml = `\n\t\t
\n\t\t\t\n\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t${getItem(index)}\n\t\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\n\t\t
\n\t`;\n\n\tconst innerHtml = comp.get('isVertical')\n\t\t? verticalInnerHtml\n\t\t: horizontalInnerHtml;\n\n\tconst html = margins(innerHtml, {\n\t\ttopMargin: comp.get('topMargin') || 0,\n\t\trightMargin: comp.get('rightMargin') || 0,\n\t\tbottomMargin: comp.get('bottomMargin') || 0,\n\t\tleftMargin: comp.get('leftMargin') || 0,\n\t\thasMargins: comp.get('hasMargins'),\n\t\tbackgroundColor: comp.get('backgroundColor')\n\t});\n\n\tif (options.debug)\n\t\tconsole.log('List HTML: ', comp.get('hasMargins') ? html : innerHtml);\n\n\treturn comp.get('hasMargins') ? html : innerHtml;\n};\n","import { COMPONENTS_DEFAULTS } from '../../../config/_config';\nimport render from './_render';\nimport methods from './_methods';\nimport buildTrait from './_buildTrait';\nimport { merge } from 'datatalks-utils';\nimport { getComponentsDefaultsByType } from '../../componentsDefaults/_componentsDefaults';\nimport toHtml from './_toHtml';\n\n/**\n * @typedef {'left' | 'center' | 'right'} ComponentAlignment\n */\n\n/**\n * The object containing the options to configure the list component build\n * @typedef { Object } ListComponentBuildOptions\n * @property {ListItemComponent } defaultItem - The default ListItem component to add when adding a new item.\n * @property { ListItemComponent[] } startItemsList - The list of ListItem components to display when using the list component.\n * @property { string } width - The width of the list component (in CSS notation).\n * @property { ComponentAlignment } align - The alignment of the component. See ComponentAlignment type definition.\n * @property { boolean } isVertical - If set to true the list is displayed in the vertical, else it would be displayed horizontally.\n */\n\n/**\n * Returns an List component configured with the passed options\n * @param { ListComponentBuildOptions } componentOptions - The options to configure the list component.\n * @param { EmailBuilder } emailBuilder - The Email Builder class instance.\n * @return { ListComponent } The List component\n */\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = {\n\t\tattributes: {},\n\t\tcssClass: 'gjs-comp-list',\n\t\twidth: '100%',\n\t\talign: 'center',\n\t\tisVertical: false,\n\t\tstyle: {\n\t\t\t'table-layout': 'fixed'\n\t\t},\n\t\tnumberOfStartingItems: 2,\n\t\tmaxItems: 3,\n\t\tname: 'List',\n\t\titemType: 'list-item',\n\t\titemOptions: {\n\t\t\tdescription: '

This is part of a list

',\n\t\t\timgWidth: '100%'\n\t\t},\n\t\ttraitDefaultOptions: {\n\t\t\tmutateOptions: {\n\t\t\t\tlistItemElementTemplateOptions: {\n\t\t\t\t\thasImageUploader: true,\n\t\t\t\t\thasTitleEditor: true,\n\t\t\t\t\thasDescriptionEditor: true,\n\t\t\t\t\thasButtonEditor: true,\n\t\t\t\t\tbuttonProp: 'buttonText',\n\t\t\t\t\ttitleProp: 'title'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tspacingBetweenElements: '24px',\n\t\titemPropsMap: null,\n\t\ttoHtmlOptions: {}\n\t};\n\n\tconst options = merge(\n\t\tCOMPONENTS_DEFAULTS,\n\t\tgetComponentsDefaultsByType(),\n\t\tdefaults,\n\t\tcomponentOptions\n\t);\n\n\toptions.itemOptions = merge(\n\t\tgetComponentsDefaultsByType(options.itemType) || {},\n\t\toptions.itemOptions\n\t);\n\n\tif (options.numberOfStartingItems > options.maxItems)\n\t\toptions.numberOfStartingItems = options.maxItems;\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\tisCompound: true,\n\t\t\t\t...options,\n\t\t\t\tname: options.name,\n\t\t\t\titemDefaultOptions: options.itemOptions,\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\talign: options.align,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tstyle: merge(options.style, { width: options.width }),\n\t\t\t\ttagName: 'table',\n\t\t\t\tcomponents: comp => comp.componentRender(comp),\n\t\t\t\titems: [],\n\t\t\t\tdefaultItem: options.defaultItem,\n\t\t\t\tisVertical: options.isVertical,\n\t\t\t\ttraits: comp => comp.buildTrait(comp)\n\t\t\t}),\n\n\t\t\ttoHTML(toHtmlOpts = {}) {\n\t\t\t\treturn toHtml(this, merge(options.toHtmlOptions, toHtmlOpts));\n\t\t\t},\n\n\t\t\tcomponentRender: render,\n\t\t\tbuildTrait,\n\t\t\t...methods(options, editor)\n\t\t}\n\t};\n};\n","/**\n * The object containing the callbacks for the file reader events\n * @typedef { Object } HeaderTraitOptions\n * @property { string } cssClass - The base class to apply to the wrapper container of the header trait.\n * @property { string } extendedClasses - Other classes to apply to the wrapper container of the header trait (i.e. utility classes).\n * @property { object } contentTabOptions - The options to configure header trait's content tab.\n * @property { object } styleTabOptions - The options to configure header trait's style tab.\n */\n\n/**\n * Creates a trait of the type 'header' configured with the passed options\n * @param {HeaderTraitOptions} options - The options to configure the header trait.\n */\n\nexport default (options = {}) => {\n\treturn {\n\t\ttype: 'header',\n\t\toptions\n\t};\n};\n","import { getUnit } from 'datatalks-utils';\n\nimport { addSpace as _addSpace } from '../_componentsUtils';\nimport { validateStyleObj } from '../../common/functions/_utilFunctions';\nimport updateStyle from '../common/_updateCommonStyle';\n\nexport default comp => {\n\tlet image;\n\n\tconst innerComponents = [];\n\tconst addVerticalSpace = _addSpace.bind(null, comp, true, innerComponents);\n\n\tconst recommendedWidth =\n\t\tgetUnit(comp.attributes.imageWidth) == '%'\n\t\t\t? (parseInt(comp.attributes.imageWidth) / 100) * 600\n\t\t\t: getUnit(comp.attributes.imageWidth) == 'px'\n\t\t\t? parseInt(comp.attributes.imageWidth)\n\t\t\t: comp.attributes.imageWidth;\n\n\tif (\n\t\tcomp.attributes.imgSrc ||\n\t\t!comp.attributes.useImagePlaceholderComponent\n\t) {\n\t\timage = {\n\t\t\ttype: 'image-wrapper',\n\t\t\tstyle: validateStyleObj({\n\t\t\t\t'border-radius': comp.attributes.imageUseBorderRadius\n\t\t\t\t\t? Object.values(comp.get('imageBorderRadius')).join(' ')\n\t\t\t\t\t: null,\n\t\t\t\t'border-color': comp.get('imageBorderColor'),\n\t\t\t\t'border-style': comp.get('imageBorderStyle'),\n\t\t\t\t'border-width': comp.get('imageBorderWidth'),\n\t\t\t\twidth:\n\t\t\t\t\tcomp.get('layoutVariant') === 0\n\t\t\t\t\t\t? '100%'\n\t\t\t\t\t\t: comp.attributes.imageWidth\n\t\t\t}),\n\t\t\timgSrc: comp.attributes.imgSrc,\n\t\t\thref: comp.get('imageHref'),\n\t\t\thasLink: comp.get('imageHasLink')\n\t\t};\n\t} else {\n\t\timage = {\n\t\t\ttype: 'image-placeholder',\n\t\t\tstyle: {\n\t\t\t\twidth:\n\t\t\t\t\tcomp.get('layoutVariant') === 0\n\t\t\t\t\t\t? '100%'\n\t\t\t\t\t\t: comp.attributes.imageWidth\n\t\t\t},\n\t\t\timagePlaceholderHTMLOptions: {\n\t\t\t\trecommendedWidth\n\t\t\t}\n\t\t};\n\t}\n\n\tif (comp.get('layoutVariant') === 0) {\n\t\t// side by side\n\t\tconst comps = [];\n\t\tif (comp.get('displayImage')) {\n\t\t\tcomps.push({\n\t\t\t\ttype: 'cell',\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: comp.attributes.imageWidth\n\t\t\t\t},\n\t\t\t\tattributes: {\n\t\t\t\t\talign: comp.attributes.imageAlignment\n\t\t\t\t},\n\t\t\t\tcomponents: image\n\t\t\t});\n\t\t}\n\n\t\tif (comp.get('displayLinks')) {\n\t\t\tif (comps.length)\n\t\t\t\tcomps.push({\n\t\t\t\t\ttype: 'space',\n\t\t\t\t\tdimension: comp.get('spacingBetweenElements'),\n\t\t\t\t\tisVertical: false\n\t\t\t\t});\n\n\t\t\tcomps.push({\n\t\t\t\ttype: 'cell',\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: comp.get('useLinksGap')\n\t\t\t\t\t\t? 'auto'\n\t\t\t\t\t\t: comp.attributes.linksListWidth\n\t\t\t\t},\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'links-list',\n\t\t\t\t\tlinksList: comp.attributes.linksList,\n\t\t\t\t\tlinksAlignment: 'center',\n\t\t\t\t\tlistWidth: comp.get('useLinksGap') ? 'auto' : '100%',\n\t\t\t\t\tlistAlign: comp.attributes.linksListAlign,\n\t\t\t\t\tlinksBorderRadius: comp.attributes.linksBorderRadius,\n\t\t\t\t\tlinksUseBorderRadius: comp.attributes.linksUseBorderRadius,\n\t\t\t\t\tlinksBorderColor: comp.attributes.linksBorderColor,\n\t\t\t\t\tlinksBorderStyle: comp.attributes.linksBorderStyle,\n\t\t\t\t\tlinksBorderWidth: comp.attributes.linksBorderWidth,\n\t\t\t\t\tlinksColor: comp.attributes.linksColor,\n\t\t\t\t\tlinksBackground: comp.attributes.linksBackground,\n\t\t\t\t\tlinksFont: comp.attributes.linksFont,\n\t\t\t\t\tlinksWeight: comp.attributes.linksWeight,\n\t\t\t\t\tlinksLetterSpacing: comp.attributes.linksLetterSpacing,\n\t\t\t\t\tgap: comp.get('useLinksGap') ? comp.get('linksGap') : 0,\n\t\t\t\t\tisTextList: comp.get('isTextList')\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tinnerComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: comps\n\t\t});\n\t} else {\n\t\tif (comp.get('displayImage')) {\n\t\t\tinnerComponents.push({\n\t\t\t\ttype: 'row',\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'cell',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tcolSpan: comp.attributes.linksList.length * 2 - 1,\n\t\t\t\t\t\talign: comp.attributes.imageAlignment\n\t\t\t\t\t},\n\t\t\t\t\tcomponents: image\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tif (comp.get('displayLinks')) {\n\t\t\tif (innerComponents.length) addVerticalSpace();\n\n\t\t\tinnerComponents.push({\n\t\t\t\ttype: 'row',\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'cell',\n\t\t\t\t\tcomponents: {\n\t\t\t\t\t\ttype: 'links-list',\n\t\t\t\t\t\tlinksList: comp.attributes.linksList,\n\t\t\t\t\t\tlinksAlignment: 'center',\n\t\t\t\t\t\tlistWidth: comp.get('useLinksGap')\n\t\t\t\t\t\t\t? 'auto'\n\t\t\t\t\t\t\t: comp.attributes.linksListWidth,\n\t\t\t\t\t\tlistAlign: comp.attributes.linksListAlign,\n\t\t\t\t\t\tlinksBorderRadius: comp.attributes.linksBorderRadius,\n\t\t\t\t\t\tlinksBorderColor: comp.attributes.linksBorderColor,\n\t\t\t\t\t\tlinksBorderStyle: comp.attributes.linksBorderStyle,\n\t\t\t\t\t\tlinksBorderWidth: comp.attributes.linksBorderWidth,\n\t\t\t\t\t\tlinksColor: comp.attributes.linksColor,\n\t\t\t\t\t\tlinksBackground: comp.attributes.linksBackground,\n\t\t\t\t\t\tlinksFont: comp.attributes.linksFont,\n\t\t\t\t\t\tlinksWeight: comp.attributes.linksWeight,\n\t\t\t\t\t\tlinksLetterSpacing: comp.attributes.linksLetterSpacing,\n\t\t\t\t\t\tgap: comp.get('useLinksGap') ? comp.get('linksGap') : 0,\n\t\t\t\t\t\tisTextList: comp.get('isTextList')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tupdateStyle(comp);\n\n\treturn [\n\t\t{\n\t\t\ttype: 'margins',\n\t\t\tinnerComponents,\n\t\t\thasMargins: comp.get('hasMargins'),\n\t\t\tmargins: {\n\t\t\t\ttop: comp.get('topMargin'),\n\t\t\t\tright: comp.get('rightMargin'),\n\t\t\t\tbottom: comp.get('bottomMargin'),\n\t\t\t\tleft: comp.get('leftMargin')\n\t\t\t},\n\t\t\tmarginsColor: {\n\t\t\t\ttop: comp.get('topMarginColor'),\n\t\t\t\tright: comp.get('rightMarginColor'),\n\t\t\t\tbottom: comp.get('bottomMarginColor'),\n\t\t\t\tleft: comp.get('leftMarginColor')\n\t\t\t}\n\t\t}\n\t];\n};\n","import { validateStyleObj } from '../../common/functions/_utilFunctions';\n\nexport default comp => {\n\tconst getGeneralStyle = comp\n\t\t.getEditor()\n\t\t.getStyleRules.bind(comp.getEditor(), 'component');\n\n\tconst borderRadius = comp.get('useBorderRadius')\n\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t: [\n\t\t\t\tgetGeneralStyle('border-top-left-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-top-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-left-radius') || 0\n\t\t ].join(' ');\n\n\tconst style = {\n\t\t'background-color':\n\t\t\tcomp.get('backgroundColor') || getGeneralStyle('background-color'),\n\t\twidth: comp.get('width'),\n\t\t'border-radius': borderRadius\n\t};\n\n\treturn validateStyleObj(style);\n};\n","import { merge, cssStyleObjectToString } from 'datatalks-utils';\nimport getComputedStyle from './_getComputedStyle';\nimport margins from '../common/htmlTemplates/_margins';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tstyle: getComputedStyle(comp),\n\t\ttext: comp.get('text'),\n\t\tparentWidth: null,\n\t\talign: comp.get('align') || 'center',\n\t\tverticalAlignment: comp.get('vAlign'),\n\t\tsideLayout: comp.get('layoutVariant') === 0,\n\t\timageWidth: comp.get('imageWidth'),\n\t\tlinksListWidth: comp.get('linksListWidth'),\n\t\tspaceSize: comp.get('spacingBetweenElements')\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tconst sideLayout =\n\t\toptions.sideLayout &&\n\t\tcomp.get('displayImage') &&\n\t\tcomp.get('displayLinks');\n\n\tconst imageRatio = parseFloat(options.imageWidth) / 100;\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst isMobileOptimized = comp\n\t\t.getEditor()\n\t\t.getEmailBuilder()\n\t\t.getAdvancedOption('isMobileOptimized');\n\n\tconst marginsWidth = comp.get('hasMargins')\n\t\t? parseFloat(comp.get('leftMargin')) +\n\t\t parseFloat(comp.get('rightMargin')) +\n\t\t 'px'\n\t\t: 0;\n\n\t/**\n\t * Calculates the width of the list item based on the parent width, provided options and number of columns.\n\t * @param {boolean} isImage - Whether it should calculate image's width or links' width.\n\t * @return {number} The width (without unit, only number) in pixels of the element based on the parent's width.\n\t */\n\tfunction getParentWidth(isImage) {\n\t\tconst ratio = isImage ? imageRatio : 1 - imageRatio;\n\t\tif (sideLayout)\n\t\t\treturn (\n\t\t\t\t(parseFloat(options.parentWidth) -\n\t\t\t\t\tparseFloat(marginsWidth) -\n\t\t\t\t\tparseFloat(comp.get('spacingBetweenElements'))) *\n\t\t\t\tratio\n\t\t\t);\n\t\telse {\n\t\t\tif (isImage) {\n\t\t\t\treturn (\n\t\t\t\t\t(parseFloat(options.imageWidth) / 100) *\n\t\t\t\t\t(parseFloat(options.parentWidth) - parseFloat(marginsWidth))\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\treturn (\n\t\t\t\t\t(parseFloat(\n\t\t\t\t\t\toptions.linksListWidth == 'auto'\n\t\t\t\t\t\t\t? 100\n\t\t\t\t\t\t\t: options.linksListWidth\n\t\t\t\t\t) /\n\t\t\t\t\t\t100) *\n\t\t\t\t\t(parseFloat(options.parentWidth) - parseFloat(marginsWidth))\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves the HTML representation of a specific element based on its name.\n\t *\n\t * @param {string} name - The name of the element to retrieve.\n\t * @return {string} The HTML representation of the element.\n\t */\n\tfunction getElement(name) {\n\t\tswitch (name) {\n\t\t\tcase 'image':\n\t\t\t\treturn comp\n\t\t\t\t\t.findType('image-wrapper')[0]\n\t\t\t\t\t.toHTML({ parentWidth: imageWidthPx });\n\t\t\t\tbreak;\n\n\t\t\tcase 'links':\n\t\t\t\treturn comp\n\t\t\t\t\t.findType('links-list')[0]\n\t\t\t\t\t.toHTML({ parentWidth: linksWidthPx, isMobileOptimized });\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tconsole.warn('Invalid element name: ', name);\n\t\t\t\treturn '';\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet innerHtml;\n\n\tconst imageWidthPx = getParentWidth(true) + 'px';\n\tconst linksWidthPx = getParentWidth(false) + 'px';\n\n\tconst bgString = options.style['background-color']\n\t\t? `bgcolor=\"${options.style['background-color']}\"`\n\t\t: '';\n\n\tconst va = options.verticalAlignment;\n\tconst style = cssStyleObjectToString(options.style);\n\tconst columnPadding = isMobileOptimized\n\t\t? `padding:${parseFloat(options.spaceSize) / 2}px;`\n\t\t: '';\n\n\tconst debugStrStart = options.debug ? 'data-eb-name=\"header-first\"' : '';\n\tconst debugStrEnd = options.debug ? 'data-eb-name=\"header-last\"' : '';\n\n\tif (sideLayout) {\n\t\tconst linksPerWidth = 100 - parseFloat(options.imageWidth) + '%';\n\t\tconst imagePerWidth = options.imageWidth;\n\t\tinnerHtml = `\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t${getElement('image')}\n\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t${getElement('links')}\n\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\n\t\t\t
\n\t`;\n\t} else {\n\t\tinnerHtml = `\n\t\t\t\n\t\t\t\t${\n\t\t\t\t\tcomp.get('displayImage')\n\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t`\n\t\t\t\t\t\t: ''\n\t\t\t\t}\n\t\t\t\t${\n\t\t\t\t\tcomp.get('displayImage') && comp.get('displayLinks')\n\t\t\t\t\t\t? ``\n\t\t\t\t\t\t: ''\n\t\t\t\t}\n\t\t\t\t${\n\t\t\t\t\tcomp.get('displayLinks')\n\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t`\n\t\t\t\t\t\t: ''\n\t\t\t\t}\n\t\t\t
\n\t\t\t\t\t\t\t\t${getElement('image')}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t${getElement('links')}\n\t\t\t\t\t\t\t\t
\n\t\t`;\n\t}\n\n\tconst html = margins(innerHtml, {\n\t\ttopMargin: comp.get('topMargin') || 0,\n\t\trightMargin: comp.get('rightMargin') || 0,\n\t\tbottomMargin: comp.get('bottomMargin') || 0,\n\t\tleftMargin: comp.get('leftMargin') || 0,\n\t\thasMargins: comp.get('hasMargins'),\n\t\tbackgroundColor: comp.get('backgroundColor')\n\t});\n\n\tif (options.debug)\n\t\tconsole.log('Header HTML: ', comp.get('hasMargins') ? html : innerHtml);\n\n\treturn comp.get('hasMargins') ? html : innerHtml;\n};\n","// import { noInteractionPreset } from '../_componentsUtils';\nimport { COMPONENTS_DEFAULTS } from '../../../config/_config';\nimport headerTrait from './trait/_trait';\nimport {\n\tarrayMove,\n\tarrayRemove,\n\tgetElementWidthPercentage,\n\tfileReader,\n\tmerge\n} from 'datatalks-utils';\nimport render from './_render';\nimport baseMethods from '../common/methods/_baseMethods';\nimport { getComponentsDefaultsByType } from '../../componentsDefaults/_componentsDefaults';\nimport toHtml from './_toHtml';\nimport { cloneDeep } from 'lodash-es';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = {\n\t\tattributes: {},\n\t\talign: 'center',\n\t\tvAlign: 'middle',\n\t\tspacingBetweenElements: '12px',\n\t\tcssClass: 'gjs-comp-header',\n\t\twidth: '100%',\n\t\timageAlignment: 'center',\n\t\timgPh: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIHZpZXdCb3g9IjAgMCAyNCAyNCIgc3R5bGU9ImZpbGw6IHJnYmEoMCwwLDAsMC4xNSk7IHRyYW5zZm9ybTogc2NhbGUoMC43NSkiPgogICAgICAgIDxwYXRoIGQ9Ik04LjUgMTMuNWwyLjUgMyAzLjUtNC41IDQuNSA2SDVtMTYgMVY1YTIgMiAwIDAgMC0yLTJINWMtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxNGMxLjEgMCAyLS45IDItMnoiPjwvcGF0aD4KICAgICAgPC9zdmc+',\n\t\timageWidth: '25%',\n\t\tlinksList: [\n\t\t\t{\n\t\t\t\tcontent: 'Title',\n\t\t\t\thref: 'http://www.title.com',\n\t\t\t\ttarget: '_blank'\n\t\t\t},\n\t\t\t{\n\t\t\t\tcontent: 'Title',\n\t\t\t\thref: 'http://www.title.com',\n\t\t\t\ttarget: '_blank'\n\t\t\t},\n\t\t\t{\n\t\t\t\tcontent: 'Title',\n\t\t\t\thref: 'http://www.title.com',\n\t\t\t\ttarget: '_blank'\n\t\t\t},\n\t\t\t{\n\t\t\t\tcontent: 'Title',\n\t\t\t\thref: 'http://www.title.com',\n\t\t\t\ttarget: '_blank'\n\t\t\t}\n\t\t],\n\t\tisTextList: false,\n\t\tnewLink: {\n\t\t\tcontent: 'Title',\n\t\t\thref: 'http://www.title.com',\n\t\t\ttarget: '_blank'\n\t\t},\n\t\taddLinkCallback: null,\n\t\ttagName: 'table',\n\t\tuseImagePlaceholderComponent: false,\n\t\tlinksListWidth: '60%',\n\t\tlinksListAlign: 'center',\n\t\tlinksBorderRadius: {\n\t\t\ttopLeft: 0,\n\t\t\ttopRight: 0,\n\t\t\tbottomRight: 0,\n\t\t\tbottomLeft: 0\n\t\t},\n\t\tlinksUseBorderRadius: false,\n\t\tlinksBorderColor: 'transparent',\n\t\tlinksBorderStyle: 'solid',\n\t\tlinksBorderWidth: 0,\n\t\tlinksColor: null,\n\t\tlinksBackground: 'transparent',\n\t\tlinksGap: '20px',\n\t\tuseLinksGap: false,\n\t\tlinksFont: null,\n\t\tlinksWeight: 'normal',\n\t\tlinksLetterSpacing: 'normal',\n\t\tlinksNormalLetterSpacing: true,\n\t\tlinksDefaultLetterSpacingLength: '0.1em',\n\t\tname: 'Header',\n\t\tdisplayImage: true,\n\t\tdisplayLinks: true,\n\t\timageBorderRadius: {\n\t\t\ttopLeft: 0,\n\t\t\ttopRight: 0,\n\t\t\tbottomRight: 0,\n\t\t\tbottomLeft: 0\n\t\t},\n\t\timageUseBorderRadius: false,\n\t\timageBorderColor: 'transparent',\n\t\timageBorderStyle: 'solid',\n\t\timageBorderWidth: 0,\n\t\timageHasLink: false,\n\t\timageHref: null,\n\t\tlayoutVariant: 1,\n\t\ttoHtmlOptions: {}\n\t};\n\n\tconst options = merge(\n\t\tCOMPONENTS_DEFAULTS,\n\t\tgetComponentsDefaultsByType(),\n\t\tdefaults,\n\t\tcomponentOptions\n\t);\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\tisCompound: true,\n\t\t\t\t...options,\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\talign: options.align,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: options.width\n\t\t\t\t},\n\t\t\t\timgSrc: options.useImagePlaceholderComponent\n\t\t\t\t\t? null\n\t\t\t\t\t: options.imgPh,\n\t\t\t\tlinksList: options.linksList.map(link => cloneDeep(link)),\n\t\t\t\t// TODO: document GrapesJS array issue\n\t\t\t\tlinksNormalLetterSpacing:\n\t\t\t\t\toptions.linksLetterSpacing === 'normal',\n\t\t\t\tcomponents: comp => comp.componentRender(comp),\n\t\t\t\ttraits(component) {\n\t\t\t\t\tconst result = [headerTrait()];\n\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t}),\n\n\t\t\tinit() {\n\t\t\t\tthis.setStyle({\n\t\t\t\t\t...this.getStyle(),\n\t\t\t\t\twidth: this.get('width')\n\t\t\t\t});\n\t\t\t},\n\n\t\t\ttoHTML(toHtmlOptions = {}) {\n\t\t\t\treturn toHtml(\n\t\t\t\t\tthis,\n\t\t\t\t\tmerge(options.toHtmlOptions, toHtmlOptions)\n\t\t\t\t);\n\t\t\t},\n\n\t\t\tsetAndRerender(attr, value) {\n\t\t\t\tthis.set(attr, value);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tsetNormalLetterSpacing(isNormal) {\n\t\t\t\tthis.set('linksNormalLetterSpacing', isNormal);\n\t\t\t},\n\n\t\t\tsetLetterSpacing(value) {\n\t\t\t\tthis.setNormalLetterSpacing(value === 'normal');\n\t\t\t\tthis.setAndRerender('linksLetterSpacing', value);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\taddLink(linkOptions) {\n\t\t\t\tconst newLink = {\n\t\t\t\t\t...this.get('newLink'),\n\t\t\t\t\t...linkOptions\n\t\t\t\t};\n\t\t\t\tthis.get('linksList').push(newLink);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\tif (typeof options.addLinkCallback === 'function')\n\t\t\t\t\toptions.addLinkCallback.call(this, this, newLink);\n\t\t\t\treturn newLink;\n\t\t\t},\n\n\t\t\tdeleteLink(item) {\n\t\t\t\tarrayRemove(this.get('linksList'), item);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\tif (typeof options.deleteLinkCallback === 'function')\n\t\t\t\t\toptions.deleteLinkCallback.call(this, this);\n\t\t\t},\n\n\t\t\tchangeLinksOrder(oldIndex, newIndex) {\n\t\t\t\tarrayMove(this.get('linksList'), oldIndex, newIndex);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tchangeLinkText(item, text, rerender = true) {\n\t\t\t\tthis.get('linksList').filter(link => {\n\t\t\t\t\treturn link === item;\n\t\t\t\t})[0].content = text;\n\t\t\t\tif (rerender) this.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tgetItemProp(item, prop) {\n\t\t\t\tconst _item = this.get('linksList').find(link => {\n\t\t\t\t\treturn link === item;\n\t\t\t\t});\n\t\t\t\treturn _item ? _item[prop] : null;\n\t\t\t},\n\n\t\t\tsetItemProp(item, prop, value, rerender = true) {\n\t\t\t\tconst _item = this.get('linksList').find(link => {\n\t\t\t\t\treturn link === item;\n\t\t\t\t});\n\t\t\t\tif (_item) _item[prop] = value;\n\t\t\t\telse console.warn('Item not found');\n\n\t\t\t\tif (rerender) this.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tchangeLinkUrl(item, url) {\n\t\t\t\tthis.get('linksList').filter(link => {\n\t\t\t\t\treturn link === item;\n\t\t\t\t})[0].href = url;\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tchangeLinksColor(color) {\n\t\t\t\tconst comp = this;\n\t\t\t\tcomp.set('linksColor', color);\n\t\t\t\tcomp.components(comp.componentRender(comp));\n\t\t\t},\n\n\t\t\tsetLinksBorderRadius(corner, value) {\n\t\t\t\tconst aux = {};\n\t\t\t\tif (\n\t\t\t\t\t[\n\t\t\t\t\t\t'topLeft',\n\t\t\t\t\t\t'topRight',\n\t\t\t\t\t\t'bottomLeft',\n\t\t\t\t\t\t'bottomRight'\n\t\t\t\t\t].includes(corner)\n\t\t\t\t) {\n\t\t\t\t\taux[corner] = value;\n\t\t\t\t\tthis.set('linksBorderRadius', {\n\t\t\t\t\t\t...this.get('linksBorderRadius'),\n\t\t\t\t\t\t...aux\n\t\t\t\t\t});\n\t\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\t} else {\n\t\t\t\t\tconst br = { ...this.get('linksBorderRadius') };\n\t\t\t\t\tfor (const key in br) {\n\t\t\t\t\t\tif (br.hasOwnProperty(key)) aux[key] = value;\n\t\t\t\t\t}\n\t\t\t\t\tthis.set('linksBorderRadius', { ...aux });\n\t\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tchangeLinkOpenMode(item, target) {\n\t\t\t\tthis.get('linksList').filter(link => {\n\t\t\t\t\treturn link === item;\n\t\t\t\t})[0].target = target;\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tchangeImageWidth(width) {\n\t\t\t\tthis.set('imageWidth', width);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tchangeLinksWidthToPercentage() {\n\t\t\t\tconst linksList = this.findType('links-list')[0];\n\t\t\t\tif (linksList) {\n\t\t\t\t\tconst linksListEl = linksList.getEl();\n\t\t\t\t\tif (linksListEl)\n\t\t\t\t\t\tthis.changeLinksListWidth(\n\t\t\t\t\t\t\tgetElementWidthPercentage(linksListEl)\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tchangeLinksListWidth(width) {\n\t\t\t\tthis.set('linksListWidth', width);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tchangeLinksGap(value) {\n\t\t\t\tthis.set('linksGap', value);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tchangeImage(file, callback) {\n\t\t\t\tconst comp = this;\n\t\t\t\tif (file instanceof File || file instanceof Blob) {\n\t\t\t\t\tfileReader(file, {\n\t\t\t\t\t\tcallbacks: {\n\t\t\t\t\t\t\tonload: result => {\n\t\t\t\t\t\t\t\tcomp.set('imgSrc', result.e.target.result);\n\t\t\t\t\t\t\t\tcomp.components(comp.componentRender(comp));\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdataRead:\n\t\t\t\t\t\t\t\ttypeof callback === 'function'\n\t\t\t\t\t\t\t\t\t? callback\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\tonError: console.error,\n\t\t\t\t\t\t\tonabort: console.log\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tcomp.set('imgSrc', file);\n\t\t\t\t\tcomp.components(comp.componentRender(comp));\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tremoveImage() {\n\t\t\t\tconst comp = this;\n\t\t\t\tcomp.set('imgSrc', '');\n\t\t\t\tcomp.components(comp.componentRender(comp));\n\t\t\t},\n\n\t\t\tsetImageBorderRadius(corner, value) {\n\t\t\t\tconst aux = {};\n\t\t\t\tif (\n\t\t\t\t\t[\n\t\t\t\t\t\t'topLeft',\n\t\t\t\t\t\t'topRight',\n\t\t\t\t\t\t'bottomLeft',\n\t\t\t\t\t\t'bottomRight'\n\t\t\t\t\t].includes(corner)\n\t\t\t\t) {\n\t\t\t\t\taux[corner] = value;\n\t\t\t\t\tthis.set('imageBorderRadius', {\n\t\t\t\t\t\t...this.get('imageBorderRadius'),\n\t\t\t\t\t\t...aux\n\t\t\t\t\t});\n\t\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\t} else {\n\t\t\t\t\tconst br = { ...this.get('imageBorderRadius') };\n\t\t\t\t\tfor (const key in br) {\n\t\t\t\t\t\tif (br.hasOwnProperty(key)) aux[key] = value;\n\t\t\t\t\t}\n\t\t\t\t\tthis.set('imageBorderRadius', { ...aux });\n\t\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\t}\n\t\t\t},\n\n\t\t\thideImage() {\n\t\t\t\tthis.set('displayImage', false);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tshowImage() {\n\t\t\t\tthis.set('displayImage', true);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\ttoggleImage() {\n\t\t\t\tthis.set('displayImage', !this.get('displayImage'));\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\thideLinks() {\n\t\t\t\tthis.set('displayLinks', false);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tshowLinks() {\n\t\t\t\tthis.set('displayLinks', true);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\ttoggleLinksDisplay() {\n\t\t\t\tthis.set('displayLinks', !this.get('displayLinks'));\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tcomponentRender: render,\n\t\t\t...baseMethods(componentOptions, editor)\n\t\t}\n\t};\n};\n","import { noInteractionPreset } from '../_componentsUtils';\nimport { validateStyleObj } from '../../common/functions/_utilFunctions';\n\nexport default comp => {\n\tcomp.setStyle({\n\t\twidth: comp.get('listWidth')\n\t});\n\n\tcomp.addAttributes({ align: comp.get('listAlign') });\n\n\tconst cells = [];\n\n\tcomp.attributes.linksList.forEach((link, index, arr) => {\n\t\tconst style = validateStyleObj({\n\t\t\tbackground: comp.get('linksBackground'),\n\t\t\t'border-color': comp.get('linksBorderColor'),\n\t\t\t'border-style': comp.get('linksBorderStyle'),\n\t\t\t'border-width': comp.get('linksBorderWidth'),\n\t\t\t'border-radius': comp.get('linksBorderRadius')\n\t\t\t\t? Object.values(comp.get('linksBorderRadius')).join(' ')\n\t\t\t\t: ''\n\t\t\t// TODO: delete when footer would be updated with this props\n\t\t});\n\n\t\tconst cell = {\n\t\t\ttype: 'cell',\n\t\t\tstyle,\n\t\t\tcomponents: {\n\t\t\t\ttype: !comp.get('isTextList') ? 'link' : 'text',\n\t\t\t\tstyle: validateStyleObj({\n\t\t\t\t\tcolor: comp.get('linksColor'),\n\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t'font-weight': comp.get('linksWeight'),\n\t\t\t\t\tpadding: comp.get('linksHasMargins')\n\t\t\t\t\t\t? `${comp.get('linksTopMargin')} ${comp.get(\n\t\t\t\t\t\t\t\t'linksRightMargin'\n\t\t\t\t\t\t )} ${comp.get('linksBottomMargin')} ${comp.get(\n\t\t\t\t\t\t\t\t'linksLeftMargin'\n\t\t\t\t\t\t )}`\n\t\t\t\t\t\t: '0'\n\t\t\t\t}),\n\t\t\t\tattributes: !comp.get('isTextList')\n\t\t\t\t\t? {\n\t\t\t\t\t\t\thref: link.href,\n\t\t\t\t\t\t\tclass: comp.attributes.cssClass + '__link',\n\t\t\t\t\t\t\ttarget: link.target || '_blank'\n\t\t\t\t\t }\n\t\t\t\t\t: null\n\t\t\t},\n\t\t\tattributes: {\n\t\t\t\talign: comp.attributes.linksAlignment,\n\t\t\t\tclass: comp.attributes.cssClass + '__link-container'\n\t\t\t}\n\t\t};\n\n\t\tif (typeof link.content === 'object') {\n\t\t\tcell.components.components = link.content;\n\t\t} else if (comp.get('isTextList')) {\n\t\t\tcell.components.text = link.content;\n\t\t} else {\n\t\t\tcell.components.content = link.content;\n\t\t}\n\n\t\tcells.push(cell);\n\n\t\tif (index < arr.length - 1 && parseInt(comp.attributes.gap) > 0)\n\t\t\tcells.push({\n\t\t\t\ttype: 'cell',\n\t\t\t\tattributes: {\n\t\t\t\t\tclass: comp.attributes.cssClass + '__gap'\n\t\t\t\t},\n\t\t\t\tstyle: validateStyleObj({\n\t\t\t\t\twidth: comp.attributes.gap\n\t\t\t\t})\n\t\t\t});\n\t});\n\n\treturn {\n\t\ttype: 'row',\n\t\tcomponents: cells,\n\t\tstyle: validateStyleObj({\n\t\t\t'font-family': comp.get('linksFont'),\n\t\t\t'letter-spacing': comp.get('linksLetterSpacing')\n\t\t}),\n\t\t...noInteractionPreset\n\t};\n};\n","import { validateStyleObj } from '../../common/functions/_utilFunctions';\n\nexport default comp => {\n\treturn validateStyleObj({\n\t\twidth: comp.get('width')\n\t});\n};\n","import { merge, cssStyleObjectToString } from 'datatalks-utils';\n\nimport getComputedStyle from './_getComputedStyle';\nimport margins from '../common/htmlTemplates/_margins';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tparentWidth: null,\n\t\tstyle: getComputedStyle(comp)\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst listWidth = comp.get('listWidth') || 'auto';\n\tconst nColumns = comp.get('linksList')?.length;\n\tconst align = comp.get('listAlign') || 'center';\n\tconst colPadding = comp.get('linksHasMargins')\n\t\t? `padding-left: ${comp.get(\n\t\t\t\t'linksLeftMargin'\n\t\t )}; padding-right: ${comp.get(\n\t\t\t\t'linksRightMargin'\n\t\t )}; padding-bottom: ${comp.get(\n\t\t\t\t'linksBottomMargin'\n\t\t )}; padding-top: ${comp.get('linksTopMargin')};`\n\t\t: '';\n\tconst gap = parseFloat(comp.get('gap'));\n\tconst linksBackground = comp.get('linksBackground');\n\tconst isWrapable = comp.get('isWrapable');\n\n\t/**\n\t * Calculates the width of the list item based on the parent width, provided options and number of columns.\n\t * @param {boolean} isWrapper - Whether it should calculate list's width or texts' width.\n\t * @return {number} The width of the parent element.\n\t */\n\tfunction getParentWidth(isWrapper = false) {\n\t\treturn (\n\t\t\t(parseFloat(options.parentWidth) - gap * (nColumns - 1)) /\n\t\t\t\tnColumns -\n\t\t\t(comp.get('linksHasMargins') && !isWrapper\n\t\t\t\t? parseFloat(comp.get('linksLeftMargin')) +\n\t\t\t\t parseFloat(comp.get('linksRightMargin'))\n\t\t\t\t: 0)\n\t\t);\n\t}\n\n\tconst tableHtml = `\n\t\t\n\t\t\t\n\t\t\t\t${comp\n\t\t\t\t\t.get('linksList')\n\t\t\t\t\t.map(\n\t\t\t\t\t\t(item, index) =>\n\t\t\t\t\t\t\t`${\n\t\t\t\t\t\t\t\tindex != 0\n\t\t\t\t\t\t\t\t\t? ``\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t`\n\t\t\t\t\t)\n\t\t\t\t\t.join('')}\n\n\t\t\n\t
\n\t\t\t\t\t\t\t\t${comp.findType(!comp.get('isTextList') ? 'link' : 'text')[index].toHTML({\n\t\t\t\t\t\t\t\t\tparentWidth: `${getParentWidth()}px`,\n\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\tdisplay: 'inline-block'\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t
`;\n\n\tconst innerHtml = isWrapable\n\t\t? `\n\t\t
\n\t\t\t\n\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t${comp.findType(!comp.get('isTextList') ? 'link' : 'text')[index].toHTML({\n\t\t\t\t\t\t\t\t\t\t\t\t\tparentWidth: `${getParentWidth()}px`,\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: 'inline-block'\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\n\t\t
\n\t`\n\t\t: tableHtml;\n\n\tconst html = margins(innerHtml, {\n\t\ttopMargin: comp.get('topMargin') || 0,\n\t\trightMargin: comp.get('rightMargin') || 0,\n\t\tbottomMargin: comp.get('bottomMargin') || 0,\n\t\tleftMargin: comp.get('leftMargin') || 0,\n\t\thasMargins: comp.get('hasMargins'),\n\t\tbackgroundColor: comp.get('backgroundColor')\n\t});\n\n\tif (options.debug)\n\t\tconsole.log('List HTML: ', comp.get('hasMargins') ? html : innerHtml);\n\n\treturn comp.get('hasMargins') ? html : innerHtml;\n};\n","import { merge } from 'datatalks-utils';\n\nimport { COMPONENTS_DEFAULTS } from '../../../config/_config';\nimport render from './_render';\nimport { getComponentsDefaultsByType } from '../../componentsDefaults/_componentsDefaults';\nimport toHtml from './_toHtml';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst defaults = getComponentsDefaultsByType('links-list');\n\n\tconst options = {\n\t\t...COMPONENTS_DEFAULTS,\n\t\t...defaults,\n\t\t...componentOptions\n\t};\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\t...options,\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tcomponents: comp => comp.componentRender(comp)\n\t\t\t}),\n\n\t\t\ttoHTML(toHtmlOpts = {}) {\n\t\t\t\treturn toHtml(this, merge(options.toHtmlOptions, toHtmlOpts));\n\t\t\t},\n\n\t\t\tcomponentRender: render\n\t\t}\n\t};\n};\n","/**\n * The object containing the options to configure the hero trait\n * @typedef { Object } HeroTraitOptions\n * @property { string } cssClass - The base class to apply to the wrapper container of the hero trait.\n * @property { string } extendedClasses - Other classes to apply to the wrapper container of the hero trait (i.e. utility classes).\n * @property { boolean } hasImageWidthSlider - Wether or not to have a range slider that changes image's width.\n */\n\n/**\n * Creates a trait of the type 'hero' configured with the passed options\n * @param {HeroTraitOptions} options - The options to configure the hero trait.\n */\n\nexport default (options = {}) => {\n\treturn {\n\t\ttype: 'hero',\n\t\toptions\n\t};\n};\n","import { validateStyleObj } from '../../common/functions/_utilFunctions';\nimport {\n\tnoInteractionPreset,\n\taddSpace as _addSpace\n} from '../_componentsUtils';\nimport updateStyle from '../common/_updateCommonStyle';\n\nexport default comp => {\n\tconst innerComponents = [];\n\tconst addSpace = _addSpace.bind(null, comp, true, innerComponents);\n\n\tif (comp.get('displayImage')) {\n\t\tconst image = {\n\t\t\ttype: 'image-wrapper',\n\t\t\timgSrc: comp.attributes.imgSrc,\n\t\t\tuseBorderRadius: comp.get('imageUseBorderRadius'),\n\t\t\tborderRadius: comp.get('imageBorderRadius'),\n\t\t\tborderColor: comp.get('imageBorderColor'),\n\t\t\tborderStyle: comp.get('imageBorderStyle'),\n\t\t\tborderWidth: comp.get('imageBorderWidth'),\n\t\t\timgWidth: comp.attributes.imageWidth,\n\t\t\thref: comp.get('imageHref'),\n\t\t\thasLink: comp.get('imageHasLink')\n\t\t};\n\n\t\tinnerComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tattributes: {\n\t\t\t\t\talign: comp.attributes.imageAlignment\n\t\t\t\t},\n\t\t\t\tcomponents: image\n\t\t\t},\n\t\t\t...noInteractionPreset\n\t\t});\n\t}\n\n\tif (comp.get('displayTitle')) {\n\t\tif (innerComponents.length) addSpace();\n\t\tinnerComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tstyle: {\n\t\t\t\t\t'text-align': comp.get('headingAlignment')\n\t\t\t\t},\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tstyle: validateStyleObj(comp.get('headingStyle')),\n\t\t\t\t\ttext: comp.attributes.title\n\t\t\t\t}\n\t\t\t},\n\t\t\t...noInteractionPreset\n\t\t});\n\t}\n\n\tif (comp.get('displayText')) {\n\t\tif (innerComponents.length) addSpace();\n\t\tinnerComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tstyle: {\n\t\t\t\t\t'text-align': comp.get('textAlignment')\n\t\t\t\t},\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tstyle: validateStyleObj(comp.get('textStyle')),\n\t\t\t\t\ttext: comp.attributes.textContent\n\t\t\t\t}\n\t\t\t},\n\t\t\t...noInteractionPreset\n\t\t});\n\t}\n\n\tif (comp.get('displayButton')) {\n\t\tif (innerComponents.length) addSpace();\n\t\tinnerComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tattributes: {\n\t\t\t\t\talign: comp.get('buttonAlignment')\n\t\t\t\t},\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'button',\n\t\t\t\t\tbackgroundColor: comp.get('buttonBackgroundColor'),\n\t\t\t\t\theight: comp.get('buttonHeight'),\n\t\t\t\t\twidth: comp.get('buttonWidth'),\n\t\t\t\t\tfontFamily: comp.get('buttonFontFamily'),\n\t\t\t\t\tfontSize: comp.get('buttonFontSize'),\n\t\t\t\t\tfontStyle: comp.get('buttonFontStyle'),\n\t\t\t\t\tcolor: comp.get('buttonColor'),\n\t\t\t\t\tfontWeight: comp.get('buttonFontWeight'),\n\t\t\t\t\tborderWidth: comp.get('buttonBorderWidth'),\n\t\t\t\t\tborderStyle: comp.get('buttonBorderStyle'),\n\t\t\t\t\tborderColor: comp.get('buttonBorderColor'),\n\t\t\t\t\tborderRadius: comp.get('buttonBorderRadius'),\n\t\t\t\t\tuseBorderRadius: comp.get('buttonUseBorderRadius'),\n\t\t\t\t\thref: comp.get('buttonHref'),\n\t\t\t\t\threfState: comp.get('buttonHrefState'),\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\t'letter-spacing': comp.get('buttonLetterSpacing')\n\t\t\t\t\t},\n\t\t\t\t\ttext: comp.attributes.buttonText,\n\t\t\t\t\tlineHeight: comp.get('buttonLineHeight'),\n\t\t\t\t\ttextAlignment: comp.get('buttonTextAlignment'),\n\t\t\t\t\ttextDecorationLine: comp.get('buttonTextDecorationLine')\n\t\t\t\t}\n\t\t\t},\n\t\t\t...noInteractionPreset\n\t\t});\n\t}\n\n\tupdateStyle(comp);\n\n\treturn [\n\t\t{\n\t\t\ttype: 'margins',\n\t\t\tinnerComponents,\n\t\t\thasMargins: comp.get('hasMargins'),\n\t\t\tmargins: {\n\t\t\t\ttop: comp.get('topMargin'),\n\t\t\t\tright: comp.get('rightMargin'),\n\t\t\t\tbottom: comp.get('bottomMargin'),\n\t\t\t\tleft: comp.get('leftMargin')\n\t\t\t},\n\t\t\tmarginsColor: {\n\t\t\t\ttop: comp.get('topMarginColor'),\n\t\t\t\tright: comp.get('rightMarginColor'),\n\t\t\t\tbottom: comp.get('bottomMarginColor'),\n\t\t\t\tleft: comp.get('leftMarginColor')\n\t\t\t}\n\t\t}\n\t];\n};\n","import { validateStyleObj } from '../../common/functions/_utilFunctions';\n\nexport default comp => {\n\tconst getGeneralStyle = comp\n\t\t.getEditor()\n\t\t.getStyleRules.bind(comp.getEditor(), 'component');\n\n\tconst borderRadius = comp.get('useBorderRadius')\n\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t: [\n\t\t\t\tgetGeneralStyle('border-top-left-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-top-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-left-radius') || 0\n\t\t ].join(' ');\n\n\treturn validateStyleObj({\n\t\t'background-color':\n\t\t\tcomp.get('backgroundColor') || getGeneralStyle('background-color'),\n\t\twidth: comp.get('width'),\n\t\t'border-radius': borderRadius\n\t});\n};\n","import {\n\tmerge,\n\tcssStyleObjectToString,\n\tinsertAfterEveryItem\n} from 'datatalks-utils';\n\nimport getComputedStyle from './_getComputedStyle';\nimport margins from '../common/htmlTemplates/_margins';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tparentWidth: null,\n\t\tstyle: getComputedStyle(comp),\n\t\timageWidth: comp.get('imageWidth'),\n\t\tspace: comp.get('spacingBetweenElements')\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst debugStrStart = options.debug ? 'data-eb-name=\"hero-first\"' : '';\n\tconst debugStrEnd = options.debug ? 'data-eb-name=\"hero-last\"' : '';\n\n\tconst marginsWidth = comp.get('hasMargins')\n\t\t? parseFloat(comp.get('leftMargin')) +\n\t\t parseFloat(comp.get('rightMargin')) +\n\t\t 'px'\n\t\t: 0;\n\n\tconst textIndex = comp.get('displayTitle') ? 1 : 0;\n\n\t/**\n\t * Retrieves the HTML representation of a specific element based on its name.\n\t *\n\t * @param {string} name - The name of the element to retrieve.\n\t * @return {string} The HTML representation of the element.\n\t */\n\tfunction getElement(name) {\n\t\tconst parentWidth = `${\n\t\t\tparseFloat(options.parentWidth) - parseFloat(marginsWidth)\n\t\t}px`;\n\t\tswitch (name) {\n\t\t\tcase 'image':\n\t\t\t\treturn comp\n\t\t\t\t\t.findType('image-wrapper')[0]\n\t\t\t\t\t.toHTML({ parentWidth });\n\t\t\t\tbreak;\n\n\t\t\tcase 'title':\n\t\t\t\treturn comp.findType('text')[0].toHTML({ parentWidth });\n\t\t\t\tbreak;\n\n\t\t\tcase 'text':\n\t\t\t\treturn comp.findType('text')[textIndex].toHTML({ parentWidth });\n\t\t\t\tbreak;\n\n\t\t\tcase 'button':\n\t\t\t\treturn comp.findType('button')[0].toHTML({ parentWidth });\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tconsole.warn('Invalid element name: ', name);\n\t\t\t\treturn '';\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Generates an HTML table row with the provided content.\n\t *\n\t * @param {string} content - The content to be placed inside the table cell.\n\t * @param {boolean} shouldRender - Determines whether the row should be rendered or not.\n\t * @param {object} rowOptions - Additional options for the row.\n\t * @return {string} - The generated HTML table row.\n\t */\n\tfunction row(content, shouldRender, rowOptions = {}) {\n\t\tconst defaults = {\n\t\t\talign: 'center'\n\t\t};\n\n\t\trowOptions = merge(defaults, rowOptions);\n\n\t\tif (shouldRender) {\n\t\t\tcontent = typeof content === 'function' ? content() : content;\n\t\t\treturn `\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t${content}\n\t\t\t\t\t\n\t\t\t\t`;\n\t\t} else return '';\n\t}\n\n\tconst space = `\n\t\t\n\t\t\t\n\t\t`;\n\n\tconst imageRow = row(\n\t\tgetElement.bind(null, 'image'),\n\t\tcomp.get('displayImage'),\n\t\t{\n\t\t\talign: comp.get('imageAlignment')\n\t\t}\n\t);\n\n\tconst titleRow = row(\n\t\tgetElement.bind(null, 'title'),\n\t\tcomp.get('displayTitle'),\n\t\t{\n\t\t\talign: comp.get('titleAlignment')\n\t\t}\n\t);\n\n\tconst textRow = row(\n\t\tgetElement.bind(null, 'text'),\n\t\tcomp.get('displayText'),\n\t\t{\n\t\t\talign: comp.get('textAlignment')\n\t\t}\n\t);\n\n\tconst buttonRow = row(\n\t\tgetElement.bind(null, 'button'),\n\t\tcomp.get('displayButton'),\n\t\t{\n\t\t\talign: comp.get('buttonAlignment')\n\t\t}\n\t);\n\n\tconst rows = insertAfterEveryItem(\n\t\t[imageRow, titleRow, textRow, buttonRow].filter(row => !!row),\n\t\tspace\n\t).join(' ');\n\n\tconst innerHtml = `\n\t\t\n\t\t\t${rows}\n\t\t
\n\t`;\n\n\tconst html = margins(innerHtml, {\n\t\ttopMargin: comp.get('topMargin') || 0,\n\t\trightMargin: comp.get('rightMargin') || 0,\n\t\tbottomMargin: comp.get('bottomMargin') || 0,\n\t\tleftMargin: comp.get('leftMargin') || 0,\n\t\thasMargins: comp.get('hasMargins'),\n\t\tbackgroundColor: comp.get('backgroundColor')\n\t});\n\n\tif (options.debug)\n\t\tconsole.log('List HTML: ', comp.get('hasMargins') ? html : innerHtml);\n\n\treturn comp.get('hasMargins') ? html : innerHtml;\n};\n","import { COMPONENTS_DEFAULTS } from '../../../config/_config';\nimport { fileReader, merge } from 'datatalks-utils';\nimport heroTrait from './trait/_trait';\nimport render from './_render';\nimport baseMethods from '../common/methods/_baseMethods';\nimport { getComponentsDefaultsByType } from '../../componentsDefaults/_componentsDefaults';\nimport toHtml from './_toHtml';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = {\n\t\tattributes: {},\n\t\tspacingBetweenElements: '12px',\n\t\tcssClass: 'gjs-comp-hero',\n\t\twidth: '100%',\n\t\ttitlePh: 'Simple informing headline',\n\t\theadingStyle: {\n\t\t\tcolor: null\n\t\t},\n\t\theadingAlignment: 'left',\n\t\ttextContentPh:\n\t\t\t'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultrices tempor porta. Maecenas eu libero at nunc pulvinar fermentum et convallis elit. In et nisi lacus. Morbi mauris metus, imperdiet pharetra efficitur sit amet, hendrerit et neque. Etiam nec vestibulum sem. Etiam condimentum eros in feugiat finibus. Quisque eget mollis velit. Maecenas tempus placerat arcu, id molestie mauris fermentum at. Phasellus vel tellus feugiat urna interdum posuere. Integer eu sodales urna. Nam metus leo, consectetur id neque imperdiet, vulputate dictum erat. Cras tristique, tortor a viverra ultricies, nulla enim faucibus tellus, non vestibulum diam eros ut orci.',\n\t\ttextStyle: {\n\t\t\tcolor: null\n\t\t},\n\t\ttextAlignment: 'left',\n\t\tname: 'Hero',\n\t\tdisplayTitle: true,\n\t\tdisplayText: true,\n\t\tdisplayButton: true,\n\t\tbuttonPh: 'Button text',\n\t\tbuttonBackgroundColor: null,\n\t\tbuttonHeight: null,\n\t\tbuttonWidth: '100%',\n\t\tbuttonFontFamily: null,\n\t\tbuttonFontSize: null,\n\t\tbuttonFontStyle: 'normal',\n\t\tbuttonColor: null,\n\t\tbuttonFontWeight: null,\n\t\tbuttonBorderWidth: '0px',\n\t\tbuttonBorderStyle: 'solid',\n\t\tbuttonBorderColor: 'transparent',\n\t\tbuttonAlignment: 'center',\n\t\tbuttonBorderRadius: {\n\t\t\ttopLeft: 0,\n\t\t\ttopRight: 0,\n\t\t\tbottomRight: 0,\n\t\t\tbottomLeft: 0\n\t\t},\n\t\tbuttonLineHeight: null,\n\t\tbuttonUseBorderRadius: false,\n\t\tbuttonLetterSpacing: 'normal',\n\t\tbuttonNormalLetterSpacing: true,\n\t\tbuttonDefaultLetterSpacingLength: '0.1em',\n\t\tbuttonHasOutlookBorderRadius: false,\n\t\tbuttonOutlookWidth: '150px',\n\t\tbuttonTextDecorationLine: null,\n\t\tdisplayImage: true,\n\t\timgPh: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIHZpZXdCb3g9IjAgMCAyNCAyNCIgc3R5bGU9ImZpbGw6IHJnYmEoMCwwLDAsMC4xNSk7IHRyYW5zZm9ybTogc2NhbGUoMC43NSkiPgogICAgICAgIDxwYXRoIGQ9Ik04LjUgMTMuNWwyLjUgMyAzLjUtNC41IDQuNSA2SDVtMTYgMVY1YTIgMiAwIDAgMC0yLTJINWMtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxNGMxLjEgMCAyLS45IDItMnoiPjwvcGF0aD4KICAgICAgPC9zdmc+',\n\t\timageWidth: '100%',\n\t\timageAlignment: 'center',\n\t\timageBorderRadius: {\n\t\t\ttopLeft: 0,\n\t\t\ttopRight: 0,\n\t\t\tbottomRight: 0,\n\t\t\tbottomLeft: 0\n\t\t},\n\t\timageUseBorderRadius: false,\n\t\timageBorderColor: 'transparent',\n\t\timageBorderStyle: 'solid',\n\t\timageBorderWidth: 0,\n\t\timageHasLink: false,\n\t\timageHref: null,\n\t\ttoHtmlOptions: {}\n\t};\n\n\tconst options = merge(\n\t\tCOMPONENTS_DEFAULTS,\n\t\tgetComponentsDefaultsByType(),\n\t\tdefaults,\n\t\tcomponentOptions\n\t);\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\tisCompound: true,\n\t\t\t\t...options,\n\t\t\t\tname: options.name,\n\t\t\t\ttagName: 'table',\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: options.width\n\t\t\t\t},\n\t\t\t\tdisplayImage: options.displayImage,\n\t\t\t\timgSrc: options.imgPh,\n\t\t\t\timageAlignment: options.imageAlignment,\n\t\t\t\timageWidth: options.imageWidth,\n\t\t\t\tbuttonLetterSpacing: options.buttonLetterSpacing,\n\t\t\t\tbuttonNormalLetterSpacing:\n\t\t\t\t\toptions.buttonLetterSpacing === 'normal',\n\t\t\t\tbuttonDefaultLetterSpacingLength:\n\t\t\t\t\toptions.buttonDefaultLetterSpacingLength,\n\t\t\t\timageBorderRadius: options.imageBorderRadius,\n\t\t\t\timageBorderColor: options.imageBorderColor,\n\t\t\t\timageBorderStyle: options.imageBorderStyle,\n\t\t\t\timageBorderWidth: options.imageBorderWidth,\n\t\t\t\tdisplayTitle: options.displayTitle,\n\t\t\t\ttitle: `

${options.titlePh}

`,\n\t\t\t\tdisplayText: options.displayText,\n\t\t\t\ttextContent: `

${options.textContentPh}

`,\n\t\t\t\tdisplayButton: options.displayButton,\n\t\t\t\tbuttonText: options.buttonPh,\n\t\t\t\tcomponents: comp => comp.componentRender(comp),\n\t\t\t\ttraits(component) {\n\t\t\t\t\tconst result = [\n\t\t\t\t\t\theroTrait({\n\t\t\t\t\t\t\thasImageWidthSlider: true\n\t\t\t\t\t\t})\n\t\t\t\t\t];\n\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t}),\n\n\t\t\tinit() {\n\t\t\t\tthis.setStyle({\n\t\t\t\t\t...this.getStyle(),\n\t\t\t\t\twidth: this.get('width')\n\t\t\t\t});\n\t\t\t},\n\n\t\t\ttoHTML(toHtmlOpts = {}) {\n\t\t\t\treturn toHtml(this, merge(options.toHtmlOptions, toHtmlOpts));\n\t\t\t},\n\n\t\t\tsetNormalLetterSpacing(isNormal) {\n\t\t\t\tthis.set('buttonNormalLetterSpacing', isNormal);\n\t\t\t},\n\n\t\t\tsetLetterSpacing(value) {\n\t\t\t\tthis.setNormalLetterSpacing(value === 'normal');\n\t\t\t\tthis.setAndRerender('buttonLetterSpacing', value);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tsetAndRerender(prop, value) {\n\t\t\t\tthis.set(prop, value);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\trerender() {\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tchangeImageWidth(width) {\n\t\t\t\tthis.set('imageWidth', width);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tchangeImage(file, callback) {\n\t\t\t\tconst comp = this;\n\t\t\t\tif (file instanceof File || file instanceof Blob) {\n\t\t\t\t\tfileReader(file, {\n\t\t\t\t\t\tcallbacks: {\n\t\t\t\t\t\t\tonload: result => {\n\t\t\t\t\t\t\t\tcomp.set('imgSrc', result.e.target.result);\n\t\t\t\t\t\t\t\tcomp.components(comp.componentRender(comp));\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdataRead:\n\t\t\t\t\t\t\t\ttypeof callback === 'function'\n\t\t\t\t\t\t\t\t\t? callback\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\tonError: console.error,\n\t\t\t\t\t\t\tonabort: console.log\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tcomp.set('imgSrc', file);\n\t\t\t\t\tcomp.components(comp.componentRender(comp));\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tremoveImage() {\n\t\t\t\tconst comp = this;\n\t\t\t\tcomp.set('imgSrc', '');\n\t\t\t\tcomp.components(comp.componentRender(comp));\n\t\t\t},\n\n\t\t\ttoggleImage() {\n\t\t\t\tthis.set('displayImage', !this.get('displayImage'));\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tsetImageBorderRadius(corner, value) {\n\t\t\t\tconst aux = {};\n\t\t\t\tif (\n\t\t\t\t\t[\n\t\t\t\t\t\t'topLeft',\n\t\t\t\t\t\t'topRight',\n\t\t\t\t\t\t'bottomLeft',\n\t\t\t\t\t\t'bottomRight'\n\t\t\t\t\t].includes(corner)\n\t\t\t\t) {\n\t\t\t\t\taux[corner] = value;\n\t\t\t\t\tthis.set('imageBorderRadius', {\n\t\t\t\t\t\t...this.get('imageBorderRadius'),\n\t\t\t\t\t\t...aux\n\t\t\t\t\t});\n\t\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\t} else {\n\t\t\t\t\tconst br = { ...this.get('imageBorderRadius') };\n\t\t\t\t\tfor (const key in br) {\n\t\t\t\t\t\tif (br.hasOwnProperty(key)) aux[key] = value;\n\t\t\t\t\t}\n\t\t\t\t\tthis.set('imageBorderRadius', { ...aux });\n\t\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tcomponentRender: render,\n\t\t\t...baseMethods(componentOptions, editor)\n\t\t}\n\t};\n};\n","/* eslint-disable require-jsdoc */\nimport { addSpace as _addSpace } from '../_componentsUtils';\nimport { validateStyleObj } from '../../common/functions/_utilFunctions';\nimport updateStyle from '../common/_updateCommonStyle';\n\nexport default comp => {\n\tlet innerComponents = [];\n\tconst addSpace = _addSpace.bind(null, comp, true, innerComponents);\n\n\tif (comp.get('displayTitle')) {\n\t\tinnerComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\tattributes: {\n\t\t\t\t\talign: comp.get('titleAlignment')\n\t\t\t\t},\n\t\t\t\tstyle: validateStyleObj(comp.get('titleStyle')),\n\t\t\t\ttype: 'cell',\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\ttext: comp.attributes.title\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tif (comp.get('displayDescription')) {\n\t\tif (innerComponents.length) addSpace();\n\t\tinnerComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\tattributes: {\n\t\t\t\t\talign: comp.get('descriptionAlignment')\n\t\t\t\t},\n\t\t\t\tstyle: validateStyleObj(comp.get('descriptionStyle')),\n\t\t\t\ttype: 'cell',\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\ttext: comp.attributes.description\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tconst socialListGapAndMargins = comp.get('socialListIsWrapable')\n\t\t? {\n\t\t\t\tlinksHasMargins: true,\n\t\t\t\tgap: '0px',\n\t\t\t\tlinksLeftMargin:\n\t\t\t\t\tparseFloat(comp.get('socialListGap')) / 2 + 'px',\n\t\t\t\tlinksRightMargin:\n\t\t\t\t\tparseFloat(comp.get('socialListGap')) / 2 + 'px',\n\t\t\t\tlinksTopMargin:\n\t\t\t\t\tparseFloat(comp.get('socialListGap')) / 2 + 'px',\n\t\t\t\tlinksBottomMargin:\n\t\t\t\t\tparseFloat(comp.get('socialListGap')) / 2 + 'px'\n\t\t }\n\t\t: { linksHasMargins: false, gap: comp.get('socialListGap') };\n\n\tif (comp.get('displaySocialList') && !comp.get('socialListSideways')) {\n\t\tif (innerComponents.length) addSpace();\n\t\tinnerComponents.push({\n\t\t\ttype: 'row',\n\t\t\tattributes: {\n\t\t\t\talign: 'center'\n\t\t\t},\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'links-list',\n\t\t\t\t\tlinksList: comp.attributes.socialList,\n\t\t\t\t\tlistWidth: comp.attributes.linksListWidth,\n\t\t\t\t\tlistAlign: comp.get('socialListAlignment'),\n\t\t\t\t\tisWrapable: comp.get('socialListIsWrapable'),\n\t\t\t\t\t...socialListGapAndMargins\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tif (comp.get('displayLinks')) {\n\t\tif (innerComponents.length) addSpace();\n\t\tinnerComponents.push({\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tattributes: {\n\t\t\t\t\talign: comp.get('linksAlignment')\n\t\t\t\t},\n\t\t\t\tcomponents: {\n\t\t\t\t\ttype: 'table',\n\t\t\t\t\tstyle: validateStyleObj({\n\t\t\t\t\t\t'border-collapse': 'separate',\n\t\t\t\t\t\t'background-color': comp.attributes.linksBackground,\n\t\t\t\t\t\t'border-radius': `${Object.values(\n\t\t\t\t\t\t\tcomp.attributes.linksBorderRadius\n\t\t\t\t\t\t).join(' ')}`,\n\t\t\t\t\t\t'border-color': comp.attributes.linksBorderColor,\n\t\t\t\t\t\t'border-style': comp.attributes.linksBorderStyle,\n\t\t\t\t\t\t'border-width': comp.attributes.linksBorderWidth,\n\t\t\t\t\t\twidth: comp.attributes.linksWidth\n\t\t\t\t\t}),\n\t\t\t\t\tcomponents: {\n\t\t\t\t\t\ttype: 'row',\n\t\t\t\t\t\tcomponents: {\n\t\t\t\t\t\t\ttype: 'cell',\n\t\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\t\talign: 'left'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tstyle: validateStyleObj({\n\t\t\t\t\t\t\t\t...comp.get('linksStyle')\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tcomponents: {\n\t\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\t\ttext: comp.attributes.links\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tconst getListWidth = () =>\n\t\t(parseFloat(comp.get('iconWidth')) +\n\t\t\tparseFloat(comp.get('socialListRightMargin')) +\n\t\t\tparseFloat(comp.get('socialListLeftMargin'))) *\n\t\t\tcomp.get('socialList').length +\n\t\tparseFloat(comp.get('socialListGap')) *\n\t\t\t(comp.get('socialList').length - 1) +\n\t\t'px';\n\n\tif (comp.get('displaySocialList') && comp.get('socialListSideways')) {\n\t\tinnerComponents = [\n\t\t\t{\n\t\t\t\ttype: 'row',\n\t\t\t\tcomponents: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'cell',\n\t\t\t\t\t\tcomponents: {\n\t\t\t\t\t\t\ttype: 'table',\n\t\t\t\t\t\t\tcomponents: innerComponents\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'space',\n\t\t\t\t\t\tisVertical: false,\n\t\t\t\t\t\tdimension: comp.get('horizontalSpacingBetweenElements')\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'cell',\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t'vertical-align': comp.get('socialListVAlignment'),\n\t\t\t\t\t\t\twidth:\n\t\t\t\t\t\t\t\tcomp.attributes.linksListWidth === 'auto'\n\t\t\t\t\t\t\t\t\t? getListWidth()\n\t\t\t\t\t\t\t\t\t: comp.attributes.linksListWidth\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcomponents: {\n\t\t\t\t\t\t\ttype: 'links-list',\n\t\t\t\t\t\t\tlinksList: comp.attributes.socialList,\n\t\t\t\t\t\t\tisWrapable: comp.get('socialListIsWrapable'),\n\t\t\t\t\t\t\tlistWidth: '100%',\n\t\t\t\t\t\t\tlistAlign: comp.get('socialListAlignment'),\n\t\t\t\t\t\t\t...socialListGapAndMargins\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t];\n\t}\n\n\tupdateStyle(comp);\n\n\treturn [\n\t\t{\n\t\t\ttype: 'margins',\n\t\t\tinnerComponents,\n\t\t\thasMargins: comp.get('hasMargins'),\n\t\t\tmargins: {\n\t\t\t\ttop: comp.get('topMargin'),\n\t\t\t\tright: comp.get('rightMargin'),\n\t\t\t\tbottom: comp.get('bottomMargin'),\n\t\t\t\tleft: comp.get('leftMargin')\n\t\t\t},\n\t\t\tmarginsColor: {\n\t\t\t\ttop: comp.get('topMarginColor'),\n\t\t\t\tright: comp.get('rightMarginColor'),\n\t\t\t\tbottom: comp.get('bottomMarginColor'),\n\t\t\t\tleft: comp.get('leftMarginColor')\n\t\t\t}\n\t\t}\n\t];\n};\n","/**\n * The object containing the callbacks for the file reader events\n * @typedef { Object } FooterTraitOptions\n * @property { string } cssClass - The base class to apply to the wrapper container of the footer trait.\n * @property { string } extendedClasses - Other classes to apply to the wrapper container of the footer trait (i.e. utility classes).\n */\n\n/**\n * Creates a trait of the type 'footer' configured with the passed options\n * @param {FooterTraitOptions} options - The options to configure the footer trait.\n */\n\nexport default (options = {}) => {\n\treturn {\n\t\tname: 'footer',\n\t\ttype: 'footer',\n\t\toptions\n\t};\n};\n","import footerTrait from './trait/_trait';\n\nexport default comp => {\n\tconst result = [footerTrait()];\n\n\treturn result;\n};\n","import buildTrait from './_buildTrait';\nimport {\n\tarrayMove,\n\tarrayRemove,\n\tgetElementWidthPercentage\n} from 'datatalks-utils';\nimport { cloneDeep } from 'lodash-es';\nimport baseMethods from '../common/methods/_baseMethods';\n\nexport default (options, editor) => {\n\treturn {\n\t\taddListItem(itemOptions) {\n\t\t\tconst newListItem = {\n\t\t\t\t...cloneDeep(this.get('newListItem')),\n\t\t\t\t...itemOptions\n\t\t\t};\n\t\t\tthis.get('socialList').push(newListItem);\n\t\t\tthis.components(this.componentRender(this));\n\t\t\tif (typeof options.addListItemCallback === 'function')\n\t\t\t\toptions.addListItemCallback.call(this, this, newListItem);\n\t\t\treturn newListItem;\n\t\t},\n\n\t\tdeleteItem(item) {\n\t\t\tarrayRemove(this.get('socialList'), item);\n\t\t\tthis.components(this.componentRender(this));\n\t\t\tif (typeof options.deleteLinkCallback === 'function')\n\t\t\t\toptions.deleteLinkCallback.call(this, this);\n\t\t},\n\n\t\tchangeLinksGap(gap) {\n\t\t\tthis.set('socialListGap', gap);\n\t\t\tthis.components(this.componentRender(this));\n\t\t},\n\n\t\tchangeItemsOrder(oldIndex, newIndex) {\n\t\t\tarrayMove(this.get('socialList'), oldIndex, newIndex);\n\t\t\tthis.components(this.componentRender(this));\n\t\t},\n\n\t\tchangeItemProp(item, propName, value) {\n\t\t\tconst auxItem = this.get('socialList').filter(i => i === item)[0];\n\t\t\tauxItem[propName] = value;\n\t\t\tthis.components(this.componentRender(this));\n\t\t\tthis.emitUpdate(`item:${propName}`, item, value);\n\t\t\tthis.emitUpdate('item', item);\n\t\t\tthis.emitUpdate('socialList', this.get('socialList'));\n\t\t},\n\n\t\tchangeAllItemWidth(value) {\n\t\t\tthis.set('iconWidth', value);\n\t\t\tthis.get('socialList').forEach(item => {\n\t\t\t\titem.content.style.width = value;\n\t\t\t\titem.content.renderWidth = value;\n\t\t\t});\n\t\t\tthis.components(this.componentRender(this));\n\t\t\tthis.emitUpdate('socialList', this.get('socialList'));\n\t\t},\n\n\t\tchangeItemImage(item, imgSrc) {\n\t\t\tconst auxItem = this.get('socialList').filter(i => i === item)[0];\n\t\t\tauxItem.content.imgSrc = imgSrc;\n\t\t\tthis.components(this.componentRender(this));\n\t\t\tthis.emitUpdate('item:image', item, imgSrc);\n\t\t\tthis.emitUpdate('item', item);\n\t\t\tthis.emitUpdate('socialList', this.get('socialList'));\n\t\t},\n\n\t\tchangeLinksWidthToPercentage() {\n\t\t\tconst linksList = this.findType('links-list')[0];\n\t\t\tif (linksList) {\n\t\t\t\tconst linksListEl = linksList.getEl();\n\t\t\t\tif (linksListEl)\n\t\t\t\t\tthis.changeLinksListWidth(\n\t\t\t\t\t\tgetElementWidthPercentage(linksListEl, {\n\t\t\t\t\t\t\tparentEl: this.getEl()\n\t\t\t\t\t\t}) || '50%'\n\t\t\t\t\t);\n\t\t\t}\n\t\t},\n\n\t\tchangeLinksListWidth(width) {\n\t\t\tthis.set('linksListWidth', width);\n\t\t\tthis.components(this.componentRender(this));\n\t\t},\n\n\t\tchangeLinks(html) {\n\t\t\tthis.set('links', html);\n\t\t\tthis.components(this.componentRender(this));\n\t\t},\n\n\t\t// TODO: create utility function as this is a copy based on the image border radius\n\t\tsetLinksBorderRadius(corner, value) {\n\t\t\tconst aux = {};\n\t\t\tif (\n\t\t\t\t['topLeft', 'topRight', 'bottomLeft', 'bottomRight'].includes(\n\t\t\t\t\tcorner\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\taux[corner] = value;\n\t\t\t\tthis.set('linksBorderRadius', {\n\t\t\t\t\t...this.get('linksBorderRadius'),\n\t\t\t\t\t...aux\n\t\t\t\t});\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t} else {\n\t\t\t\tconst br = { ...this.get('linksBorderRadius') };\n\t\t\t\tfor (const key in br) {\n\t\t\t\t\tif (br.hasOwnProperty(key)) aux[key] = value;\n\t\t\t\t}\n\t\t\t\tthis.set('linksBorderRadius', { ...aux });\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t}\n\t\t},\n\n\t\tsetAndRerender(attr, value) {\n\t\t\tthis.set(attr, value);\n\t\t\tthis.components(this.componentRender(this));\n\t\t},\n\t\tbuildTrait,\n\t\trefreshTrait() {\n\t\t\tthis.removeTrait('footer');\n\t\t\tthis.addTrait(this.buildTrait(this));\n\t\t},\n\t\t...baseMethods(options, editor)\n\t};\n};\n","import { validateStyleObj } from '../../common/functions/_utilFunctions';\n\nexport default comp => {\n\tconst getGeneralStyle = comp\n\t\t.getEditor()\n\t\t.getStyleRules.bind(comp.getEditor(), 'component');\n\n\tconst borderRadius = comp.get('useBorderRadius')\n\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t: [\n\t\t\t\tgetGeneralStyle('border-top-left-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-top-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-left-radius') || 0\n\t\t ].join(' ');\n\n\tconst style = {\n\t\t'background-color':\n\t\t\tcomp.get('backgroundColor') || getGeneralStyle('background-color'),\n\t\twidth: comp.get('width'),\n\t\t'border-radius': borderRadius\n\t};\n\n\treturn validateStyleObj(style);\n};\n","import { merge, cssStyleObjectToString } from 'datatalks-utils';\nimport { validateStyleObj } from '../../../common/functions/_utilFunctions';\n\nexport default (innerHtml, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\ttopMargin: '0px',\n\t\trightMargin: '0px',\n\t\tbottomMargin: '0px',\n\t\tleftMargin: '0px',\n\t\thasMargins: false,\n\t\twidth: '100%',\n\t\tbackgroundColor: null,\n\t\thasBorderRadius: false,\n\t\tborderRadius: {\n\t\t\ttopLeft: '0px',\n\t\t\ttopRight: '0px',\n\t\t\tbottomRight: '0px',\n\t\t\tbottomLeft: '0px'\n\t\t},\n\t\tborderWidth: null,\n\t\tborderStyle: null,\n\t\tborderColor: null,\n\t\tuseVml: false\n\t};\n\n\toptions = merge(defaults, options);\n\n\t// Calculations\n\t// TODO: Add options and calculations for the outlook to render border radius depending margin values\n\tconst hasBackground = options.backgroundColor != 'transparent';\n\tconst hasBorder =\n\t\toptions.borderColor != 'transparent' ||\n\t\toptions.borderWidth != '0px' ||\n\t\toptions.borderStyle != 'none';\n\n\tconst tableStyle = {\n\t\t'max-width': options.width,\n\t\twidth: '100%',\n\t\t'background-color': options.backgroundColor,\n\t\t'border-collapse': options.hasBorderRadius ? 'separate' : null,\n\t\t'border-radius': options.hasBorderRadius\n\t\t\t? Object.values(options.borderRadius).join(' ')\n\t\t\t: null,\n\t\t'border-width': options.borderWidth,\n\t\t'border-style': options.borderStyle,\n\t\t'border-color': options.borderColor\n\t};\n\n\tconst cellStyle = {\n\t\t'padding-top': options.hasMargins ? options.topMargin || 0 : 0,\n\t\t'padding-right': options.hasMargins ? options.rightMargin || 0 : 0,\n\t\t'padding-bottom': options.hasMargins ? options.bottomMargin || 0 : 0,\n\t\t'padding-left': options.hasMargins ? options.leftMargin || 0 : 0\n\t};\n\n\t// TODO: Improve VML for better rendering in Outlook\n\tconst vml =\n\t\tinnerHtml => `\n\n \n \n \n \n\n \n\n \n \n \n \n\n \n \n \n \n \n\n \n \n \n \n \n\n \n\n \n \n \n \n \n\n \n \n \n \n \n\n \n \n \n \n\n \n \n \n \n \n\n
\n \n \n
\n \n ${innerHtml}\n \n
\n \n \n
`;\n\n\tconst html = options.useVml\n\t\t? vml(innerHtml)\n\t\t: `\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t\t\t\t${innerHtml}\n\t\t\t\t\t
\n\t\t`;\n\n\tif (options.debug) console.log('Margins common template HTML: ', html);\n\n\treturn html;\n};\n","import {\n\tmerge,\n\tcssStyleObjectToString,\n\tinsertAfterEveryItem\n} from 'datatalks-utils';\nimport getComputedStyle from './_getComputedStyle';\nimport margins from '../common/htmlTemplates/_margins';\nimport borderWrapper from '../common/htmlTemplates/_borderWrapper';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tstyle: getComputedStyle(comp),\n\t\ttext: comp.get('text'),\n\t\tparentWidth: null,\n\t\tverticalAlignment: comp.get('socialListVAlignment'),\n\t\tsideLayout: comp.get('socialListSideways'),\n\t\timageWidth: comp.get('imageWidth'),\n\t\tlinksListWidth: comp.get('linksListWidth'),\n\t\tvSpace: comp.get('spacingBetweenElements'),\n\t\thSpace: comp.get('horizontalSpacingBetweenElements'),\n\t\tlistAlignment: comp.get('socialListAlignment')\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tconst debugStrStart = options.debug ? 'data-eb-name=\"footer-first\"' : '';\n\tconst debugStrEnd = options.debug ? 'data-eb-name=\"footer-last\"' : '';\n\n\tconst isSideLayout =\n\t\toptions.sideLayout &&\n\t\tcomp.get('displaySocialList') &&\n\t\t(comp.get('displayTitle') ||\n\t\t\tcomp.get('displayDescription') ||\n\t\t\tcomp.get('displayLinks'));\n\n\tconst listRatio =\n\t\toptions.linksListWidth == 'auto'\n\t\t\t? 0.3\n\t\t\t: parseFloat(options.linksListWidth) / 100;\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst isMobileOptimized = comp\n\t\t.getEditor()\n\t\t.getEmailBuilder()\n\t\t.getAdvancedOption('isMobileOptimized');\n\n\tconst marginsWidth = comp.get('hasMargins')\n\t\t? parseFloat(comp.get('leftMargin')) +\n\t\t parseFloat(comp.get('rightMargin')) +\n\t\t 'px'\n\t\t: 0;\n\n\t/**\n\t * Calculates the width of the list based on the component's attributes.\n\t * If the linksListWidth attribute is set to 'auto', it calculates the width based on the icon width, social list margins, and gaps.\n\t * If the linksListWidth attribute is not set to 'auto', it calculates the width based on the parent width and margins width.\n\t * @return {number} The calculated width of the list.\n\t */\n\tfunction getListWidth() {\n\t\tif (comp.attributes.linksListWidth === 'auto')\n\t\t\treturn comp.get('socialListIsWrapable')\n\t\t\t\t? (parseFloat(comp.get('iconWidth')) +\n\t\t\t\t\t\tparseFloat(comp.get('socialListGap'))) *\n\t\t\t\t\t\tcomp.get('socialList').length\n\t\t\t\t: parseFloat(comp.get('iconWidth')) *\n\t\t\t\t\t\tcomp.get('socialList').length +\n\t\t\t\t\t\tparseFloat(comp.get('socialListGap')) *\n\t\t\t\t\t\t\t(comp.get('socialList').length - 1);\n\t\telse\n\t\t\treturn (\n\t\t\t\t(parseFloat(options.parentWidth) - parseFloat(marginsWidth)) *\n\t\t\t\tlistRatio\n\t\t\t);\n\t}\n\n\t/**\n\t * Calculates the width of the list item based on the parent width, provided options and number of columns.\n\t * @param {number} rightSideWidth - The width of the list in pixels.\n\t * @return {number} The width (without unit, only number) in pixels of the element based on the parent's width.\n\t */\n\tfunction getParentWidth(rightSideWidth) {\n\t\tif (options.sideLayout)\n\t\t\treturn (\n\t\t\t\tparseFloat(options.parentWidth) -\n\t\t\t\tparseFloat(marginsWidth) -\n\t\t\t\tparseFloat(rightSideWidth) -\n\t\t\t\tparseFloat(options.hSpace)\n\t\t\t);\n\t\telse return parseFloat(options.parentWidth) - parseFloat(marginsWidth);\n\t}\n\n\t/**\n\t * Calculates the width of the links in pixels.\n\t * @param {number} parentWidth - The width of the parent element in pixels.\n\t * @param {boolean} isBorderWrapper - Indicates whether the links have a border wrapper.\n\t * @return {string} The width of the links in pixels.\n\t */\n\tfunction getLinksWidthPx(parentWidth, isBorderWrapper = false) {\n\t\tconst borderWidth = isBorderWrapper\n\t\t\t? 0\n\t\t\t: parseFloat(comp.attributes.linksBorderWidth) * 2;\n\t\treturn (\n\t\t\t(parseFloat(parentWidth) * parseFloat(comp.attributes.linksWidth)) /\n\t\t\t\t100 -\n\t\t\tborderWidth +\n\t\t\t'px'\n\t\t);\n\t}\n\n\tlet innerHtml;\n\n\tconst listWidthPx = getListWidth() + 'px';\n\tconst textWidthPx = getParentWidth(listWidthPx) + 'px';\n\tconst descriptionIndex = comp.get('displayTitle') ? 1 : 0;\n\tconst linksIndex =\n\t\t0 +\n\t\t(comp.get('displayTitle') ? 1 : 0) +\n\t\t(comp.get('displayDescription') ? 1 : 0);\n\n\t/**\n\t * Retrieves the HTML representation of a specific element based on its name.\n\t *\n\t * @param {string} name - The name of the element to retrieve.\n\t * @return {string} The HTML representation of the element.\n\t */\n\tfunction getElement(name) {\n\t\tswitch (name) {\n\t\t\tcase 'list':\n\t\t\t\treturn comp\n\t\t\t\t\t.findType('links-list')[0]\n\t\t\t\t\t.toHTML({ parentWidth: listWidthPx, isMobileOptimized });\n\t\t\t\tbreak;\n\n\t\t\tcase 'title':\n\t\t\t\treturn comp\n\t\t\t\t\t.findType('text')[0]\n\t\t\t\t\t.toHTML({ parentWidth: textWidthPx });\n\t\t\t\tbreak;\n\n\t\t\tcase 'description':\n\t\t\t\treturn comp\n\t\t\t\t\t.findType('text')\n\t\t\t\t\t[descriptionIndex].toHTML({ parentWidth: textWidthPx });\n\t\t\t\tbreak;\n\n\t\t\tcase 'links':\n\t\t\t\treturn borderWrapper(\n\t\t\t\t\tcomp.findType('text')[linksIndex].toHTML({\n\t\t\t\t\t\tparentWidth: getLinksWidthPx(textWidthPx, false)\n\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\twidth: getLinksWidthPx(textWidthPx, true),\n\t\t\t\t\t\tbackgroundColor: comp.attributes.linksBackground,\n\t\t\t\t\t\thasBorderRadius: Object.values(\n\t\t\t\t\t\t\tcomp.attributes.linksBorderRadius\n\t\t\t\t\t\t).some(borderRadius => borderRadius !== '0px'),\n\t\t\t\t\t\tborderRadius: comp.attributes.linksBorderRadius,\n\t\t\t\t\t\tborderWidth: comp.attributes.linksBorderWidth,\n\t\t\t\t\t\tborderStyle: comp.attributes.linksBorderStyle,\n\t\t\t\t\t\tborderColor: comp.attributes.linksBorderColor,\n\t\t\t\t\t\tuseVml: false\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tconsole.warn('Invalid element name: ', name);\n\t\t\t\treturn '';\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Generates an HTML table row with the provided content.\n\t *\n\t * @param {string} content - The content to be placed inside the table cell.\n\t * @param {boolean} shouldRender - Determines whether the row should be rendered or not.\n\t * @param {object} rowOptions - Additional options for the row.\n\t * @return {string} - The generated HTML table row.\n\t */\n\tfunction row(content, shouldRender, rowOptions = {}) {\n\t\tconst defaults = {\n\t\t\talign: 'left',\n\t\t\tmsoComments: false,\n\t\t\thasMargins: false\n\t\t};\n\n\t\trowOptions = merge(defaults, rowOptions);\n\t\tconst mso = rowOptions.msoComments;\n\n\t\tif (shouldRender) {\n\t\t\tcontent = typeof content === 'function' ? content() : content;\n\t\t\tconst marginStr = rowOptions.hasMargins\n\t\t\t\t? `margin-top: ${options.vSpace};`\n\t\t\t\t: '';\n\t\t\treturn `\n\t\t\t${mso ? '' : ''}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t${content}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t${mso ? '' : ''}`;\n\t\t} else return '';\n\t}\n\n\t/**\n\t * Checks if an element should have a margin based on the elements that are displayed above.\n\t * @param {string} elementName - The name of the element.\n\t * @return {boolean} - Returns true if the element should have a margin, false otherwise.\n\t */\n\tfunction elementShouldHaveMargin(elementName) {\n\t\tswitch (elementName) {\n\t\t\tcase 'description':\n\t\t\t\treturn comp.get('displayTitle');\n\t\t\t\tbreak;\n\t\t\tcase 'links':\n\t\t\t\treturn (\n\t\t\t\t\tcomp.get('displayDescription') || comp.get('displayTitle')\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tconst vSpace = `\n\t\t\n\t\t\t\n\t\t`;\n\n\tconst listRow = row(\n\t\tgetElement.bind(null, 'list'),\n\t\tcomp.get('displaySocialList'),\n\t\t{ align: options.listAlignment }\n\t);\n\tconst titleRow = row(\n\t\tgetElement.bind(null, 'title'),\n\t\tcomp.get('displayTitle'),\n\t\t{\n\t\t\tmsoComments: isSideLayout,\n\t\t\thasMargins: elementShouldHaveMargin('title')\n\t\t}\n\t);\n\tconst descriptionRow = row(\n\t\tgetElement.bind(null, 'description'),\n\t\tcomp.get('displayDescription'),\n\t\t{\n\t\t\tmsoComments: isSideLayout,\n\t\t\thasMargins: elementShouldHaveMargin('description')\n\t\t}\n\t);\n\tconst linksRow = row(\n\t\tgetElement.bind(null, 'links'),\n\t\tcomp.get('displayLinks'),\n\t\t{\n\t\t\tmsoComments: isSideLayout,\n\t\t\thasMargins: elementShouldHaveMargin('links'),\n\t\t\talign: comp.attributes.linksAlignment\n\t\t}\n\t);\n\n\t// TODO: display\n\n\tconst bgString = options.style['background-color']\n\t\t? `bgcolor=\"${options.style['background-color']}\"`\n\t\t: '';\n\n\tconst columnPadding = isMobileOptimized\n\t\t? `padding:${parseFloat(options.hSpace) / 2}px;`\n\t\t: '';\n\n\tconst va = options.verticalAlignment;\n\tconst style = cssStyleObjectToString(options.style);\n\n\tif (isSideLayout) {\n\t\tconst rows = insertAfterEveryItem(\n\t\t\t[titleRow, descriptionRow, linksRow].filter(row => !!row),\n\t\t\t``\n\t\t).join(' ');\n\t\tconst textPerWidth = 100 - parseFloat(options.linksListWidth) + '%';\n\t\tconst listPerWidth = options.linksListWidth;\n\t\tinnerHtml = `\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t${rows}\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t${getElement('list')}\n\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\n\t\t\t
\n\t`;\n\t} else {\n\t\tconst rows = insertAfterEveryItem(\n\t\t\t[titleRow, descriptionRow, listRow, linksRow].filter(row => !!row),\n\t\t\tvSpace\n\t\t).join(' ');\n\t\tinnerHtml = `\n\t\t\t\n\t\t\t\t${rows}\n\t\t\t
\n\t\t`;\n\t}\n\n\tconst html = margins(innerHtml, {\n\t\ttopMargin: comp.get('topMargin') || 0,\n\t\trightMargin: comp.get('rightMargin') || 0,\n\t\tbottomMargin: comp.get('bottomMargin') || 0,\n\t\tleftMargin: comp.get('leftMargin') || 0,\n\t\thasMargins: comp.get('hasMargins'),\n\t\tbackgroundColor: comp.get('backgroundColor')\n\t});\n\n\tif (options.debug)\n\t\tconsole.log('Footer HTML: ', comp.get('hasMargins') ? html : innerHtml);\n\n\treturn comp.get('hasMargins') ? html : innerHtml;\n};\n","import { COMPONENTS_DEFAULTS } from '../../../config/_config';\nimport render from './_render';\nimport methods from './_methods';\nimport { merge } from 'datatalks-utils';\nimport { getComponentsDefaultsByType } from '../../componentsDefaults/_componentsDefaults';\nimport toHtml from './_toHtml';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tlet defaults = {\n\t\tattributes: {},\n\t\tspacingBetweenElements: '12px',\n\t\thorizontalSpacingBetweenElements: '12px',\n\t\tcssClass: 'gjs-comp-footer',\n\t\twidth: '100%',\n\t\ttagName: 'table',\n\t\ttitlePh: 'Keep in touch and follow us',\n\t\ttitleAlignment: 'center',\n\t\ttitleStyle: {\n\t\t\tcolor: null\n\t\t},\n\t\tdisplayTitle: true,\n\t\tdescriptionPh: '@2022 Your brand. All rights reserved',\n\t\tdescriptionAlignment: 'center',\n\t\tdescriptionStyle: {\n\t\t\tcolor: null\n\t\t},\n\t\tdisplayDescription: true,\n\t\tsocialListGap: '0px',\n\t\tsocialListSideways: false,\n\t\tdisplaySocialList: true,\n\t\tsocialListAlignment: 'center',\n\t\tsocialListVAlignment: 'bottom',\n\t\tsocialListLeftMargin: '0px',\n\t\tsocialListRightMargin: '0px',\n\t\tsocialListTopMargin: '0px',\n\t\tsocialListBottomMargin: '0px',\n\t\tsocialListIsWrapable: false,\n\t\tuseLinksGap: true,\n\t\tlinksListWidth: 'auto',\n\t\tlinks: '

DataTalks CDP | DataTalks Website

',\n\t\tlinksAlignment: 'center',\n\t\tlinksStyle: {\n\t\t\tcolor: null\n\t\t},\n\t\tlinksBackground: 'transparent',\n\t\tlinksWidth: '100%',\n\t\tlinksBorderRadius: {\n\t\t\ttopLeft: 0,\n\t\t\ttopRight: 0,\n\t\t\tbottomRight: 0,\n\t\t\tbottomLeft: 0\n\t\t},\n\t\tlinksBorderColor: 'transparent',\n\t\tlinksBorderStyle: 'solid',\n\t\tlinksBorderWidth: 0,\n\t\ticonWidth: '36px',\n\t\tdisplayLinks: true,\n\t\tname: 'Footer',\n\t\taddListItemCallback: null,\n\t\tdeleteLinkCallback: null,\n\t\ttoHtmlOptions: {}\n\t};\n\n\tdefaults = {\n\t\t...defaults,\n\t\tsocialList: [\n\t\t\t{\n\t\t\t\tcontent: {\n\t\t\t\t\ttype: 'image-wrapper',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tsrc: null\n\t\t\t\t\t},\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\twidth: componentOptions.iconWidth || defaults.iconWidth\n\t\t\t\t\t},\n\t\t\t\t\trenderWidth:\n\t\t\t\t\t\tcomponentOptions.iconWidth || defaults.iconWidth\n\t\t\t\t},\n\t\t\t\thref: 'http://www.facebook.com',\n\t\t\t\tname: 'Facebook',\n\t\t\t\ttarget: '_blank'\n\t\t\t},\n\t\t\t{\n\t\t\t\tcontent: {\n\t\t\t\t\ttype: 'image-wrapper',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tsrc: null\n\t\t\t\t\t},\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\twidth: componentOptions.iconWidth || defaults.iconWidth\n\t\t\t\t\t},\n\t\t\t\t\trenderWidth:\n\t\t\t\t\t\tcomponentOptions.iconWidth || defaults.iconWidth\n\t\t\t\t},\n\t\t\t\thref: 'http://www.instagram.com',\n\t\t\t\tname: 'Instagram',\n\t\t\t\ttarget: '_blank'\n\t\t\t},\n\t\t\t{\n\t\t\t\tcontent: {\n\t\t\t\t\ttype: 'image-wrapper',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tsrc: null\n\t\t\t\t\t},\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\twidth: componentOptions.iconWidth || defaults.iconWidth\n\t\t\t\t\t},\n\t\t\t\t\trenderWidth:\n\t\t\t\t\t\tcomponentOptions.iconWidth || defaults.iconWidth\n\t\t\t\t},\n\t\t\t\thref: 'http://www.twitter.com',\n\t\t\t\tname: 'Twitter',\n\t\t\t\ttarget: '_blank'\n\t\t\t}\n\t\t],\n\t\tnewListItem: {\n\t\t\tcontent: {\n\t\t\t\ttype: 'image-wrapper',\n\t\t\t\tattributes: {\n\t\t\t\t\tsrc: null\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: componentOptions.iconWidth || defaults.iconWidth\n\t\t\t\t},\n\t\t\t\trenderWidth: componentOptions.iconWidth || defaults.iconWidth\n\t\t\t},\n\t\t\thref: 'http://www.newItem.com',\n\t\t\tname: 'New Item',\n\t\t\ttarget: '_blank'\n\t\t}\n\t};\n\n\tconst options = merge(\n\t\tCOMPONENTS_DEFAULTS,\n\t\tgetComponentsDefaultsByType(),\n\t\tdefaults,\n\t\tcomponentOptions\n\t);\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\tisCompound: true,\n\t\t\t\t...options,\n\t\t\t\ttitle: `

${options.titlePh}

`,\n\t\t\t\tdescription: `
${options.descriptionPh}
`,\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: options.width\n\t\t\t\t},\n\t\t\t\tsocialList: [...options.socialList],\n\t\t\t\tcomponents: comp => comp.componentRender(comp),\n\t\t\t\ttraits: comp => comp.buildTrait(comp)\n\t\t\t}),\n\n\t\t\tinit() {\n\t\t\t\tthis.setStyle({\n\t\t\t\t\t...this.getStyle(),\n\t\t\t\t\twidth: this.get('width')\n\t\t\t\t});\n\t\t\t},\n\n\t\t\ttoHTML(toHtmlOptions = {}) {\n\t\t\t\treturn toHtml(\n\t\t\t\t\tthis,\n\t\t\t\t\tmerge(options.toHtmlOptions, toHtmlOptions)\n\t\t\t\t);\n\t\t\t},\n\n\t\t\tcomponentRender: render,\n\t\t\t...methods(options, editor)\n\t\t}\n\t};\n};\n","/**\n * The object containing the options to configure the Call To Action trait\n * @typedef { Object } CallToActionTraitOptions\n * @property { string } cssClass - The base class to apply to the wrapper container of the trait.\n * @property { string } extendedClasses - Other classes to apply to the wrapper container of the trait (i.e. utility classes).\n */\n\n/**\n * Creates a trait of the type 'call-to-action' configured with the passed options\n * @param {CallToActionTraitOptions} options - The options to configure the call to action trait.\n */\n\nexport default (options = {}) => {\n\treturn {\n\t\ttype: 'call-to-action',\n\t\toptions\n\t};\n};\n","import { addSpace as _addSpace } from '../_componentsUtils';\nimport { validateStyleObj } from '../../common/functions/_utilFunctions';\nimport updateStyle from '../common/_updateCommonStyle';\n\nexport default comp => {\n\tconst innerComponents = [];\n\tconst addSpace = _addSpace.bind(null, comp, false, innerComponents);\n\n\t/**\n\t * Get the width of an element based on the component's properties.\n\t * @param {string} element - The element type ('text' or 'button').\n\t * @return {string} The calculated width of the element.\n\t */\n\tfunction getWidth(element) {\n\t\tif (!comp.get('displayText') || !comp.get('displayButton')) {\n\t\t\treturn '100%';\n\t\t} else {\n\t\t\tconst percentage =\n\t\t\t\telement === 'text'\n\t\t\t\t\t? `${(1 - comp.get('buttonContentRatio')) * 100}%`\n\t\t\t\t\t: `${comp.get('buttonContentRatio') * 100}%`;\n\n\t\t\t// return `calc(${percentage} - ${comp.get(\n\t\t\t// \t'spacingBetweenElements'\n\t\t\t// )})`;\n\t\t\treturn percentage;\n\t\t}\n\t}\n\n\tif (comp.get('displayText')) {\n\t\tinnerComponents.push({\n\t\t\ttype: 'cell',\n\t\t\tstyle: {\n\t\t\t\t'text-align': comp.attributes.textAlignment,\n\t\t\t\twidth: getWidth('text')\n\t\t\t},\n\t\t\tcomponents: {\n\t\t\t\ttype: 'text',\n\t\t\t\tstyle: validateStyleObj(comp.get('textStyle')),\n\t\t\t\ttext: comp.attributes.textContent\n\t\t\t}\n\t\t});\n\t}\n\n\tif (comp.get('displayButton')) {\n\t\tif (innerComponents.length) addSpace();\n\n\t\tinnerComponents.push({\n\t\t\ttype: 'cell',\n\t\t\tstyle: {\n\t\t\t\twidth: getWidth('button')\n\t\t\t},\n\t\t\tattributes: {\n\t\t\t\talign: comp.get('buttonAlignment')\n\t\t\t},\n\t\t\tcomponents: {\n\t\t\t\ttype: 'button',\n\t\t\t\tbackgroundColor: comp.get('buttonBackgroundColor'),\n\t\t\t\theight: comp.get('buttonHeight'),\n\t\t\t\twidth: comp.get('buttonWidth'),\n\t\t\t\tfontFamily: comp.get('buttonFontFamily'),\n\t\t\t\tfontSize: comp.get('buttonFontSize'),\n\t\t\t\tfontStyle: comp.get('buttonFontStyle'),\n\t\t\t\tcolor: comp.get('buttonColor'),\n\t\t\t\tfontWeight: comp.get('buttonFontWeight'),\n\t\t\t\tborderWidth: comp.get('buttonBorderWidth'),\n\t\t\t\tborderStyle: comp.get('buttonBorderStyle'),\n\t\t\t\tborderColor: comp.get('buttonBorderColor'),\n\t\t\t\tborderRadius: comp.get('buttonBorderRadius'),\n\t\t\t\tuseBorderRadius: comp.get('buttonUseBorderRadius'),\n\t\t\t\tlineHeight: comp.get('buttonLineHeight'),\n\t\t\t\thref: comp.get('buttonHref'),\n\t\t\t\threfState: comp.get('buttonHrefState'),\n\t\t\t\tstyle: {\n\t\t\t\t\t'letter-spacing': comp.get('buttonLetterSpacing')\n\t\t\t\t},\n\t\t\t\ttext: comp.attributes.buttonText,\n\t\t\t\ttextAlignment: comp.get('buttonTextAlignment'),\n\t\t\t\ttextDecorationLine: comp.get('buttonTextDecorationLine')\n\t\t\t}\n\t\t});\n\t}\n\n\tupdateStyle(comp);\n\n\treturn [\n\t\t{\n\t\t\ttype: 'margins',\n\t\t\tinnerComponents: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'row',\n\t\t\t\t\tcomponents: innerComponents\n\t\t\t\t}\n\t\t\t],\n\t\t\thasMargins: comp.get('hasMargins'),\n\t\t\tmargins: {\n\t\t\t\ttop: comp.get('topMargin'),\n\t\t\t\tright: comp.get('rightMargin'),\n\t\t\t\tbottom: comp.get('bottomMargin'),\n\t\t\t\tleft: comp.get('leftMargin')\n\t\t\t},\n\t\t\tmarginsColor: {\n\t\t\t\ttop: comp.get('topMarginColor'),\n\t\t\t\tright: comp.get('rightMarginColor'),\n\t\t\t\tbottom: comp.get('bottomMarginColor'),\n\t\t\t\tleft: comp.get('leftMarginColor')\n\t\t\t}\n\t\t}\n\t];\n};\n","import { validateStyleObj } from '../../common/functions/_utilFunctions';\n\nexport default comp => {\n\tconst getGeneralStyle = comp\n\t\t.getEditor()\n\t\t.getStyleRules.bind(comp.getEditor(), 'component');\n\n\tconst borderRadius = comp.get('useBorderRadius')\n\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t: [\n\t\t\t\tgetGeneralStyle('border-top-left-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-top-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-left-radius') || 0\n\t\t ].join(' ');\n\n\treturn validateStyleObj({\n\t\t'background-color':\n\t\t\tcomp.get('backgroundColor') || getGeneralStyle('background-color'),\n\t\twidth: comp.get('width'),\n\t\t'border-radius': borderRadius\n\t});\n};\n","import {\n\tmerge,\n\tcssStyleObjectToString,\n\tisValidDimension\n} from 'datatalks-utils';\n\nimport getComputedStyle from './_getComputedStyle';\nimport margins from '../common/htmlTemplates/_margins';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tparentWidth: null,\n\t\tstyle: getComputedStyle(comp),\n\t\tspace: comp.get('spacingBetweenElements'),\n\t\tbuttonRatio: comp.get('buttonContentRatio') || 0.3\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst isMobileOptimized = comp\n\t\t.getEditor()\n\t\t.getEmailBuilder()\n\t\t.getAdvancedOption('isMobileOptimized');\n\n\tconst debugStrStart = options.debug ? 'data-eb-name=\"cta-first\"' : '';\n\tconst debugStrEnd = options.debug ? 'data-eb-name=\"cta-last\"' : '';\n\n\tconst marginsWidth = comp.get('hasMargins')\n\t\t? parseFloat(comp.get('leftMargin')) +\n\t\t parseFloat(comp.get('rightMargin')) +\n\t\t 'px'\n\t\t: 0;\n\n\tlet innerHtml;\n\n\tconst bgAttr = options.style['background-color']\n\t\t? `bgcolor=\"${options.style['background-color']}\"`\n\t\t: '';\n\n\t/**\n\t * Calculates the width of the list item based on the parent width, provided options and number of columns.\n\t * @param {string} element - The element to calculate the width for.\n\t * @param {number} nElements - The number of elements to calculate the width for.\n\t * @return {number} The width of the parent element.\n\t */\n\tfunction getParentWidth(element, nElements = 2) {\n\t\tlet ratio =\n\t\t\telement === 'text' ? 1 - options.buttonRatio : options.buttonRatio;\n\t\tif (nElements === 1) ratio = 1;\n\t\treturn `${\n\t\t\t(parseFloat(options.parentWidth) -\n\t\t\t\tparseFloat(marginsWidth) -\n\t\t\t\tparseFloat(options.space)) *\n\t\t\tratio\n\t\t}px`;\n\t}\n\tconst columnPadding =\n\t\tisMobileOptimized && isValidDimension(options.space)\n\t\t\t? `padding:${parseFloat(options.space) / 2}px;`\n\t\t\t: '';\n\n\tif (comp.get('displayText') && comp.get('displayButton')) {\n\t\tinnerHtml = `\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t${comp.findType('text')[0].toHTML({ parentWidth: getParentWidth('text') })}\n\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t${comp.findType('button')[0].toHTML({ parentWidth: getParentWidth('button') })}\n\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t
\n\t\t`;\n\t} else if (!comp.get('displayText') && !comp.get('displayButton')) {\n\t\tinnerHtml = '';\n\t} else {\n\t\tconst element = comp.get('displayText') ? 'text' : 'button';\n\t\tinnerHtml = `\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t\t\t\t${comp.findType(element)[0].toHTML({ parentWidth: getParentWidth(element, 1) })}\n\t\t\t\t\t
\n\t\t`;\n\t}\n\n\tconst html = margins(innerHtml, {\n\t\ttopMargin: comp.get('topMargin') || 0,\n\t\trightMargin: comp.get('rightMargin') || 0,\n\t\tbottomMargin: comp.get('bottomMargin') || 0,\n\t\tleftMargin: comp.get('leftMargin') || 0,\n\t\thasMargins: comp.get('hasMargins'),\n\t\tbackgroundColor: comp.get('backgroundColor')\n\t});\n\n\tif (options.debug)\n\t\tconsole.log(\n\t\t\t'Call to action HTML: ',\n\t\t\tcomp.get('hasMargins') ? html : innerHtml\n\t\t);\n\n\treturn comp.get('hasMargins') ? html : innerHtml;\n};\n","import { COMPONENTS_DEFAULTS } from '../../../config/_config';\nimport trait from './trait/_trait';\nimport render from './_render';\nimport baseMethods from '../common/methods/_baseMethods';\nimport { getComponentsDefaultsByType } from '../../componentsDefaults/_componentsDefaults';\nimport { merge } from 'datatalks-utils';\nimport toHtml from './_toHtml';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = {\n\t\tattributes: {},\n\t\tspacingBetweenElements: '12px',\n\t\tcssClass: 'gjs-comp-call-to-action',\n\t\twidth: '100%',\n\t\ttextContentPh: 'This should be a call to action heading.',\n\t\tbuttonPh: 'Button text',\n\t\ttextAlignment: 'left',\n\t\ttextStyle: {\n\t\t\tcolor: null\n\t\t},\n\t\tname: 'Call To Action',\n\t\tdisplayText: true,\n\t\tdisplayButton: true,\n\t\tbuttonPh: 'Button text',\n\t\tbuttonBackgroundColor: null,\n\t\tbuttonHeight: null,\n\t\tbuttonWidth: '100%',\n\t\tbuttonFontFamily: null,\n\t\tbuttonFontSize: null,\n\t\tbuttonFontStyle: 'normal',\n\t\tbuttonColor: null,\n\t\tbuttonFontWeight: null,\n\t\tbuttonBorderWidth: '0px',\n\t\tbuttonBorderStyle: 'solid',\n\t\tbuttonBorderColor: 'transparent',\n\t\tbuttonAlignment: 'right',\n\t\tbuttonBorderRadius: {\n\t\t\ttopLeft: 0,\n\t\t\ttopRight: 0,\n\t\t\tbottomRight: 0,\n\t\t\tbottomLeft: 0\n\t\t},\n\t\tbuttonUseBorderRadius: false,\n\t\tbuttonLetterSpacing: 'normal',\n\t\tbuttonNormalLetterSpacing: true,\n\t\tbuttonDefaultLetterSpacingLength: '0.1em',\n\t\tbuttonLineHeight: null,\n\t\tbuttonHasOutlookBorderRadius: false,\n\t\tbuttonOutlookWidth: '150px',\n\t\ttoHtmlOptions: {},\n\t\tbuttonContentRatio: '0.3',\n\t\tbuttonTextDecorationLine: null\n\t};\n\n\tconst options = merge(\n\t\tCOMPONENTS_DEFAULTS,\n\t\tgetComponentsDefaultsByType(),\n\t\tdefaults,\n\t\tcomponentOptions\n\t);\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\tisCompound: true,\n\t\t\t\tname: options.name,\n\t\t\t\t...options,\n\t\t\t\ttagName: 'table',\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: options.width\n\t\t\t\t},\n\t\t\t\ttextContent: `

${options.textContentPh}

`,\n\t\t\t\tbuttonText: options.buttonPh,\n\t\t\t\tbuttonNormalLetterSpacing:\n\t\t\t\t\toptions.buttonLetterSpacing === 'normal',\n\t\t\t\tcomponents: comp => comp.componentRender(comp),\n\t\t\t\ttraits(component) {\n\t\t\t\t\tconst result = [trait()];\n\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t}),\n\n\t\t\tinit() {\n\t\t\t\tthis.setStyle({\n\t\t\t\t\t...this.getStyle(),\n\t\t\t\t\twidth: this.get('width')\n\t\t\t\t});\n\t\t\t},\n\n\t\t\ttoHTML(toHtmlOpts = {}) {\n\t\t\t\treturn toHtml(this, merge(options.toHtmlOptions, toHtmlOpts));\n\t\t\t},\n\n\t\t\tcomponentRender: render,\n\n\t\t\tsetNormalLetterSpacing(isNormal) {\n\t\t\t\tthis.set('buttonNormalLetterSpacing', isNormal);\n\t\t\t},\n\n\t\t\tsetLetterSpacing(value) {\n\t\t\t\tthis.setNormalLetterSpacing(value === 'normal');\n\t\t\t\tthis.setAndRerender('buttonLetterSpacing', value);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\tsetAndRerender(prop, value) {\n\t\t\t\tthis.set(prop, value);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\n\t\t\trerender() {\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t},\n\t\t\t...baseMethods(componentOptions, editor)\n\t\t}\n\t};\n};\n","export function resolveUrl(url, baseUrl) {\n // url is absolute already\n if (url.match(/^[a-z]+:\\/\\//i)) {\n return url;\n }\n // url is absolute already, without protocol\n if (url.match(/^\\/\\//)) {\n return window.location.protocol + url;\n }\n // dataURI, mailto:, tel:, etc.\n if (url.match(/^[a-z]+:/i)) {\n return url;\n }\n const doc = document.implementation.createHTMLDocument();\n const base = doc.createElement('base');\n const a = doc.createElement('a');\n doc.head.appendChild(base);\n doc.body.appendChild(a);\n if (baseUrl) {\n base.href = baseUrl;\n }\n a.href = url;\n return a.href;\n}\nexport const uuid = (() => {\n // generate uuid for className of pseudo elements.\n // We should not use GUIDs, otherwise pseudo elements sometimes cannot be captured.\n let counter = 0;\n // ref: http://stackoverflow.com/a/6248722/2519373\n const random = () => \n // eslint-disable-next-line no-bitwise\n `0000${((Math.random() * 36 ** 4) << 0).toString(36)}`.slice(-4);\n return () => {\n counter += 1;\n return `u${random()}${counter}`;\n };\n})();\nexport function delay(ms) {\n return (args) => new Promise((resolve) => {\n setTimeout(() => resolve(args), ms);\n });\n}\nexport function toArray(arrayLike) {\n const arr = [];\n for (let i = 0, l = arrayLike.length; i < l; i++) {\n arr.push(arrayLike[i]);\n }\n return arr;\n}\nfunction px(node, styleProperty) {\n const win = node.ownerDocument.defaultView || window;\n const val = win.getComputedStyle(node).getPropertyValue(styleProperty);\n return val ? parseFloat(val.replace('px', '')) : 0;\n}\nfunction getNodeWidth(node) {\n const leftBorder = px(node, 'border-left-width');\n const rightBorder = px(node, 'border-right-width');\n return node.clientWidth + leftBorder + rightBorder;\n}\nfunction getNodeHeight(node) {\n const topBorder = px(node, 'border-top-width');\n const bottomBorder = px(node, 'border-bottom-width');\n return node.clientHeight + topBorder + bottomBorder;\n}\nexport function getImageSize(targetNode, options = {}) {\n const width = options.width || getNodeWidth(targetNode);\n const height = options.height || getNodeHeight(targetNode);\n return { width, height };\n}\nexport function getPixelRatio() {\n let ratio;\n let FINAL_PROCESS;\n try {\n FINAL_PROCESS = process;\n }\n catch (e) {\n // pass\n }\n const val = FINAL_PROCESS && FINAL_PROCESS.env\n ? FINAL_PROCESS.env.devicePixelRatio\n : null;\n if (val) {\n ratio = parseInt(val, 10);\n if (Number.isNaN(ratio)) {\n ratio = 1;\n }\n }\n return ratio || window.devicePixelRatio || 1;\n}\n// @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size\nconst canvasDimensionLimit = 16384;\nexport function checkCanvasDimensions(canvas) {\n if (canvas.width > canvasDimensionLimit ||\n canvas.height > canvasDimensionLimit) {\n if (canvas.width > canvasDimensionLimit &&\n canvas.height > canvasDimensionLimit) {\n if (canvas.width > canvas.height) {\n canvas.height *= canvasDimensionLimit / canvas.width;\n canvas.width = canvasDimensionLimit;\n }\n else {\n canvas.width *= canvasDimensionLimit / canvas.height;\n canvas.height = canvasDimensionLimit;\n }\n }\n else if (canvas.width > canvasDimensionLimit) {\n canvas.height *= canvasDimensionLimit / canvas.width;\n canvas.width = canvasDimensionLimit;\n }\n else {\n canvas.width *= canvasDimensionLimit / canvas.height;\n canvas.height = canvasDimensionLimit;\n }\n }\n}\nexport function canvasToBlob(canvas, options = {}) {\n if (canvas.toBlob) {\n return new Promise((resolve) => {\n canvas.toBlob(resolve, options.type ? options.type : 'image/png', options.quality ? options.quality : 1);\n });\n }\n return new Promise((resolve) => {\n const binaryString = window.atob(canvas\n .toDataURL(options.type ? options.type : undefined, options.quality ? options.quality : undefined)\n .split(',')[1]);\n const len = binaryString.length;\n const binaryArray = new Uint8Array(len);\n for (let i = 0; i < len; i += 1) {\n binaryArray[i] = binaryString.charCodeAt(i);\n }\n resolve(new Blob([binaryArray], {\n type: options.type ? options.type : 'image/png',\n }));\n });\n}\nexport function createImage(url) {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.decode = () => resolve(img);\n img.onload = () => resolve(img);\n img.onerror = reject;\n img.crossOrigin = 'anonymous';\n img.decoding = 'async';\n img.src = url;\n });\n}\nexport async function svgToDataURL(svg) {\n return Promise.resolve()\n .then(() => new XMLSerializer().serializeToString(svg))\n .then(encodeURIComponent)\n .then((html) => `data:image/svg+xml;charset=utf-8,${html}`);\n}\nexport async function nodeToDataURL(node, width, height) {\n const xmlns = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(xmlns, 'svg');\n const foreignObject = document.createElementNS(xmlns, 'foreignObject');\n svg.setAttribute('width', `${width}`);\n svg.setAttribute('height', `${height}`);\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n foreignObject.setAttribute('x', '0');\n foreignObject.setAttribute('y', '0');\n foreignObject.setAttribute('externalResourcesRequired', 'true');\n svg.appendChild(foreignObject);\n foreignObject.appendChild(node);\n return svgToDataURL(svg);\n}\nexport const isInstanceOfElement = (node, instance) => {\n if (node instanceof instance)\n return true;\n const nodePrototype = Object.getPrototypeOf(node);\n if (nodePrototype === null)\n return false;\n return (nodePrototype.constructor.name === instance.name ||\n isInstanceOfElement(nodePrototype, instance));\n};\n//# sourceMappingURL=util.js.map","import { uuid, toArray } from './util';\nfunction formatCSSText(style) {\n const content = style.getPropertyValue('content');\n return `${style.cssText} content: '${content.replace(/'|\"/g, '')}';`;\n}\nfunction formatCSSProperties(style) {\n return toArray(style)\n .map((name) => {\n const value = style.getPropertyValue(name);\n const priority = style.getPropertyPriority(name);\n return `${name}: ${value}${priority ? ' !important' : ''};`;\n })\n .join(' ');\n}\nfunction getPseudoElementStyle(className, pseudo, style) {\n const selector = `.${className}:${pseudo}`;\n const cssText = style.cssText\n ? formatCSSText(style)\n : formatCSSProperties(style);\n return document.createTextNode(`${selector}{${cssText}}`);\n}\nfunction clonePseudoElement(nativeNode, clonedNode, pseudo) {\n const style = window.getComputedStyle(nativeNode, pseudo);\n const content = style.getPropertyValue('content');\n if (content === '' || content === 'none') {\n return;\n }\n const className = uuid();\n try {\n clonedNode.className = `${clonedNode.className} ${className}`;\n }\n catch (err) {\n return;\n }\n const styleElement = document.createElement('style');\n styleElement.appendChild(getPseudoElementStyle(className, pseudo, style));\n clonedNode.appendChild(styleElement);\n}\nexport function clonePseudoElements(nativeNode, clonedNode) {\n clonePseudoElement(nativeNode, clonedNode, ':before');\n clonePseudoElement(nativeNode, clonedNode, ':after');\n}\n//# sourceMappingURL=clone-pseudos.js.map","const WOFF = 'application/font-woff';\nconst JPEG = 'image/jpeg';\nconst mimes = {\n woff: WOFF,\n woff2: WOFF,\n ttf: 'application/font-truetype',\n eot: 'application/vnd.ms-fontobject',\n png: 'image/png',\n jpg: JPEG,\n jpeg: JPEG,\n gif: 'image/gif',\n tiff: 'image/tiff',\n svg: 'image/svg+xml',\n webp: 'image/webp',\n};\nfunction getExtension(url) {\n const match = /\\.([^./]*?)$/g.exec(url);\n return match ? match[1] : '';\n}\nexport function getMimeType(url) {\n const extension = getExtension(url).toLowerCase();\n return mimes[extension] || '';\n}\n//# sourceMappingURL=mimes.js.map","function getContentFromDataUrl(dataURL) {\n return dataURL.split(/,/)[1];\n}\nexport function isDataUrl(url) {\n return url.search(/^(data:)/) !== -1;\n}\nexport function makeDataUrl(content, mimeType) {\n return `data:${mimeType};base64,${content}`;\n}\nexport async function fetchAsDataURL(url, init, process) {\n const res = await fetch(url, init);\n if (res.status === 404) {\n throw new Error(`Resource \"${res.url}\" not found`);\n }\n const blob = await res.blob();\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = reject;\n reader.onloadend = () => {\n try {\n resolve(process({ res, result: reader.result }));\n }\n catch (error) {\n reject(error);\n }\n };\n reader.readAsDataURL(blob);\n });\n}\nconst cache = {};\nfunction getCacheKey(url, contentType, includeQueryParams) {\n let key = url.replace(/\\?.*/, '');\n if (includeQueryParams) {\n key = url;\n }\n // font resource\n if (/ttf|otf|eot|woff2?/i.test(key)) {\n key = key.replace(/.*\\//, '');\n }\n return contentType ? `[${contentType}]${key}` : key;\n}\nexport async function resourceToDataURL(resourceUrl, contentType, options) {\n const cacheKey = getCacheKey(resourceUrl, contentType, options.includeQueryParams);\n if (cache[cacheKey] != null) {\n return cache[cacheKey];\n }\n // ref: https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache\n if (options.cacheBust) {\n // eslint-disable-next-line no-param-reassign\n resourceUrl += (/\\?/.test(resourceUrl) ? '&' : '?') + new Date().getTime();\n }\n let dataURL;\n try {\n const content = await fetchAsDataURL(resourceUrl, options.fetchRequestInit, ({ res, result }) => {\n if (!contentType) {\n // eslint-disable-next-line no-param-reassign\n contentType = res.headers.get('Content-Type') || '';\n }\n return getContentFromDataUrl(result);\n });\n dataURL = makeDataUrl(content, contentType);\n }\n catch (error) {\n dataURL = options.imagePlaceholder || '';\n let msg = `Failed to fetch resource: ${resourceUrl}`;\n if (error) {\n msg = typeof error === 'string' ? error : error.message;\n }\n if (msg) {\n console.warn(msg);\n }\n }\n cache[cacheKey] = dataURL;\n return dataURL;\n}\n//# sourceMappingURL=dataurl.js.map","import { clonePseudoElements } from './clone-pseudos';\nimport { createImage, toArray, isInstanceOfElement } from './util';\nimport { getMimeType } from './mimes';\nimport { resourceToDataURL } from './dataurl';\nasync function cloneCanvasElement(canvas) {\n const dataURL = canvas.toDataURL();\n if (dataURL === 'data:,') {\n return canvas.cloneNode(false);\n }\n return createImage(dataURL);\n}\nasync function cloneVideoElement(video, options) {\n if (video.currentSrc) {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n canvas.width = video.clientWidth;\n canvas.height = video.clientHeight;\n ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n const dataURL = canvas.toDataURL();\n return createImage(dataURL);\n }\n const poster = video.poster;\n const contentType = getMimeType(poster);\n const dataURL = await resourceToDataURL(poster, contentType, options);\n return createImage(dataURL);\n}\nasync function cloneIFrameElement(iframe) {\n var _a;\n try {\n if ((_a = iframe === null || iframe === void 0 ? void 0 : iframe.contentDocument) === null || _a === void 0 ? void 0 : _a.body) {\n return (await cloneNode(iframe.contentDocument.body, {}, true));\n }\n }\n catch (_b) {\n // Failed to clone iframe\n }\n return iframe.cloneNode(false);\n}\nasync function cloneSingleNode(node, options) {\n if (isInstanceOfElement(node, HTMLCanvasElement)) {\n return cloneCanvasElement(node);\n }\n if (isInstanceOfElement(node, HTMLVideoElement)) {\n return cloneVideoElement(node, options);\n }\n if (isInstanceOfElement(node, HTMLIFrameElement)) {\n return cloneIFrameElement(node);\n }\n return node.cloneNode(false);\n}\nconst isSlotElement = (node) => node.tagName != null && node.tagName.toUpperCase() === 'SLOT';\nasync function cloneChildren(nativeNode, clonedNode, options) {\n var _a, _b;\n let children = [];\n if (isSlotElement(nativeNode) && nativeNode.assignedNodes) {\n children = toArray(nativeNode.assignedNodes());\n }\n else if (isInstanceOfElement(nativeNode, HTMLIFrameElement) &&\n ((_a = nativeNode.contentDocument) === null || _a === void 0 ? void 0 : _a.body)) {\n children = toArray(nativeNode.contentDocument.body.childNodes);\n }\n else {\n children = toArray(((_b = nativeNode.shadowRoot) !== null && _b !== void 0 ? _b : nativeNode).childNodes);\n }\n if (children.length === 0 ||\n isInstanceOfElement(nativeNode, HTMLVideoElement)) {\n return clonedNode;\n }\n await children.reduce((deferred, child) => deferred\n .then(() => cloneNode(child, options))\n .then((clonedChild) => {\n if (clonedChild) {\n clonedNode.appendChild(clonedChild);\n }\n }), Promise.resolve());\n return clonedNode;\n}\nfunction cloneCSSStyle(nativeNode, clonedNode) {\n const targetStyle = clonedNode.style;\n if (!targetStyle) {\n return;\n }\n const sourceStyle = window.getComputedStyle(nativeNode);\n if (sourceStyle.cssText) {\n targetStyle.cssText = sourceStyle.cssText;\n targetStyle.transformOrigin = sourceStyle.transformOrigin;\n }\n else {\n toArray(sourceStyle).forEach((name) => {\n let value = sourceStyle.getPropertyValue(name);\n if (name === 'font-size' && value.endsWith('px')) {\n const reducedFont = Math.floor(parseFloat(value.substring(0, value.length - 2))) - 0.1;\n value = `${reducedFont}px`;\n }\n if (isInstanceOfElement(nativeNode, HTMLIFrameElement) &&\n name === 'display' &&\n value === 'inline') {\n value = 'block';\n }\n if (name === 'd' && clonedNode.getAttribute('d')) {\n value = `path(${clonedNode.getAttribute('d')})`;\n }\n targetStyle.setProperty(name, value, sourceStyle.getPropertyPriority(name));\n });\n }\n}\nfunction cloneInputValue(nativeNode, clonedNode) {\n if (isInstanceOfElement(nativeNode, HTMLTextAreaElement)) {\n clonedNode.innerHTML = nativeNode.value;\n }\n if (isInstanceOfElement(nativeNode, HTMLInputElement)) {\n clonedNode.setAttribute('value', nativeNode.value);\n }\n}\nfunction cloneSelectValue(nativeNode, clonedNode) {\n if (isInstanceOfElement(nativeNode, HTMLSelectElement)) {\n const clonedSelect = clonedNode;\n const selectedOption = Array.from(clonedSelect.children).find((child) => nativeNode.value === child.getAttribute('value'));\n if (selectedOption) {\n selectedOption.setAttribute('selected', '');\n }\n }\n}\nfunction decorate(nativeNode, clonedNode) {\n if (isInstanceOfElement(clonedNode, Element)) {\n cloneCSSStyle(nativeNode, clonedNode);\n clonePseudoElements(nativeNode, clonedNode);\n cloneInputValue(nativeNode, clonedNode);\n cloneSelectValue(nativeNode, clonedNode);\n }\n return clonedNode;\n}\nasync function ensureSVGSymbols(clone, options) {\n const uses = clone.querySelectorAll ? clone.querySelectorAll('use') : [];\n if (uses.length === 0) {\n return clone;\n }\n const processedDefs = {};\n for (let i = 0; i < uses.length; i++) {\n const use = uses[i];\n const id = use.getAttribute('xlink:href');\n if (id) {\n const exist = clone.querySelector(id);\n const definition = document.querySelector(id);\n if (!exist && definition && !processedDefs[id]) {\n // eslint-disable-next-line no-await-in-loop\n processedDefs[id] = (await cloneNode(definition, options, true));\n }\n }\n }\n const nodes = Object.values(processedDefs);\n if (nodes.length) {\n const ns = 'http://www.w3.org/1999/xhtml';\n const svg = document.createElementNS(ns, 'svg');\n svg.setAttribute('xmlns', ns);\n svg.style.position = 'absolute';\n svg.style.width = '0';\n svg.style.height = '0';\n svg.style.overflow = 'hidden';\n svg.style.display = 'none';\n const defs = document.createElementNS(ns, 'defs');\n svg.appendChild(defs);\n for (let i = 0; i < nodes.length; i++) {\n defs.appendChild(nodes[i]);\n }\n clone.appendChild(svg);\n }\n return clone;\n}\nexport async function cloneNode(node, options, isRoot) {\n if (!isRoot && options.filter && !options.filter(node)) {\n return null;\n }\n return Promise.resolve(node)\n .then((clonedNode) => cloneSingleNode(clonedNode, options))\n .then((clonedNode) => cloneChildren(node, clonedNode, options))\n .then((clonedNode) => decorate(node, clonedNode))\n .then((clonedNode) => ensureSVGSymbols(clonedNode, options));\n}\n//# sourceMappingURL=clone-node.js.map","import { resolveUrl } from './util';\nimport { getMimeType } from './mimes';\nimport { isDataUrl, makeDataUrl, resourceToDataURL } from './dataurl';\nconst URL_REGEX = /url\\((['\"]?)([^'\"]+?)\\1\\)/g;\nconst URL_WITH_FORMAT_REGEX = /url\\([^)]+\\)\\s*format\\(([\"']?)([^\"']+)\\1\\)/g;\nconst FONT_SRC_REGEX = /src:\\s*(?:url\\([^)]+\\)\\s*format\\([^)]+\\)[,;]\\s*)+/g;\nfunction toRegex(url) {\n // eslint-disable-next-line no-useless-escape\n const escaped = url.replace(/([.*+?^${}()|\\[\\]\\/\\\\])/g, '\\\\$1');\n return new RegExp(`(url\\\\(['\"]?)(${escaped})(['\"]?\\\\))`, 'g');\n}\nexport function parseURLs(cssText) {\n const urls = [];\n cssText.replace(URL_REGEX, (raw, quotation, url) => {\n urls.push(url);\n return raw;\n });\n return urls.filter((url) => !isDataUrl(url));\n}\nexport async function embed(cssText, resourceURL, baseURL, options, getContentFromUrl) {\n try {\n const resolvedURL = baseURL ? resolveUrl(resourceURL, baseURL) : resourceURL;\n const contentType = getMimeType(resourceURL);\n let dataURL;\n if (getContentFromUrl) {\n const content = await getContentFromUrl(resolvedURL);\n dataURL = makeDataUrl(content, contentType);\n }\n else {\n dataURL = await resourceToDataURL(resolvedURL, contentType, options);\n }\n return cssText.replace(toRegex(resourceURL), `$1${dataURL}$3`);\n }\n catch (error) {\n // pass\n }\n return cssText;\n}\nfunction filterPreferredFontFormat(str, { preferredFontFormat }) {\n return !preferredFontFormat\n ? str\n : str.replace(FONT_SRC_REGEX, (match) => {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const [src, , format] = URL_WITH_FORMAT_REGEX.exec(match) || [];\n if (!format) {\n return '';\n }\n if (format === preferredFontFormat) {\n return `src: ${src};`;\n }\n }\n });\n}\nexport function shouldEmbed(url) {\n return url.search(URL_REGEX) !== -1;\n}\nexport async function embedResources(cssText, baseUrl, options) {\n if (!shouldEmbed(cssText)) {\n return cssText;\n }\n const filteredCSSText = filterPreferredFontFormat(cssText, options);\n const urls = parseURLs(filteredCSSText);\n return urls.reduce((deferred, url) => deferred.then((css) => embed(css, url, baseUrl, options)), Promise.resolve(filteredCSSText));\n}\n//# sourceMappingURL=embed-resources.js.map","import { embedResources } from './embed-resources';\nimport { toArray, isInstanceOfElement } from './util';\nimport { isDataUrl, resourceToDataURL } from './dataurl';\nimport { getMimeType } from './mimes';\nasync function embedProp(propName, node, options) {\n var _a;\n const propValue = (_a = node.style) === null || _a === void 0 ? void 0 : _a.getPropertyValue(propName);\n if (propValue) {\n const cssString = await embedResources(propValue, null, options);\n node.style.setProperty(propName, cssString, node.style.getPropertyPriority(propName));\n return true;\n }\n return false;\n}\nasync function embedBackground(clonedNode, options) {\n if (!(await embedProp('background', clonedNode, options))) {\n await embedProp('background-image', clonedNode, options);\n }\n if (!(await embedProp('mask', clonedNode, options))) {\n await embedProp('mask-image', clonedNode, options);\n }\n}\nasync function embedImageNode(clonedNode, options) {\n const isImageElement = isInstanceOfElement(clonedNode, HTMLImageElement);\n if (!(isImageElement && !isDataUrl(clonedNode.src)) &&\n !(isInstanceOfElement(clonedNode, SVGImageElement) &&\n !isDataUrl(clonedNode.href.baseVal))) {\n return;\n }\n const url = isImageElement ? clonedNode.src : clonedNode.href.baseVal;\n const dataURL = await resourceToDataURL(url, getMimeType(url), options);\n await new Promise((resolve, reject) => {\n clonedNode.onload = resolve;\n clonedNode.onerror = reject;\n const image = clonedNode;\n if (image.decode) {\n image.decode = resolve;\n }\n if (image.loading === 'lazy') {\n image.loading = 'eager';\n }\n if (isImageElement) {\n clonedNode.srcset = '';\n clonedNode.src = dataURL;\n }\n else {\n clonedNode.href.baseVal = dataURL;\n }\n });\n}\nasync function embedChildren(clonedNode, options) {\n const children = toArray(clonedNode.childNodes);\n const deferreds = children.map((child) => embedImages(child, options));\n await Promise.all(deferreds).then(() => clonedNode);\n}\nexport async function embedImages(clonedNode, options) {\n if (isInstanceOfElement(clonedNode, Element)) {\n await embedBackground(clonedNode, options);\n await embedImageNode(clonedNode, options);\n await embedChildren(clonedNode, options);\n }\n}\n//# sourceMappingURL=embed-images.js.map","export function applyStyle(node, options) {\n const { style } = node;\n if (options.backgroundColor) {\n style.backgroundColor = options.backgroundColor;\n }\n if (options.width) {\n style.width = `${options.width}px`;\n }\n if (options.height) {\n style.height = `${options.height}px`;\n }\n const manual = options.style;\n if (manual != null) {\n Object.keys(manual).forEach((key) => {\n style[key] = manual[key];\n });\n }\n return node;\n}\n//# sourceMappingURL=apply-style.js.map","import { toArray } from './util';\nimport { fetchAsDataURL } from './dataurl';\nimport { shouldEmbed, embedResources } from './embed-resources';\nconst cssFetchCache = {};\nasync function fetchCSS(url) {\n let cache = cssFetchCache[url];\n if (cache != null) {\n return cache;\n }\n const res = await fetch(url);\n const cssText = await res.text();\n cache = { url, cssText };\n cssFetchCache[url] = cache;\n return cache;\n}\nasync function embedFonts(data, options) {\n let cssText = data.cssText;\n const regexUrl = /url\\([\"']?([^\"')]+)[\"']?\\)/g;\n const fontLocs = cssText.match(/url\\([^)]+\\)/g) || [];\n const loadFonts = fontLocs.map(async (loc) => {\n let url = loc.replace(regexUrl, '$1');\n if (!url.startsWith('https://')) {\n url = new URL(url, data.url).href;\n }\n return fetchAsDataURL(url, options.fetchRequestInit, ({ result }) => {\n cssText = cssText.replace(loc, `url(${result})`);\n return [loc, result];\n });\n });\n return Promise.all(loadFonts).then(() => cssText);\n}\nfunction parseCSS(source) {\n if (source == null) {\n return [];\n }\n const result = [];\n const commentsRegex = /(\\/\\*[\\s\\S]*?\\*\\/)/gi;\n // strip out comments\n let cssText = source.replace(commentsRegex, '');\n // eslint-disable-next-line prefer-regex-literals\n const keyframesRegex = new RegExp('((@.*?keyframes [\\\\s\\\\S]*?){([\\\\s\\\\S]*?}\\\\s*?)})', 'gi');\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const matches = keyframesRegex.exec(cssText);\n if (matches === null) {\n break;\n }\n result.push(matches[0]);\n }\n cssText = cssText.replace(keyframesRegex, '');\n const importRegex = /@import[\\s\\S]*?url\\([^)]*\\)[\\s\\S]*?;/gi;\n // to match css & media queries together\n const combinedCSSRegex = '((\\\\s*?(?:\\\\/\\\\*[\\\\s\\\\S]*?\\\\*\\\\/)?\\\\s*?@media[\\\\s\\\\S]' +\n '*?){([\\\\s\\\\S]*?)}\\\\s*?})|(([\\\\s\\\\S]*?){([\\\\s\\\\S]*?)})';\n // unified regex\n const unifiedRegex = new RegExp(combinedCSSRegex, 'gi');\n // eslint-disable-next-line no-constant-condition\n while (true) {\n let matches = importRegex.exec(cssText);\n if (matches === null) {\n matches = unifiedRegex.exec(cssText);\n if (matches === null) {\n break;\n }\n else {\n importRegex.lastIndex = unifiedRegex.lastIndex;\n }\n }\n else {\n unifiedRegex.lastIndex = importRegex.lastIndex;\n }\n result.push(matches[0]);\n }\n return result;\n}\nasync function getCSSRules(styleSheets, options) {\n const ret = [];\n const deferreds = [];\n // First loop inlines imports\n styleSheets.forEach((sheet) => {\n if ('cssRules' in sheet) {\n try {\n toArray(sheet.cssRules || []).forEach((item, index) => {\n if (item.type === CSSRule.IMPORT_RULE) {\n let importIndex = index + 1;\n const url = item.href;\n const deferred = fetchCSS(url)\n .then((metadata) => embedFonts(metadata, options))\n .then((cssText) => parseCSS(cssText).forEach((rule) => {\n try {\n sheet.insertRule(rule, rule.startsWith('@import')\n ? (importIndex += 1)\n : sheet.cssRules.length);\n }\n catch (error) {\n console.error('Error inserting rule from remote css', {\n rule,\n error,\n });\n }\n }))\n .catch((e) => {\n console.error('Error loading remote css', e.toString());\n });\n deferreds.push(deferred);\n }\n });\n }\n catch (e) {\n const inline = styleSheets.find((a) => a.href == null) || document.styleSheets[0];\n if (sheet.href != null) {\n deferreds.push(fetchCSS(sheet.href)\n .then((metadata) => embedFonts(metadata, options))\n .then((cssText) => parseCSS(cssText).forEach((rule) => {\n inline.insertRule(rule, sheet.cssRules.length);\n }))\n .catch((err) => {\n console.error('Error loading remote stylesheet', err);\n }));\n }\n console.error('Error inlining remote css file', e);\n }\n }\n });\n return Promise.all(deferreds).then(() => {\n // Second loop parses rules\n styleSheets.forEach((sheet) => {\n if ('cssRules' in sheet) {\n try {\n toArray(sheet.cssRules || []).forEach((item) => {\n ret.push(item);\n });\n }\n catch (e) {\n console.error(`Error while reading CSS rules from ${sheet.href}`, e);\n }\n }\n });\n return ret;\n });\n}\nfunction getWebFontRules(cssRules) {\n return cssRules\n .filter((rule) => rule.type === CSSRule.FONT_FACE_RULE)\n .filter((rule) => shouldEmbed(rule.style.getPropertyValue('src')));\n}\nasync function parseWebFontRules(node, options) {\n if (node.ownerDocument == null) {\n throw new Error('Provided element is not within a Document');\n }\n const styleSheets = toArray(node.ownerDocument.styleSheets);\n const cssRules = await getCSSRules(styleSheets, options);\n return getWebFontRules(cssRules);\n}\nexport async function getWebFontCSS(node, options) {\n const rules = await parseWebFontRules(node, options);\n const cssTexts = await Promise.all(rules.map((rule) => {\n const baseUrl = rule.parentStyleSheet ? rule.parentStyleSheet.href : null;\n return embedResources(rule.cssText, baseUrl, options);\n }));\n return cssTexts.join('\\n');\n}\nexport async function embedWebFonts(clonedNode, options) {\n const cssText = options.fontEmbedCSS != null\n ? options.fontEmbedCSS\n : options.skipFonts\n ? null\n : await getWebFontCSS(clonedNode, options);\n if (cssText) {\n const styleNode = document.createElement('style');\n const sytleContent = document.createTextNode(cssText);\n styleNode.appendChild(sytleContent);\n if (clonedNode.firstChild) {\n clonedNode.insertBefore(styleNode, clonedNode.firstChild);\n }\n else {\n clonedNode.appendChild(styleNode);\n }\n }\n}\n//# sourceMappingURL=embed-webfonts.js.map","import { cloneNode } from './clone-node';\nimport { embedImages } from './embed-images';\nimport { applyStyle } from './apply-style';\nimport { embedWebFonts, getWebFontCSS } from './embed-webfonts';\nimport { getImageSize, getPixelRatio, createImage, canvasToBlob, nodeToDataURL, checkCanvasDimensions, } from './util';\nexport async function toSvg(node, options = {}) {\n const { width, height } = getImageSize(node, options);\n const clonedNode = (await cloneNode(node, options, true));\n await embedWebFonts(clonedNode, options);\n await embedImages(clonedNode, options);\n applyStyle(clonedNode, options);\n const datauri = await nodeToDataURL(clonedNode, width, height);\n return datauri;\n}\nexport async function toCanvas(node, options = {}) {\n const { width, height } = getImageSize(node, options);\n const svg = await toSvg(node, options);\n const img = await createImage(svg);\n const canvas = document.createElement('canvas');\n const context = canvas.getContext('2d');\n const ratio = options.pixelRatio || getPixelRatio();\n const canvasWidth = options.canvasWidth || width;\n const canvasHeight = options.canvasHeight || height;\n canvas.width = canvasWidth * ratio;\n canvas.height = canvasHeight * ratio;\n if (!options.skipAutoScale) {\n checkCanvasDimensions(canvas);\n }\n canvas.style.width = `${canvasWidth}`;\n canvas.style.height = `${canvasHeight}`;\n if (options.backgroundColor) {\n context.fillStyle = options.backgroundColor;\n context.fillRect(0, 0, canvas.width, canvas.height);\n }\n context.drawImage(img, 0, 0, canvas.width, canvas.height);\n return canvas;\n}\nexport async function toPixelData(node, options = {}) {\n const { width, height } = getImageSize(node, options);\n const canvas = await toCanvas(node, options);\n const ctx = canvas.getContext('2d');\n return ctx.getImageData(0, 0, width, height).data;\n}\nexport async function toPng(node, options = {}) {\n const canvas = await toCanvas(node, options);\n return canvas.toDataURL();\n}\nexport async function toJpeg(node, options = {}) {\n const canvas = await toCanvas(node, options);\n return canvas.toDataURL('image/jpeg', options.quality || 1);\n}\nexport async function toBlob(node, options = {}) {\n const canvas = await toCanvas(node, options);\n const blob = await canvasToBlob(canvas);\n return blob;\n}\nexport async function getFontEmbedCSS(node, options = {}) {\n return getWebFontCSS(node, options);\n}\n//# sourceMappingURL=index.js.map","/**\n * The options to configure the Icon of the ImagePlaceholder\n * @typedef { Object } ImagePlaceholderIconOptions\n * @property { string } fill - The color to fill the svg icon with.\n * @property { string } height - The height of the svg icon.\n * @property { string } viewBox - The viewBox of the svg icon.\n * @property { string } width - The width of the svg icon.\n * @memberof ImagePlaceholder\n */\n\n/**\n * Returns svg element for image placeholder's icon\n * @param { ImagePlaceholderIconOptions } options - The options to configure the svg element.\n * @return {string } The HTML string with the SVG element for the image placeholder's icon.\n * @memberof ImagePlaceholder\n */\n\nexport default options => {\n\tconst defaults = {\n\t\tfill: '#B5B4C3',\n\t\theight: '42',\n\t\tviewBox: '0 0 46 42',\n\t\twidth: '46'\n\t};\n\n\toptions = {\n\t\t...defaults,\n\t\t...options\n\t};\n\n\treturn `\n\t\n\t\t\n\t\n\t`;\n};\n","import icon from './_buildSvg';\nimport { merge } from 'datatalks-utils';\n\n/**\n * The options to configure the HTML of the ImagePlaceholder\n * @typedef { Object } ImagePlaceholderHTMLOptions\n * @property { string } dimensionsDivider - The divider to display in between the recommended dimensions. Defaults to 'x' => 1920x1080.\n * @property { string } divider - The divider to display in between recommended dimensions and recommended size. Defaults to '•'.\n * @property { function | string } icon - The HTML string that displays the icon or a function that returns the HTML string.\n * @property { ImagePlaceholderIconOptions } iconOptions - The options to configure the icon if it uses the default icon.\n * @property { number } recommendedFileSize - The recommended width of the image.\n * @property { string } recommendedFileSizeUnit - The unit (suffix) of the recommended file size for the image.\n * @property { number } recommendedWidthRatio - The recommended ratio of image's width to height.\n * @property { number } recommendedHeightRatio - The recommended ratio of image's height to width.\n * @property { number } recommendedWidth - The recommended width in pixels for the image.\n * @property { boolean } showSpecsInBold - Whether or not to show recommended specs in a bold text.\n * @property { string } text - The text to display behind the recommended specs. Defaults to 'Recommended specs'.\n * @memberof ImagePlaceholder\n */\n\n/**\n * Returns HTML string for image placeholder\n * @param { ImagePlaceholderHTMLOptions } options - The options to configure the HTML element.\n * @return {string } The HTML string for the image placeholder.\n * @memberof ImagePlaceholder\n */\nexport default function (options) {\n\tconst defaults = {\n\t\talign: 'center',\n\t\tdimensionsDivider: 'x',\n\t\tdivider: '•',\n\t\ticon: icon,\n\t\ticonOptions: {\n\t\t\tfill: '#B5B4C3',\n\t\t\theight: '42',\n\t\t\tviewBox: '0 0 46 42',\n\t\t\twidth: '46'\n\t\t},\n\t\trecommendedFileSize: 20,\n\t\trecommendedFileSizeUnit: 'Kb',\n\t\trecommendedHeightRatio: 9,\n\t\trecommendedWidthRatio: 16,\n\t\trecommendedWidth: 2400,\n\t\tshowSpecsInBold: true,\n\t\ttext: 'Recommended specs'\n\t};\n\n\toptions = merge(defaults, options);\n\n\treturn `\n\t\t
\n\t\t\t
\n\t\t\t\t${\n\t\t\t\t\toptions.icon === defaults.icon\n\t\t\t\t\t\t? icon.call({}, options.iconOptions)\n\t\t\t\t\t\t: typeof options.icon === 'function'\n\t\t\t\t\t\t? icon()\n\t\t\t\t\t\t: icon\n\t\t\t\t}\n\t\t\t
\n\t\t\t
\n\t\t\t\t${options.text}\n\t\t\t\t${options.showSpecsInBold ? '' : ''}\n\t\t\t\t\t${parseInt(options.recommendedWidth)}\n\t\t\t\t\t${options.dimensionsDivider}\n\t\t\t\t\t${parseInt(\n\t\t\t\t\t\toptions.recommendedWidth *\n\t\t\t\t\t\t\t(options.recommendedHeightRatio /\n\t\t\t\t\t\t\t\toptions.recommendedWidthRatio)\n\t\t\t\t\t)}\n\t\t\t\t\t${options.divider}\n\t\t\t\t\t${options.recommendedFileSize}\n\t\t\t\t\t${options.recommendedFileSizeUnit}\n\t\t\t\t${options.showSpecsInBold ? '' : ''}\n\t\t\t
\n\t\t
\n\t`;\n}\n","import { noInteractionPreset } from '../_componentsUtils';\nimport { COMPONENTS_DEFAULTS } from '../../../config/_config';\nimport { merge } from 'datatalks-utils';\nimport { toPng } from 'html-to-image';\nimport html from './_buildHtml';\nimport { getImageSize, convertDataUnit } from 'datatalks-utils';\n\n/**\n * The options to configure the build of the ImagePlaceholder component\n * @typedef { Object } ImagePlaceholderBuildOptions\n * @property { object } attributes\n * @property { string } cssClass\n * @property { ImagePlaceholderHTMLOptions } imagePlaceholderHTMLOptions\n * @property { string } width\n * @memberof ImagePlaceholder\n */\n\n/**\n * Returns an image placeholder component build configured with the passed options\n * @param { ImagePlaceholderBuildOptions } componentOptions\n * @param { GrapesJS.Editor } editor\n * @return { ImagePlaceholderComponentBuild }\n * @memberof ImagePlaceholder\n */\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = {\n\t\tattributes: {},\n\t\tcssClass: 'gjs-comp-header',\n\t\timagePlaceholderHTMLOptions: {},\n\t\twidth: '100%',\n\t\tautoRecommendedWidth: true,\n\t\tdoubleDimensionValues: true,\n\t\tautoRecommendedFileSize: true\n\t};\n\n\tconst options = merge(defaults, componentOptions, COMPONENTS_DEFAULTS);\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\t...options,\n\t\t\t\ttagName: 'div',\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: options.width\n\t\t\t\t},\n\t\t\t\timagePlaceholderHTMLOptions:\n\t\t\t\t\toptions.imagePlaceholderHTMLOptions,\n\t\t\t\tphHtml: null,\n\t\t\t\tcomponents: comp => comp.componentRender(comp),\n\t\t\t\timgSrc: null\n\t\t\t\t// ...noInteractionPreset\n\t\t\t}),\n\n\t\t\tinit() {\n\t\t\t\tthis.updatePhHtml();\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\teditor.on('component:mount', component => {\n\t\t\t\t\tif (component === this)\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tthis.set('mounted', true);\n\t\t\t\t\t\t}, 3000);\n\t\t\t\t});\n\t\t\t},\n\n\t\t\tupdatePhHtml(recommendedWidth, recommendedFileSize) {\n\t\t\t\tif (recommendedWidth)\n\t\t\t\t\tthis.set('imagePlaceholderHTMLOptions', {\n\t\t\t\t\t\t...this.get('imagePlaceholderHTMLOptions'),\n\t\t\t\t\t\trecommendedWidth\n\t\t\t\t\t});\n\n\t\t\t\tif (recommendedFileSize) {\n\t\t\t\t\tlet recommendedFileSizeUnit = 'Kb';\n\n\t\t\t\t\tif (recommendedFileSize.toString().length > 9) {\n\t\t\t\t\t\trecommendedFileSizeUnit = 'Tb';\n\t\t\t\t\t\trecommendedFileSize = parseInt(\n\t\t\t\t\t\t\trecommendedFileSize / 1000000000\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (recommendedFileSize.toString().length > 6) {\n\t\t\t\t\t\trecommendedFileSizeUnit = 'Gb';\n\t\t\t\t\t\trecommendedFileSize = parseInt(\n\t\t\t\t\t\t\trecommendedFileSize / 1000000\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (recommendedFileSize.toString().length > 3) {\n\t\t\t\t\t\trecommendedFileSizeUnit = 'Mb';\n\t\t\t\t\t\trecommendedFileSize = parseInt(\n\t\t\t\t\t\t\trecommendedFileSize / 1000\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.set('imagePlaceholderHTMLOptions', {\n\t\t\t\t\t\t...this.get('imagePlaceholderHTMLOptions'),\n\t\t\t\t\t\trecommendedFileSize,\n\t\t\t\t\t\trecommendedFileSizeUnit\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tthis.set(\n\t\t\t\t\t'phHtml',\n\t\t\t\t\thtml.call(null, this.get('imagePlaceholderHTMLOptions'))\n\t\t\t\t);\n\t\t\t},\n\n\t\t\tupdated(prop) {\n\t\t\t\tif (prop === 'mounted' && this.isHtml()) {\n\t\t\t\t\tthis.convertToImage();\n\t\t\t\t}\n\t\t\t\tif (prop === 'imagePlaceholderHTMLOptions') {\n\t\t\t\t\tthis.updatePhHtml();\n\t\t\t\t\tthis.updateImage();\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tisHtml() {\n\t\t\t\treturn this.getEl()?.firstChild?.hasAttribute('data-ph');\n\t\t\t},\n\n\t\t\tcomponentRender: comp => {\n\t\t\t\tif (comp.attributes.imgSrc) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'image',\n\t\t\t\t\t\tsrc: comp.attributes.imgSrc\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn comp.get('phHtml');\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tupdateImage() {\n\t\t\t\tthis.set('imgSrc', null);\n\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\tthis.convertToImage();\n\t\t\t},\n\n\t\t\tconvertToImage() {\n\t\t\t\tlet width =\n\t\t\t\t\toptions.imagePlaceholderHTMLOptions.recommendedWidth;\n\t\t\t\tlet size =\n\t\t\t\t\toptions.imagePlaceholderHTMLOptions.recommendedFileSize;\n\n\t\t\t\tif (options.autoRecommendedWidth)\n\t\t\t\t\twidth =\n\t\t\t\t\t\tthis.getEl().clientWidth *\n\t\t\t\t\t\t(options.doubleDimensionValues ? 2 : 1);\n\n\t\t\t\tif (options.autoRecommendedFileSize)\n\t\t\t\t\tsize = this.updatePhHtml(width, size);\n\n\t\t\t\ttoPng(this.getEl().firstChild)\n\t\t\t\t\t.then(dataUrl => {\n\t\t\t\t\t\tthis.set('imgSrc', dataUrl);\n\t\t\t\t\t\tthis.components(this.componentRender(this));\n\t\t\t\t\t})\n\t\t\t\t\t.catch(function (error) {\n\t\t\t\t\t\tconsole.error('oops, something went wrong!', error);\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n};\n","import { validateStyleObj } from '../../../common/functions/_utilFunctions';\nimport { cssSidesToObject, extractPlainText, isHTML } from 'datatalks-utils';\n\nexport default comp => {\n\tconst getGeneralStyle = comp\n\t\t.getEditor()\n\t\t.getStyleRules.bind(comp.getEditor(), 'button');\n\tconst generalStyleProp = comp\n\t\t.getEditor()\n\t\t.getEmailBuilder()\n\t\t.getStyleProp('buttons');\n\n\tlet lineHeight = comp.get('lineHeight') || generalStyleProp.lineHeight;\n\tif (\n\t\tlineHeight ===\n\t\tcomp.getEditor().getEmailBuilder().getLineHeightTypes().auto\n\t) {\n\t\tlineHeight = getAutoLineHeight();\n\t} else if (\n\t\tlineHeight ===\n\t\tcomp.getEditor().getEmailBuilder().getLineHeightTypes().sameAsHeight\n\t) {\n\t\tlineHeight = comp.get('height') || getGeneralStyle('height');\n\t}\n\n\t/**\n\t * Calculates the auto line height for the button component.\n\t * @return {string} The calculated auto line height.\n\t */\n\tfunction getAutoLineHeight() {\n\t\tconst borderWidth =\n\t\t\tcomp.get('borderWidth') || getGeneralStyle('border-width') || '0px';\n\t\tconst height = comp.get('height') || generalStyleProp.height || '40px';\n\t\tconst padding =\n\t\t\tcomp.get('padding') ||\n\t\t\t[\n\t\t\t\tgeneralStyleProp.paddings.top || '0px',\n\t\t\t\tgeneralStyleProp.paddings.right || '0px',\n\t\t\t\tgeneralStyleProp.paddings.bottom || '0px',\n\t\t\t\tgeneralStyleProp.paddings.left || '0px'\n\t\t\t].join(' ');\n\t\treturn (\n\t\t\tparseFloat(height) -\n\t\t\t(cssSidesToObject(padding).top +\n\t\t\t\tcssSidesToObject(padding).bottom +\n\t\t\t\tcssSidesToObject(borderWidth).top +\n\t\t\t\tcssSidesToObject(borderWidth).bottom) +\n\t\t\t'px'\n\t\t);\n\t}\n\n\tcomp.setStyle(\n\t\tvalidateStyleObj({\n\t\t\t'background-color': comp.get('backgroundColor'),\n\t\t\t'font-family': comp.get('fontFamily'),\n\t\t\t'font-size': comp.get('fontSize'),\n\t\t\t'font-style': comp.get('fontStyle'),\n\t\t\tcolor: comp.get('color'),\n\t\t\t'font-weight': comp.get('fontWeight'),\n\t\t\t'border-width': comp.get('borderWidth'),\n\t\t\t'border-style': comp.get('borderStyle'),\n\t\t\t'border-color': comp.get('borderColor'),\n\t\t\t'border-radius': comp.get('useBorderRadius')\n\t\t\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t\t\t: null,\n\t\t\t'min-height': comp.get('height'),\n\t\t\theight: 'auto',\n\t\t\twidth: comp.get('width'),\n\t\t\t'text-align': comp.get('textAlignment'),\n\t\t\t'line-height': lineHeight,\n\t\t\t'text-decoration-line': comp.get('textDecorationLine')\n\t\t})\n\t);\n\n\treturn {\n\t\ttype: 'textnode',\n\t\tcontent: isHTML(comp.get('text'))\n\t\t\t? extractPlainText(comp.get('text'))\n\t\t\t: comp.get('text')\n\t};\n};\n","import {\n\tvalidateStyleObj,\n\tvalidateBorder\n} from '../../../common/functions/_utilFunctions';\nimport { cssSidesToObject, isValidDimension } from 'datatalks-utils';\n\nexport default comp => {\n\tconst getGeneralStyle = comp\n\t\t.getEditor()\n\t\t.getStyleRules.bind(comp.getEditor(), 'button');\n\tconst getStyleProp = comp\n\t\t.getEditor()\n\t\t.getEmailBuilder()\n\t\t.getStyleProp.bind(comp.getEditor().getEmailBuilder(), 'buttons');\n\tconst borderRadius = comp.get('useBorderRadius')\n\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t: [\n\t\t\t\tgetGeneralStyle('border-top-left-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-top-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-right-radius') || 0,\n\t\t\t\tgetGeneralStyle('border-bottom-left-radius') || 0\n\t\t ].join(' ');\n\tconst padding =\n\t\tcomp.get('padding') ||\n\t\t[\n\t\t\tgetGeneralStyle('padding-top') || 0,\n\t\t\tgetGeneralStyle('padding-right') || 0,\n\t\t\tgetGeneralStyle('padding-bottom') || 0,\n\t\t\tgetGeneralStyle('padding-left') || 0\n\t\t].join(' ');\n\n\tconst borderWidth =\n\t\tcomp.get('borderWidth') || getGeneralStyle('border-width') || '0px';\n\tconst height = comp.get('height') || getStyleProp().height;\n\n\tlet lineHeight =\n\t\tcomp.get('lineHeight') ||\n\t\tcomp.getEditor().getEmailBuilder().getStyleProp('buttons').lineHeight;\n\tif (\n\t\tlineHeight ===\n\t\tcomp.getEditor().getEmailBuilder().getLineHeightTypes().auto\n\t) {\n\t\tlineHeight =\n\t\t\tparseFloat(height) -\n\t\t\t(cssSidesToObject(padding).top +\n\t\t\t\tcssSidesToObject(padding).bottom +\n\t\t\t\tcssSidesToObject(borderWidth).top +\n\t\t\t\tcssSidesToObject(borderWidth).bottom) +\n\t\t\t'px';\n\t} else if (\n\t\tlineHeight ===\n\t\tcomp.getEditor().getEmailBuilder().getLineHeightTypes().sameAsHeight\n\t) {\n\t\tlineHeight = height;\n\t}\n\n\tconst style = {\n\t\t'background-color':\n\t\t\tcomp.get('backgroundColor') || getGeneralStyle('background-color'),\n\t\t'font-size':\n\t\t\tcomp.get('fontSize') ||\n\t\t\tcomp.getEditor().getStyleRules('wrapper', 'font-size'),\n\t\t'min-height': height,\n\t\t'line-height': lineHeight,\n\t\twidth: isValidDimension(comp.get('width'), {\n\t\t\tacceptableValues: ['auto']\n\t\t})\n\t\t\t? comp.get('width')\n\t\t\t: '100%',\n\t\t'font-family': comp.get('fontFamily') || getGeneralStyle('font-family'),\n\t\tcolor: comp.get('color') || getGeneralStyle('color'),\n\t\t'font-weight': comp.get('fontWeight') || getGeneralStyle('font-weight'),\n\t\t'border-width': borderWidth,\n\t\t'border-style': comp.get('borderStyle'),\n\t\t'border-color': comp.get('borderColor'),\n\t\t'border-radius': borderRadius,\n\t\t'text-align': comp.get('textAlignment'),\n\t\t'vertical-align': 'middle',\n\t\tdisplay: 'inline-block',\n\t\t'mso-padding-alt': 0,\n\t\tpadding,\n\t\t'text-decoration': comp.get('textDecorationLine') || 'none',\n\t\t'font-style': comp.get('fontStyle')\n\t};\n\n\treturn validateStyleObj(validateBorder(style));\n};\n","import {\n\tcssSidesToObject,\n\tcssCornersToObject,\n\tmerge,\n\tarrayAvg,\n\tcssStyleObjectToString,\n\thtmlToElement,\n\tisElement,\n\trenderNotMsoConditional,\n\trenderMsoConditional,\n\tisHTML,\n\tgetUnit\n} from 'datatalks-utils';\nimport { validateStyleObj } from '../../../common/functions/_utilFunctions';\nimport getComputedStyle from './_getComputedStyle';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\toutlookDebug: false,\n\t\tstyle: getComputedStyle(comp),\n\t\ttext: comp.get('text'),\n\t\thref: comp.get('href'),\n\t\tparentWidth: null,\n\t\thasOutlookBorderRadius: comp.get('hasOutlookBorderRadius') || false\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst isPlainText = !isHTML(options.text) || true;\n\tconst isVMLButton =\n\t\toptions.style.width != 'auto' ||\n\t\toptions.hasOutlookBorderRadius ||\n\t\t!isPlainText;\n\tconst paddingSide = cssSidesToObject(options.style.padding);\n\n\t// Outlook VML CALCULATIONS\n\tconst getOutlookVMLButton = () => {\n\t\tconst height = options.style['min-height'];\n\t\tconst isBorderVisible = !(\n\t\t\t!options.style['border-width'] ||\n\t\t\t!options.style['border-color'] ||\n\t\t\tparseFloat(options.style['border-width']) < 0.1 ||\n\t\t\toptions.style['border-color'] == 'transparent'\n\t\t);\n\n\t\tconst borderWidthSide = options.style['border-width']\n\t\t\t? parseFloat(options.style['border-width']) || 0\n\t\t\t: 0;\n\t\tconst msoButtonWidth =\n\t\t\toptions.style.width == 'auto'\n\t\t\t\t? parseFloat(comp.get('outlookWidth')) || 150\n\t\t\t\t: getUnit(options.style.width) == '%'\n\t\t\t\t? parseFloat(options.parentWidth) *\n\t\t\t\t (parseFloat(options.style.width) / 100)\n\t\t\t\t: parseFloat(options.style.width);\n\n\t\tconst msoHeight =\n\t\t\theight == 'auto'\n\t\t\t\t? paddingSide.top +\n\t\t\t\t 2 * borderWidthSide +\n\t\t\t\t parseFloat(options.style['font-size']) +\n\t\t\t\t 'px'\n\t\t\t\t: height;\n\t\tconst msoInnerHeight =\n\t\t\tparseFloat(msoHeight) -\n\t\t\t((borderRadiusRatio <= 50 ? borderRadiusRatio : 50) *\n\t\t\t\tparseFloat(height)) /\n\t\t\t\t200 -\n\t\t\t(isBorderVisible ? borderWidthSide : 0) +\n\t\t\t'px';\n\n\t\tconst borderRadiusCorner = cssCornersToObject(\n\t\t\toptions.style['border-radius']\n\t\t);\n\t\tconst borderRadiusRatio = comp.get('useBorderRadius')\n\t\t\t? (arrayAvg(Object.values(borderRadiusCorner)) * 100) /\n\t\t\t parseFloat(msoHeight)\n\t\t\t: 0;\n\n\t\t// TODO: improve this -> temporary fix\n\t\toptions.msoText = options.text;\n\t\tif (validateStyleObj(options.style)['line-height']) {\n\t\t\tconst textEl = htmlToElement(options.text);\n\t\t\tif (isElement(textEl)) {\n\t\t\t\ttextEl.style.lineHeight = validateStyleObj(options.style)[\n\t\t\t\t\t'line-height'\n\t\t\t\t];\n\t\t\t\toptions.text = textEl.outerHTML;\n\t\t\t}\n\t\t}\n\t\treturn `\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t${options.msoText}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t`;\n\t};\n\n\tconst getOutlookPadding = side => {\n\t\tlet padding =\n\t\t\tside == 'x'\n\t\t\t\t? paddingSide.left + paddingSide.right\n\t\t\t\t: side == 'y'\n\t\t\t\t? paddingSide.top + paddingSide.bottom\n\t\t\t\t: paddingSide[side];\n\n\t\tif (\n\t\t\toptions.style.height != 'auto' &&\n\t\t\t(side == 'y' || side == 'top' || side == 'bottom')\n\t\t) {\n\t\t\tpadding =\n\t\t\t\tparseFloat(options.style['min-height']) -\n\t\t\t\tparseFloat(options.style['font-size']);\n\t\t\tif (side == 'top' || side == 'bottom') {\n\t\t\t\tpadding = padding / 2;\n\t\t\t}\n\t\t}\n\n\t\treturn (padding / parseFloat(options.style['font-size'])) * 100 + '%';\n\t};\n\n\tconst innerHtml = `\n\t<${options.href ? 'a' : 'span'} ${\n\t\toptions.debug ? 'data-eb-name=\"button-last\"' : ''\n\t}\n\t\tclass=\"ebr-button\"\n\t\t${options.href ? `href=\"${options.href}\"` : ''}\n\t\tstyle=\"${cssStyleObjectToString(validateStyleObj(options.style))}\">\n\t\t${\n\t\t\tisVMLButton\n\t\t\t\t? ''\n\t\t\t\t: renderMsoConditional(\n\t\t\t\t\t\t``,\n\t\t\t\t\t\toptions.outlookDebug\n\t\t\t\t )\n\t\t}\n\t\t${\n\t\t\tisPlainText\n\t\t\t\t? options.text\n\t\t\t\t: options.text.replace(\n\t\t\t\t\t\t// TODO: find a better way to handle this\n\t\t\t\t\t\t/"/g,\n\t\t\t\t\t\t\"'\"\n\t\t\t\t )\n\t\t}\n\t\t${\n\t\t\tisVMLButton\n\t\t\t\t? ''\n\t\t\t\t: renderMsoConditional(\n\t\t\t\t\t\t``,\n\t\t\t\t\t\toptions.outlookDebug\n\t\t\t\t )\n\t\t}\n\t\n\t`;\n\n\tconst html = `\n\t
\n\t${\n\t\tisVMLButton\n\t\t\t? renderNotMsoConditional(innerHtml, options.outlookDebug) +\n\t\t\t renderMsoConditional(getOutlookVMLButton(), options.outlookDebug)\n\t\t\t: innerHtml\n\t}\n\t
\n\t`;\n\n\tif (options.debug) console.log('List HTML: ', html);\n\n\treturn html;\n};\n","import { COMPONENTS_DEFAULTS } from '../../../../config/_config';\nimport render from './_render';\nimport { getComponentsDefaultsByType } from '../../../componentsDefaults/_componentsDefaults';\nimport baseMethods from '../../common/methods/_baseMethods';\nimport toHtml from './_toHtml';\nimport { merge } from 'datatalks-utils';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = getComponentsDefaultsByType('button');\n\n\tconst options = {\n\t\t...COMPONENTS_DEFAULTS,\n\t\t...defaults,\n\t\t...componentOptions,\n\t\tisListeningGeneralStyles: false\n\t};\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\t...options,\n\t\t\t\tname: options.name,\n\t\t\t\ttagName: options.tagName,\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tcssClass: options.cssClass,\n\t\t\t\tcontent: options.text,\n\t\t\t\tcomponents: comp => comp.componentRender(comp)\n\t\t\t}),\n\n\t\t\ttoHTML(toHtmlOpts = {}) {\n\t\t\t\treturn toHtml(this, merge(options.toHtmlOptions, toHtmlOpts));\n\t\t\t},\n\n\t\t\tcomponentRender: render,\n\t\t\t...baseMethods(componentOptions, editor)\n\t\t}\n\t};\n};\n","import { validateStyleObj } from '../../../common/functions/_utilFunctions';\nimport { getHTMLTags } from 'datatalks-utils';\n\nexport default comp => {\n\tif (comp.get('width') === 'auto') {\n\t\tcomp.set('width', '100%');\n\t}\n\n\tcomp.setStyle(\n\t\tvalidateStyleObj({\n\t\t\t'background-color': comp.get('backgroundColor'),\n\t\t\t'font-family': comp.get('fontFamily'),\n\t\t\tcolor: comp.get('color'),\n\t\t\t'font-weight': comp.get('fontWeight'),\n\t\t\t'border-width': comp.get('borderWidth'),\n\t\t\t'border-style': comp.get('borderStyle'),\n\t\t\t'border-color': comp.get('borderColor'),\n\t\t\t'text-align': comp.get('textAlign'),\n\t\t\twidth: comp.get('width'),\n\t\t\t'border-radius': comp.get('useBorderRadius')\n\t\t\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t\t\t: '0px'\n\t\t})\n\t);\n\n\tconst tag = getHTMLTags(comp.get('text'), true)[0];\n\tif (tag) comp.set('tagName', tag);\n\tcomp.set('content', comp.get('text'));\n\n\treturn null;\n};\n","import {\n\tvalidateStyleObj,\n\tvalidateBorder\n} from '../../../common/functions/_utilFunctions';\n\nexport default comp => {\n\tconst style = {\n\t\t'background-color': comp.get('backgroundColor'),\n\t\t'font-family': comp.get('fontFamily'),\n\t\tcolor: comp.get('color'),\n\t\t'font-weight': comp.get('fontWeight'),\n\t\t'border-width': comp.get('borderWidth'),\n\t\t'border-style': comp.get('borderStyle'),\n\t\t'border-color': comp.get('borderColor'),\n\t\t'text-align': comp.get('textAlign'),\n\t\twidth: comp.get('width'),\n\t\t'border-radius': comp.get('useBorderRadius')\n\t\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t\t: null,\n\t\tdisplay: 'block'\n\t};\n\n\treturn validateStyleObj(validateBorder(style));\n};\n","import {\n\tmerge,\n\tisHTML,\n\tsetNodeStyle,\n\tsetContent,\n\tcssStyleDeclarationToObject as styleToObj\n} from 'datatalks-utils';\nimport getComputedStyle from './_getComputedStyle';\nimport { validateStyleObj } from '../../../common/functions/_utilFunctions';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tstyle: getComputedStyle(comp),\n\t\ttext: comp.get('text'),\n\t\tparentWidth: null\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tif (!isHTML(options.text)) options.text = `

${options.text}

`;\n\n\tconst aux = setContent(document.createElement('div'), options.text);\n\tsetNodeStyle(\n\t\taux.childNodes[0],\n\t\tmerge(\n\t\t\tvalidateStyleObj(options.style),\n\t\t\tstyleToObj(aux.childNodes[0].style)\n\t\t)\n\t);\n\tconst html = aux.innerHTML.replace(/"/g, \"'\"); // TODO: find a better way to handle this\n\n\tif (options.debug) console.log('Text HTML: ', html);\n\n\treturn html;\n};\n","import { COMPONENTS_DEFAULTS } from '../../../../config/_config';\nimport render from './_render';\nimport { getComponentsDefaultsByType } from '../../../componentsDefaults/_componentsDefaults';\nimport baseMethods from '../../common/methods/_baseMethods';\nimport { merge } from 'datatalks-utils';\nimport toHtml from './_toHtml';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = getComponentsDefaultsByType('text');\n\n\tconst options = merge(COMPONENTS_DEFAULTS, defaults, componentOptions);\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\t...options,\n\t\t\t\tname: options.name,\n\t\t\t\ttagName: options.tagName,\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tcontent: options.text,\n\t\t\t\tcomponents: comp => comp.componentRender(comp)\n\t\t\t}),\n\n\t\t\ttoHTML(toHtmlOptions = {}) {\n\t\t\t\treturn toHtml(\n\t\t\t\t\tthis,\n\t\t\t\t\tmerge(options.toHtmlOptions, toHtmlOptions)\n\t\t\t\t);\n\t\t\t},\n\n\t\t\tcomponentRender: render,\n\t\t\t...baseMethods(componentOptions, editor)\n\t\t}\n\t};\n};\n","import { svgToBase64 } from 'datatalks-utils';\nimport { validateStyleObj } from '../../../common/functions/_utilFunctions';\n\nexport default comp => {\n\tconst imageStyle = validateStyleObj({\n\t\t'background-color': comp.get('backgroundColor'),\n\t\t'border-width': comp.get('borderWidth'),\n\t\t'border-style': comp.get('borderStyle'),\n\t\t'border-color': comp.get('borderColor'),\n\t\t'border-radius': comp.get('useBorderRadius')\n\t\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t\t: 0,\n\t\twidth: comp.get('imgWidth'),\n\t\t'text-align': comp.get('alignment')\n\t});\n\n\tif (comp.get('hasLink')) {\n\t\tif (comp.get('tagName') !== 'a') comp.set('tagName', 'a');\n\t\tif (comp.get('href')) {\n\t\t\tcomp.addAttributes({ href: comp.get('href') });\n\t\t}\n\t\tcomp.setStyle({\n\t\t\t...comp.getStyle(),\n\t\t\tdisplay: 'inline-block'\n\t\t});\n\n\t\treturn [\n\t\t\t{\n\t\t\t\ttype: 'image',\n\t\t\t\tsrc: comp.get('imgSrc'),\n\t\t\t\tstyle: imageStyle\n\t\t\t}\n\t\t];\n\t} else {\n\t\tif (comp.get('tagName') !== 'img') comp.set('tagName', 'img');\n\t\tcomp.setStyle(imageStyle);\n\n\t\tif (!comp.get('imgSrc')) {\n\t\t\tcomp.addAttributes({ src: svgToBase64(comp.get('fallback')) });\n\t\t} else {\n\t\t\tcomp.addAttributes({ src: comp.get('imgSrc') });\n\t\t}\n\n\t\treturn [];\n\t}\n};\n","import {\n\tvalidateStyleObj,\n\tvalidateBorder\n} from '../../../common/functions/_utilFunctions';\n\nexport default comp => {\n\tconst style = {\n\t\t'background-color': comp.get('backgroundColor'),\n\t\twidth: comp.get('imgWidth'),\n\t\t'border-width': comp.get('borderWidth'),\n\t\t'border-style': comp.get('borderStyle'),\n\t\t'border-color': comp.get('borderColor'),\n\t\t'border-radius': comp.get('useBorderRadius')\n\t\t\t? Object.values(comp.get('borderRadius')).join(' ')\n\t\t\t: null,\n\t\t'text-align': comp.get('alignment'),\n\t\tdisplay: 'inline-block'\n\t};\n\n\treturn validateStyleObj(validateBorder(style));\n};\n","import {\n\tmerge,\n\tcssStyleObjectToString,\n\tdeleteProps,\n\tgetUnit\n} from 'datatalks-utils';\nimport getComputedStyle from './_getComputedStyle';\nimport { validateStyleObj } from '../../../common/functions/_utilFunctions';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tstyle: getComputedStyle(comp),\n\t\tsrc: comp.get('imgSrc'),\n\t\talt: comp.get('alternateText'),\n\t\tparentWidth: null,\n\t\thasLink: comp.get('hasLink'),\n\t\thref: comp.get('href')\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst tableStyle = deleteProps(\n\t\toptions.style,\n\t\t[\n\t\t\t'display',\n\t\t\t'background-color',\n\t\t\t'border-radius',\n\t\t\t'border-width',\n\t\t\t'border-style',\n\t\t\t'border-color'\n\t\t],\n\t\tfalse\n\t);\n\n\tconst cellStyle = deleteProps(\n\t\toptions.style,\n\t\t['display', 'text-align', 'width'],\n\t\tfalse\n\t);\n\n\tconst imageHasLink = options.hasLink && !!options.href;\n\n\t/**\n\t * Calculates the width of the image based on the provided options and parent width.\n\t * @return {number} The calculated width of the image.\n\t */\n\tfunction getImageWidth() {\n\t\tif (getUnit(options.style.width) === 'px')\n\t\t\treturn parseFloat(options.style.width);\n\n\t\treturn (\n\t\t\tparseFloat(comp.get('renderWidth')) ||\n\t\t\t(parseFloat(options.style.width) / 100) *\n\t\t\t\tparseFloat(options.parentWidth)\n\t\t);\n\t}\n\n\tconst msoImage = `\"${\n\t\toptions.alt\n\t}\"`;\n\n\tconst image = `\"${options.alt}\"`;\n\n\tconst html = `\n\t\t\n\t\t\t${imageHasLink ? `` : ''}\n\t\t\n\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t${image}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\n\t\t\t${imageHasLink ? '' : ''}\n\t\t\n\t\t`;\n\n\tif (options.debug) console.log('List HTML: ', html);\n\n\treturn html;\n};\n","import { COMPONENTS_DEFAULTS } from '../../../../config/_config';\nimport render from './_render';\nimport { getComponentsDefaultsByType } from '../../../componentsDefaults/_componentsDefaults';\nimport baseMethods from '../../common/methods/_baseMethods';\nimport { merge } from 'datatalks-utils';\nimport toHtml from './_toHtml';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = getComponentsDefaultsByType('image-wrapper');\n\n\tconst options = merge(COMPONENTS_DEFAULTS, defaults, componentOptions);\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\t...options,\n\t\t\t\tname: options.name,\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\tclass: options.cssClass,\n\t\t\t\t\tsrc: options.imgSrc\n\t\t\t\t},\n\t\t\t\tcomponents: comp => comp.componentRender(comp)\n\t\t\t}),\n\n\t\t\tcache: false,\n\n\t\t\ttoHTML(toHtmlOptions = {}) {\n\t\t\t\treturn toHtml(\n\t\t\t\t\tthis,\n\t\t\t\t\tmerge(options.toHtmlOptions, toHtmlOptions)\n\t\t\t\t);\n\t\t\t},\n\n\t\t\tcomponentRender: render,\n\t\t\t...baseMethods(options, editor)\n\t\t}\n\t};\n};\n","export default comp => {\n\tconst style = {\n\t\t...comp.getStyle(),\n\t\t'background-color': comp.get('color'),\n\t\t['mso-line-height-rule']: 'exactly'\n\t};\n\n\tif (['td', 'tr'].includes(comp.get('tagName'))) {\n\t\tif (comp.get('isVertical')) {\n\t\t\tcomp.set('tagName', 'tr');\n\t\t\tcomp.set('style', {\n\t\t\t\t...style,\n\t\t\t\t['line-height']: comp.get('dimension'),\n\t\t\t\theight: comp.get('dimension'),\n\t\t\t\twidth: '100%'\n\t\t\t});\n\t\t} else {\n\t\t\tcomp.set('tagName', 'td');\n\t\t\tdelete style['height'];\n\t\t\tcomp.set('style', {\n\t\t\t\t...style,\n\t\t\t\twidth: comp.get('dimension'),\n\t\t\t\t['min-width']: comp.get('dimension')\n\t\t\t});\n\t\t}\n\t}\n\n\tif (comp.get('tagName') === 'table') {\n\t\treturn {\n\t\t\ttype: 'row',\n\t\t\tcomponents: {\n\t\t\t\ttype: 'cell',\n\t\t\t\tstyle: comp.get('isVertical')\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...style,\n\t\t\t\t\t\t\theight: comp.get('dimension'),\n\t\t\t\t\t\t\t['line-height']: comp.get('dimension'),\n\t\t\t\t\t\t\twidth: '100%'\n\t\t\t\t\t }\n\t\t\t\t\t: {\n\t\t\t\t\t\t\t...style,\n\t\t\t\t\t\t\twidth: comp.get('dimension'),\n\t\t\t\t\t\t\t['min-width']: comp.get('dimension')\n\t\t\t\t\t },\n\t\t\t\tcomponents: []\n\t\t\t}\n\t\t};\n\t}\n\n\treturn [];\n};\n","import { merge, isValidColor } from 'datatalks-utils';\nimport { toHex } from 'color2k';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tcolor: comp.get('color'),\n\t\tsize: comp.get('dimension'),\n\t\tparentWidth: null,\n\t\tconvertColorsToHex: true,\n\t\tisVertical: comp.get('isVertical')\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tif (options.convertColorsToHex && isValidColor(options.color))\n\t\toptions.color = toHex(options.color);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst html = options.isVertical\n\t\t? `\n\t\t
\n\t`\n\t\t: `\n\t`;\n\n\tif (options.debug) console.log('Space HTML: ', html);\n\n\treturn html;\n};\n","import { COMPONENTS_DEFAULTS } from '../../../../config/_config';\nimport render from './_render';\nimport baseMethods from '../../common/methods/_baseMethods';\nimport { getComponentsDefaultsByType } from '../../../componentsDefaults/_componentsDefaults';\nimport { merge } from 'datatalks-utils';\nimport toHtml from './_toHtml';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = getComponentsDefaultsByType('space');\n\n\tconst options = {\n\t\t...COMPONENTS_DEFAULTS,\n\t\t...defaults,\n\t\t...componentOptions\n\t};\n\tconst style = options.isVertical\n\t\t? {\n\t\t\t\twidth: '100%'\n\t\t }\n\t\t: {\n\t\t\t\twidth: options.dimension\n\t\t };\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\tname: options.name,\n\t\t\t\t...options,\n\t\t\t\ttagName: options.isVertical ? 'tr' : 'td',\n\t\t\t\tattributes: {\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tstyle,\n\t\t\t\tcomponents: comp => comp.componentRender(comp)\n\t\t\t}),\n\n\t\t\ttoHTML(toHtmlOpts = {}) {\n\t\t\t\treturn toHtml(this, merge(options.toHtmlOptions, toHtmlOpts));\n\t\t\t},\n\n\t\t\tcomponentRender: render,\n\t\t\t...baseMethods(componentOptions, editor)\n\t\t}\n\t};\n};\n","import { merge, cssStyleObjectToString } from 'datatalks-utils';\nimport { validateStyleObj } from '../../../common/functions/_utilFunctions';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\thref: comp.get('href') || comp.get('attributes')?.href,\n\t\tparentWidth: null,\n\t\tstyle: {\n\t\t\twidth: options.parentWidth || null,\n\t\t\tdisplay: 'inline-block'\n\t\t}\n\t};\n\n\toptions = merge({}, defaults, options);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst innerComponents = comp.components().map(c => c);\n\n\tconst isImage =\n\t\tinnerComponents.length === 1 &&\n\t\tinnerComponents[0].get('type') === 'image-wrapper';\n\n\tlet html;\n\n\tif (isImage) {\n\t\thtml = innerComponents[0].toHTML({\n\t\t\tparentWidth: options.parentWidth,\n\t\t\thref: options.href,\n\t\t\thasLink: true\n\t\t});\n\t} else {\n\t\tconst inner =\n\t\t\tcomp.get('content') ||\n\t\t\tinnerComponents\n\t\t\t\t.map(child =>\n\t\t\t\t\tchild.toHTML({ parentWidth: options.parentWidth })\n\t\t\t\t)\n\t\t\t\t.join('\\n');\n\n\t\thtml = `\n\t\t\t\n\t\t\t\t${inner}\n\t\t\t\n\t\t`;\n\t}\n\n\tif (options.debug) console.log('Link HTML: ', html);\n\n\treturn html;\n};\n","import toHtml from './_toHtml';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\treturn {\n\t\textend: 'link',\n\t\tmodel: {\n\t\t\ttoHTML(toHtmlOpts = {}) {\n\t\t\t\treturn toHtml(this, toHtmlOpts);\n\t\t\t}\n\t\t}\n\t};\n};\n","import { validateStyleObj } from '../../common/functions/_utilFunctions';\nimport { noInteractionPreset } from '../_componentsUtils';\n\nexport default component => {\n\tconst margins = component.get('margins');\n\tconst hasMargins = component.get('hasMargins');\n\tconst marginsColor = component.get('marginsColor');\n\n\tconst row = [\n\t\t{\n\t\t\ttype: 'cell',\n\t\t\tstyle: validateStyleObj({\n\t\t\t\twidth: hasMargins ? margins.left : 0,\n\t\t\t\t['background-color']: marginsColor.left\n\t\t\t})\n\t\t},\n\t\t{\n\t\t\ttype: 'cell',\n\t\t\tstyle: {\n\t\t\t\twidth: hasMargins\n\t\t\t\t\t? `calc(100% - (${margins.left} + ${margins.right}))`\n\t\t\t\t\t: '100%'\n\t\t\t},\n\t\t\tcomponents: {\n\t\t\t\ttype: 'table',\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: '100%'\n\t\t\t\t},\n\t\t\t\tcomponents: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'row',\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\theight: hasMargins ? margins.top : 0\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcomponents: {\n\t\t\t\t\t\t\ttype: 'cell',\n\t\t\t\t\t\t\tstyle: validateStyleObj({\n\t\t\t\t\t\t\t\t['background-color']: marginsColor.top\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...component.get('innerComponents'),\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'row',\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\theight: hasMargins ? margins.bottom : 0\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcomponents: {\n\t\t\t\t\t\t\ttype: 'cell',\n\t\t\t\t\t\t\tstyle: validateStyleObj({\n\t\t\t\t\t\t\t\t['background-color']: marginsColor.bottom\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\ttype: 'cell',\n\t\t\tstyle: validateStyleObj({\n\t\t\t\twidth: hasMargins ? margins.right : 0,\n\t\t\t\t['background-color']: marginsColor.right\n\t\t\t})\n\t\t}\n\t];\n\n\tif (component.get('wrapInTable')) {\n\t\tcomponent.set('tagName', 'table');\n\t\tcomponent.setStyle(\n\t\t\tvalidateStyleObj({\n\t\t\t\t...component.getStyle(),\n\t\t\t\twidth: component.get('width')\n\t\t\t})\n\t\t);\n\t}\n\n\treturn component.get('wrapInTable')\n\t\t? {\n\t\t\t\ttype: 'row',\n\t\t\t\tcomponents: row,\n\t\t\t\t...noInteractionPreset\n\t\t }\n\t\t: row;\n};\n","import { validateStyleObj } from '../../common/functions/_utilFunctions';\n\nexport default comp => {\n\treturn validateStyleObj({\n\t\twidth: comp.get('width'),\n\t\t'padding-top': comp.get('hasMargins')\n\t\t\t? comp.get('margins')?.top || 0\n\t\t\t: 0,\n\t\t'padding-right': comp.get('hasMargins')\n\t\t\t? comp.get('margins')?.right || 0\n\t\t\t: 0,\n\t\t'padding-bottom': comp.get('hasMargins')\n\t\t\t? comp.get('margins')?.bottom || 0\n\t\t\t: 0,\n\t\t'padding-left': comp.get('hasMargins')\n\t\t\t? comp.get('margins')?.left || 0\n\t\t\t: 0\n\t});\n};\n","/**\n * Retrieves the inner HTML of a component.\n *\n * @param {Object} component - The component object.\n * @param {Object} opts - The options object.\n * @param {number} opts.width - The width of the component.\n * @return {string} - The inner HTML of the component.\n */\nexport default function getInner(component, opts) {\n\tconst defaults = {\n\t\talign: null,\n\t\twidth: component.get('width')\n\t};\n\n\topts = Object.assign({}, defaults, opts);\n\n\tconst children = component.components();\n\treturn children.length\n\t\t? children\n\t\t\t\t.map(c =>\n\t\t\t\t\tc.toHTML({ align: opts.align, parentWidth: opts.width })\n\t\t\t\t)\n\t\t\t\t.join('')\n\t\t: component.content;\n}\n","import { merge, cssStyleObjectToString, deleteProps } from 'datatalks-utils';\nimport getComputedStyle from './_getComputedStyle';\nimport { validateStyleObj } from '../../common/functions/_utilFunctions';\nimport getInnerHTML from '../common/methods/_getInnerHTML';\n\nexport default (comp, options) => {\n\tconst defaults = {\n\t\tdebug: false,\n\t\tstyle: getComputedStyle(comp),\n\t\talign: null,\n\t\tparentWidth: null\n\t};\n\n\toptions = merge(defaults, options);\n\n\tif (!options.parentWidth)\n\t\tthrow new Error(\n\t\t\t\"Can't export HTML as component parent's width is required\"\n\t\t);\n\n\tconst tableStyle = validateStyleObj({\n\t\twidth: options.style?.width\n\t});\n\n\tlet cellStyle = deleteProps(options.style, ['width'], false);\n\n\tif (comp.get('innerRenderType') === 'image-wrapper') {\n\t\tcellStyle = merge(cellStyle, { 'line-height': '0' });\n\t\t// TODO: this should be set for every component. For that we need to ensure every text has a line-height defined\n\t}\n\n\tconst parentWidth =\n\t\tparseFloat(options.parentWidth) -\n\t\tparseFloat(options.style['padding-left']) -\n\t\tparseFloat(options.style['padding-right']);\n\n\tconst innerHtml = comp.get('innerRenderType')\n\t\t? comp\n\t\t\t\t.findType(comp.get('innerRenderType'))[0]\n\t\t\t\t.toHTML({ parentWidth: `${parentWidth}px` })\n\t\t: getInnerHTML(comp, { width: `${parentWidth}px` });\n\n\tconst align = options.align ? `align=\"${options.align}\"` : '';\n\n\tconst html = `\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t
\n\t\t\t\t\t${innerHtml}\n\t\t\t\t
\n\t`;\n\n\tif (options.debug) console.log('Margins component HTML: ', html);\n\n\treturn html;\n};\n","import { COMPONENTS_DEFAULTS } from '../../../config/_config';\nimport render from './_render';\nimport { getComponentsDefaultsByType } from '../../componentsDefaults/_componentsDefaults';\nimport baseMethods from '../common/methods/_baseMethods';\nimport toHtml from './_toHtml';\nimport { merge } from 'datatalks-utils';\nimport { noInteractionPreset } from '../_componentsUtils';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\tconst defaults = getComponentsDefaultsByType('margins');\n\n\tconst options = {\n\t\t...COMPONENTS_DEFAULTS,\n\t\t...defaults,\n\t\t...componentOptions\n\t};\n\n\treturn {\n\t\tmodel: {\n\t\t\tdefaults: () => ({\n\t\t\t\t...options,\n\t\t\t\tname: options.name,\n\t\t\t\ttagName: options.tagName,\n\t\t\t\tattributes: {\n\t\t\t\t\t...options.attributes,\n\t\t\t\t\tclass: options.cssClass\n\t\t\t\t},\n\t\t\t\tcssClass: options.cssClass,\n\t\t\t\t...noInteractionPreset,\n\t\t\t\tcomponents: comp => comp.componentRender(comp)\n\t\t\t}),\n\n\t\t\ttoHTML(toHtmlOpts = {}) {\n\t\t\t\treturn toHtml(this, merge(options.toHtmlOptions, toHtmlOpts));\n\t\t\t},\n\n\t\t\tcomponentRender: render,\n\t\t\t...baseMethods(componentOptions, editor)\n\t\t}\n\t};\n};\n","import { merge } from 'datatalks-utils';\nimport { validateStyleObj } from '../../common/functions/_utilFunctions';\nimport { cssStyleObjectToString } from 'datatalks-utils';\n\nexport default (model, opts) => {\n\tconst defaults = {\n\t\tdebug: false,\n\n\t\ttag: null,\n\t\tattributes: null,\n\t\taltQuoteAttr: null,\n\t\twithProps: null,\n\t\treplaceWrapperByTable: false,\n\t\tcopyWrapperAttributes: true,\n\n\t\tpreHeader: '',\n\t\tignoreEmptyPreHeader: false,\n\n\t\twidth: null,\n\t\tbackgroundColor: null,\n\t\tuseOuterBackground: false,\n\t\touterBackground: null\n\t};\n\n\topts = merge(defaults, opts);\n\n\t/**\n\t * Returns the HTML representation of the inner components.\n\t * @return {string} The HTML representation of the inner components.\n\t */\n\tfunction getInner() {\n\t\tconst children = model.components();\n\t\treturn children.length\n\t\t\t? children.map(c => c.toHTML({ parentWidth: opts.width })).join('')\n\t\t\t: model.content;\n\t}\n\n\tconst preHeader =\n\t\topts.ignoreEmptyPreHeader && !opts.preHeader\n\t\t\t? ''\n\t\t\t: `\n\t\t\n\t\t\t${opts.preHeader || ''}\n\t\t\n\t`;\n\n\tconst debugStrStart = opts.debug ? 'data-eb-name=\"wrapper-first\"' : '';\n\tconst debugStrEnd = opts.debug ? 'data-eb-name=\"wrapper-last\"' : '';\n\n\tconst toStyleString = stylesObj =>\n\t\tcssStyleObjectToString(validateStyleObj(stylesObj));\n\n\tconst html = `\n\t\t\n\t\t\t${preHeader}\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t${getInner()}\n\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t
\n\t\t\n\t`;\n\n\treturn html;\n};\n","import toHtml from './_toHtml';\nimport { startCase } from 'lodash-es';\nimport { merge } from 'datatalks-utils';\n\nexport default (componentOptions = {}, emailBuilder) => {\n\tconst defaults = {\n\t\tname: 'Wrapper',\n\t\ttoHtml,\n\t\ttoHtmlOptions: {\n\t\t\treplaceWrapperByTable: false\n\t\t}\n\t};\n\n\tcomponentOptions = merge(defaults, componentOptions);\n\n\treturn {\n\t\textend: componentOptions.name,\n\t\tmodel: {\n\t\t\tdefaults: {\n\t\t\t\tname: startCase(componentOptions.name)\n\t\t\t},\n\t\t\ttoHTML(options) {\n\t\t\t\treturn toHtml(\n\t\t\t\t\tthis,\n\t\t\t\t\tmerge(componentOptions.toHtmlOptions, options, {\n\t\t\t\t\t\tuseOuterBackground:\n\t\t\t\t\t\t\temailBuilder.layout.useOuterBackground,\n\t\t\t\t\t\touterBackground: emailBuilder.styles.background.outer,\n\t\t\t\t\t\tbackgroundColor: emailBuilder.styles.background.email,\n\t\t\t\t\t\twidth: emailBuilder.editor.getStyleRules(\n\t\t\t\t\t\t\t'wrapper',\n\t\t\t\t\t\t\t'width'\n\t\t\t\t\t\t),\n\t\t\t\t\t\tpreHeader: emailBuilder.getOptions().html.usePreHeader\n\t\t\t\t\t\t\t? emailBuilder.getOptions().html.preHeaderText\n\t\t\t\t\t\t\t: '',\n\t\t\t\t\t\tignoreEmptyPreHeader:\n\t\t\t\t\t\t\t!emailBuilder.getOptions().html.usePreHeader\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t};\n};\n","import * as componentsBuild from './_exportComponentsBuild';\nimport { kebabCase } from 'lodash-es';\n\nexport default (componentName, emailBuilder) => {\n\tconst { editor } = emailBuilder;\n\n\teditor.DomComponents.addType(\n\t\tkebabCase(componentName),\n\t\tcomponentsBuild[componentName](\n\t\t\teditor.getComponentOptions(componentName),\n\t\t\temailBuilder\n\t\t)\n\t);\n};\n","import registerComponent from './_registerComponent';\n\nexport default emailBuilder => {\n\tconst { editor } = emailBuilder;\n\n\tconst defaults = {\n\t\tlinksList: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\theader: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\thero: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\tlist: {\n\t\t\tactive: true,\n\t\t\toptions: {\n\t\t\t\tdroppable: false\n\t\t\t}\n\t\t},\n\t\tlistItem: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\timagePlaceholder: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\tfooter: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\tcallToAction: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\tbutton: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\ttext: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\timageWrapper: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\tspace: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\tmargins: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\twrapper: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t},\n\t\tlink: {\n\t\t\tactive: true,\n\t\t\toptions: {}\n\t\t}\n\t};\n\n\tconst componentsOptions = editor.addComponentsOptions(defaults);\n\n\tfor (const comp in componentsOptions) {\n\t\tif (componentsOptions[comp].active) {\n\t\t\tregisterComponent(comp, emailBuilder);\n\t\t}\n\t}\n};\n","import callToAction from './call-to-action.svg';\nimport footer from './footer.svg';\nimport header from './header.svg';\nimport hero from './hero.svg';\nimport horizontalList from './horizontal-list.svg';\nimport imageHorizontalList from './image-horizontal-list.svg';\nimport imageVerticalList from './image-vertical-list.svg';\nimport verticalList from './vertical-list.svg';\nimport image from './image.svg';\nimport button from './button.svg';\nimport text from './text.svg';\nimport space from './space.svg';\nimport separator from './separator.svg';\nimport linksList from './links-list.svg';\nimport buttonHorizontalList from './button-horizontal-list.svg';\n\nexport default {\n\tcallToAction,\n\tfooter,\n\theader,\n\thero,\n\thorizontalList,\n\timageHorizontalList,\n\timageVerticalList,\n\tverticalList,\n\timage,\n\tbutton,\n\ttext,\n\tlinksList,\n\tspace,\n\tseparator,\n\tbuttonHorizontalList\n};\n","import icons from './icons/_icons';\nimport { translationFramework } from '../../_editor';\n\nexport default (editor, opts = {}) => {\n\tconst bm = editor.BlockManager;\n\tconst names = translationFramework.getTranslation('components.names');\n\tconst categories = translationFramework.getTranslation(\n\t\t'components.categories'\n\t);\n\t// Build custom components\n\teditor.componentBuilder({ name: 'custom-button', components: ['button'] });\n\n\teditor.componentBuilder({ name: 'custom-text', components: ['text'] });\n\n\teditor.componentBuilder({\n\t\tname: 'custom-space',\n\t\tcomponents: [\n\t\t\t{\n\t\t\t\ttype: 'space',\n\t\t\t\toptions: {\n\t\t\t\t\tspaceTagName: 'table',\n\t\t\t\t\tleftMargin: '0px',\n\t\t\t\t\trightMargin: '0px',\n\t\t\t\t\ttopMargin: '0px',\n\t\t\t\t\tbottomMargin: '0px'\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\tbaseTraits: {\n\t\t\tbackground: true,\n\t\t\tmargins: false,\n\t\t\tspacing: false\n\t\t}\n\t});\n\n\teditor.componentBuilder({\n\t\tname: 'separator',\n\t\tcomponents: [\n\t\t\t{\n\t\t\t\ttype: 'space',\n\t\t\t\toptions: {\n\t\t\t\t\tspaceTagName: 'table',\n\t\t\t\t\tspaceDimension: '1px',\n\t\t\t\t\tspaceColor: '#909090'\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\tbaseTraits: {\n\t\t\tbackground: true,\n\t\t\tmargins: true,\n\t\t\tspacing: false\n\t\t}\n\t});\n\n\teditor.componentBuilder({\n\t\tname: 'custom-image',\n\t\tcomponents: ['image-wrapper']\n\t});\n\n\t// Categories\n\tbm.categories.add({\n\t\tid: 'navigation',\n\t\tlabel: categories.navigation || 'Navigation',\n\t\topen: true\n\t});\n\tbm.categories.add({\n\t\tid: 'content',\n\t\tlabel: categories.content || 'Content',\n\t\topen: true\n\t});\n\tbm.categories.add({\n\t\tid: 'base',\n\t\tlabel: categories.base || 'Base',\n\t\topen: true\n\t});\n\n\t// Base components\n\tbm.add('image', {\n\t\tlabel: names.image || 'Image',\n\t\tcontent: {\n\t\t\ttype: 'custom-image',\n\t\t\thasMargins: false\n\t\t},\n\t\tcategory: 'base',\n\t\tmedia: icons.image\n\t});\n\n\tbm.add('text', {\n\t\tlabel: names.text || 'Text',\n\t\tcontent: {\n\t\t\ttype: 'custom-text',\n\t\t\ttraitOptions: {\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\ttextAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tcolor: false,\n\t\t\t\t\t\t\talign: false,\n\t\t\t\t\t\t\tweight: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcategory: 'base',\n\t\tmedia: icons.text\n\t});\n\n\tbm.add('button', {\n\t\tlabel: names.button || 'Button',\n\t\tcontent: {\n\t\t\ttype: 'custom-button',\n\t\t\ttraitOptions: {\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\tbuttonAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tcolor: false,\n\t\t\t\t\t\t\tweight: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcategory: 'base',\n\t\tmedia: icons.button\n\t});\n\n\tbm.add('spaces', {\n\t\tlabel: names.space || 'Space',\n\t\tcontent: {\n\t\t\ttype: 'custom-space'\n\t\t},\n\t\tcategory: 'base',\n\t\tmedia: icons.space\n\t});\n\n\tbm.add('separator', {\n\t\tlabel: names.separator || 'Separator',\n\t\tcontent: {\n\t\t\ttype: 'separator',\n\t\t\ttraitOptions: {\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\tcolorAccordionOptions: {\n\t\t\t\t\t\tbackgroundColor: {\n\t\t\t\t\t\t\tlabel: 'Separator Color'\n\t\t\t\t\t\t},\n\t\t\t\t\t\taccordion: {\n\t\t\t\t\t\t\ttitle: 'Color'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tspaceAccordionOptions: {\n\t\t\t\t\t\tspace: {\n\t\t\t\t\t\t\tlabel: 'Separator Thickness'\n\t\t\t\t\t\t},\n\t\t\t\t\t\taccordion: {\n\t\t\t\t\t\t\ttitle: 'Size'\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcategory: 'base',\n\t\tmedia: icons.separator\n\t});\n\n\t// Navigation components\n\tbm.add('header', {\n\t\tlabel: names.header || 'Header',\n\t\tcontent: {\n\t\t\ttype: 'header',\n\t\t\tisTextList: true,\n\t\t\ttraitOptions: {\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\tlinksAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tcolor: false,\n\t\t\t\t\t\t\tweight: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\taccordionContentOptions: {\n\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\turl: false,\n\t\t\t\t\t\ttarget: false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcategory: 'navigation',\n\t\tmedia: icons.header\n\t});\n\n\tbm.add('footer', {\n\t\tlabel: names.footer || 'Footer',\n\t\tcontent: {\n\t\t\ttype: 'footer',\n\t\t\ttraitOptions: {\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\taccordionsVisibility: {\n\t\t\t\t\t\ttitle: false,\n\t\t\t\t\t\tdescription: false\n\t\t\t\t\t},\n\t\t\t\t\tlistAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\thorizontal: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcategory: 'navigation',\n\t\tmedia: icons.footer\n\t});\n\n\t// Content components\n\tbm.add('hero', {\n\t\tlabel: names.hero || 'Hero',\n\t\tcontent: {\n\t\t\ttype: 'hero',\n\t\t\ttraitOptions: {\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\taccordionsVisibility: {\n\t\t\t\t\t\ttext: false\n\t\t\t\t\t},\n\t\t\t\t\tbuttonAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tcolor: false,\n\t\t\t\t\t\t\tweight: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcategory: 'content',\n\t\tmedia: icons.hero\n\t});\n\n\tbm.add('horizontal-list', {\n\t\tlabel: names.horizontalList || 'Horizontal List',\n\t\tcontent: {\n\t\t\ttype: 'list',\n\t\t\tisVertical: false,\n\t\t\titemOptions: {\n\t\t\t\timagePlacement: 'top'\n\t\t\t},\n\t\t\thasMargins: false,\n\t\t\ttraitOptions: {\n\t\t\t\titemsListMutationOptions: {\n\t\t\t\t\tlistItemElementTemplateOptions: {\n\t\t\t\t\t\thasImageUploader: true,\n\t\t\t\t\t\thasTitleEditor: true,\n\t\t\t\t\t\thasDescriptionEditor: true,\n\t\t\t\t\t\thasButtonEditor: true,\n\t\t\t\t\t\tonImageChange: null,\n\t\t\t\t\t\tbuttonProp: 'buttonText',\n\t\t\t\t\t\timageHasLinkProp: 'imageHasLink',\n\t\t\t\t\t\timageHrefProp: 'imageHref',\n\t\t\t\t\t\ttitleProp: 'title'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\tbuttonAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tweight: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcategory: 'content',\n\t\tmedia: icons.horizontalList\n\t});\n\n\tbm.add('vertical-list', {\n\t\tlabel: names.verticalList || 'Vertical List',\n\t\tcontent: {\n\t\t\ttype: 'list',\n\t\t\tisVertical: true,\n\t\t\titemOptions: {\n\t\t\t\timagePlacement: 'left'\n\t\t\t},\n\t\t\ttraitOptions: {\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\talignmentAccordionOptions: {\n\t\t\t\t\t\tvAlignment: {\n\t\t\t\t\t\t\tactive: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tbuttonAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tweight: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\titemsListMutationOptions: {\n\t\t\t\t\tlistItemElementTemplateOptions: {\n\t\t\t\t\t\thasImageUploader: true,\n\t\t\t\t\t\thasTitleEditor: true,\n\t\t\t\t\t\thasDescriptionEditor: true,\n\t\t\t\t\t\thasButtonEditor: true,\n\t\t\t\t\t\tonImageChange: null,\n\t\t\t\t\t\tbuttonProp: 'buttonText',\n\t\t\t\t\t\timageHasLinkProp: 'imageHasLink',\n\t\t\t\t\t\timageHrefProp: 'imageHref',\n\t\t\t\t\t\ttitleProp: 'title'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcategory: 'content',\n\t\tmedia: icons.verticalList\n\t});\n\n\tbm.add('call-to-action', {\n\t\tlabel: names.callToAction || 'Call to Action',\n\t\tcontent: {\n\t\t\ttype: 'call-to-action',\n\t\t\ttraitOptions: {\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\taccordionsVisibility: {\n\t\t\t\t\t\ttext: false\n\t\t\t\t\t},\n\t\t\t\t\tbuttonAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tcolor: false,\n\t\t\t\t\t\t\tweight: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tspacingAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tratio: true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcategory: 'content',\n\t\tmedia: icons.callToAction\n\t});\n\n\tconst imagePropsMap = {\n\t\timageBorderRadius: 'borderRadius',\n\t\timageUseBorderRadius: 'useBorderRadius'\n\t};\n\n\tbm.add('image-horizontal-list', {\n\t\tlabel: names.imagesHorizontal || 'Images Horizontal',\n\t\tcontent: {\n\t\t\ttype: 'list',\n\t\t\tisVertical: false,\n\t\t\thasMargins: false,\n\t\t\ttraitOptions: {\n\t\t\t\titemsListMutationOptions: {\n\t\t\t\t\tlistItemElementTemplateOptions: {\n\t\t\t\t\t\thasImageUploader: true,\n\t\t\t\t\t\thasTitleEditor: false,\n\t\t\t\t\t\thasDescriptionEditor: false,\n\t\t\t\t\t\thasButtonEditor: false,\n\t\t\t\t\t\timageHasLinkProp: 'hasLink',\n\t\t\t\t\t\timageHrefProp: 'href',\n\t\t\t\t\t\tonImageChange: (comp, item, fileInput) => {\n\t\t\t\t\t\t\tcomp.changeItemProp(\n\t\t\t\t\t\t\t\titem,\n\t\t\t\t\t\t\t\t'imgName',\n\t\t\t\t\t\t\t\tfileInput?.getName()\n\t\t\t\t\t\t\t\t\t? fileInput?.getName()\n\t\t\t\t\t\t\t\t\t: 'Untitled image'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonImageDelete: (comp, item) => {\n\t\t\t\t\t\t\tcomp.changeItemProp(\n\t\t\t\t\t\t\t\titem,\n\t\t\t\t\t\t\t\t'imgName',\n\t\t\t\t\t\t\t\t'Image placeholder'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttitleProp: 'imgName'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\taccordionsVisibility: {\n\t\t\t\t\t\tbutton: false\n\t\t\t\t\t},\n\t\t\t\t\tspacingAccordionOptions: {\n\t\t\t\t\t\thorizontal: {\n\t\t\t\t\t\t\tvisible: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvertical: {\n\t\t\t\t\t\t\tvisible: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsize: {\n\t\t\t\t\t\t\tvisible: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\timageAccordionOptions: {\n\t\t\t\t\t\tinnerTraitsVisibility: {\n\t\t\t\t\t\t\talignment: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tmarginsAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tlist: true,\n\t\t\t\t\t\t\tinnerElements: {\n\t\t\t\t\t\t\t\ttitle: false,\n\t\t\t\t\t\t\t\tdescription: false,\n\t\t\t\t\t\t\t\tbutton: false,\n\t\t\t\t\t\t\t\timage: false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\talignmentAccordionOptions: {\n\t\t\t\t\t\tinnerContentVAlignment: {\n\t\t\t\t\t\t\tactive: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinnerImageVAlignment: {\n\t\t\t\t\t\t\tactive: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\titemType: 'image-wrapper',\n\t\t\titemOptions: {\n\t\t\t\timgWidth: '150px',\n\t\t\t\timgName: 'Image placeholder'\n\t\t\t},\n\t\t\titemPropsMap: imagePropsMap\n\t\t},\n\t\tcategory: 'content',\n\t\tmedia: icons.imageHorizontalList\n\t});\n\n\tbm.add('image-vertical-list', {\n\t\tlabel: names.imagesVertical || 'Images Vertical',\n\t\tcontent: {\n\t\t\ttype: 'list',\n\t\t\tisVertical: true,\n\t\t\thasMargins: true,\n\t\t\ttraitOptions: {\n\t\t\t\titemsListMutationOptions: {\n\t\t\t\t\tlistItemElementTemplateOptions: {\n\t\t\t\t\t\thasImageUploader: true,\n\t\t\t\t\t\thasTitleEditor: false,\n\t\t\t\t\t\thasDescriptionEditor: false,\n\t\t\t\t\t\thasButtonEditor: false,\n\t\t\t\t\t\timageHasLinkProp: 'hasLink',\n\t\t\t\t\t\timageHrefProp: 'href',\n\t\t\t\t\t\tonImageChange: (comp, item, fileInput) => {\n\t\t\t\t\t\t\tcomp.changeItemProp(\n\t\t\t\t\t\t\t\titem,\n\t\t\t\t\t\t\t\t'imgName',\n\t\t\t\t\t\t\t\tfileInput?.getName()\n\t\t\t\t\t\t\t\t\t? fileInput?.getName()\n\t\t\t\t\t\t\t\t\t: 'Untitled image'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonImageDelete: (comp, item) => {\n\t\t\t\t\t\t\tcomp.changeItemProp(\n\t\t\t\t\t\t\t\titem,\n\t\t\t\t\t\t\t\t'imgName',\n\t\t\t\t\t\t\t\t'Image placeholder'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttitleProp: 'imgName'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\taccordionsVisibility: {\n\t\t\t\t\t\tbutton: false\n\t\t\t\t\t},\n\t\t\t\t\talignmentAccordionOptions: {\n\t\t\t\t\t\tvAlignment: {\n\t\t\t\t\t\t\tactive: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinnerContentVAlignment: {\n\t\t\t\t\t\t\tactive: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinnerImageVAlignment: {\n\t\t\t\t\t\t\tactive: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tspacingAccordionOptions: {\n\t\t\t\t\t\thorizontal: {\n\t\t\t\t\t\t\tvisible: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvertical: {\n\t\t\t\t\t\t\tvisible: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsize: {\n\t\t\t\t\t\t\tvisible: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\timageAccordionOptions: {\n\t\t\t\t\t\tinnerTraitsVisibility: {\n\t\t\t\t\t\t\talignment: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tmarginsAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tlist: true,\n\t\t\t\t\t\t\tinnerElements: {\n\t\t\t\t\t\t\t\ttitle: false,\n\t\t\t\t\t\t\t\tdescription: false,\n\t\t\t\t\t\t\t\tbutton: false,\n\t\t\t\t\t\t\t\timage: false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\titemType: 'image-wrapper',\n\t\t\titemOptions: {\n\t\t\t\timgWidth: '300px',\n\t\t\t\timgName: 'Image placeholder'\n\t\t\t},\n\t\t\titemPropsMap: imagePropsMap\n\t\t},\n\t\tcategory: 'content',\n\t\tmedia: icons.imageVerticalList\n\t});\n\n\tconst buttonPropsMap = {\n\t\tbuttonWidth: 'width',\n\t\tbuttonHeight: 'height',\n\t\tbuttonFontFamily: 'fontFamily',\n\t\tbuttonFontSize: 'fontSize',\n\t\tbuttonFontStyle: 'fontStyle',\n\t\tbuttonColor: 'color',\n\t\tbuttonBackgroundColor: 'backgroundColor',\n\t\tbuttonFontWeight: 'fontWeight',\n\t\tbuttonBorderWidth: 'borderWidth',\n\t\tbuttonBorderStyle: 'borderStyle',\n\t\tbuttonBorderColor: 'borderColor',\n\t\tbuttonTextAlignment: 'textAlignment',\n\t\tbuttonBorderRadius: 'borderRadius',\n\t\tbuttonUseBorderRadius: 'useBorderRadius',\n\t\tbuttonTextDecorationLine: 'textDecorationLine'\n\t};\n\n\tbm.add('button-horizontal-list', {\n\t\tlabel: names.buttonsHorizontal || 'Buttons Horizontal',\n\t\tcontent: {\n\t\t\ttype: 'list',\n\t\t\tisVertical: false,\n\t\t\thasMargins: false,\n\t\t\tnumberOfStartingItems: 3,\n\t\t\tmaxItems: 4,\n\t\t\ttraitOptions: {\n\t\t\t\titemsListMutationOptions: {\n\t\t\t\t\tlistItemElementTemplateOptions: {\n\t\t\t\t\t\thasImageUploader: false,\n\t\t\t\t\t\thasTitleEditor: false,\n\t\t\t\t\t\thasDescriptionEditor: false,\n\t\t\t\t\t\thasButtonEditor: true,\n\t\t\t\t\t\tbuttonProp: 'text',\n\t\t\t\t\t\tbuttonHrefProp: 'href',\n\t\t\t\t\t\tbuttonHrefStateProp: 'hrefState',\n\t\t\t\t\t\ttitleProp: 'text'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tstyleTabOptions: {\n\t\t\t\t\taccordionsVisibility: {\n\t\t\t\t\t\timage: false\n\t\t\t\t\t},\n\t\t\t\t\tspacingAccordionOptions: {\n\t\t\t\t\t\thorizontal: {\n\t\t\t\t\t\t\tvisible: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvertical: {\n\t\t\t\t\t\t\tvisible: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tmarginsAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\tlist: true,\n\t\t\t\t\t\t\tinnerElements: {\n\t\t\t\t\t\t\t\ttitle: false,\n\t\t\t\t\t\t\t\tdescription: false,\n\t\t\t\t\t\t\t\tbutton: false,\n\t\t\t\t\t\t\t\timage: false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tbuttonAccordionOptions: {\n\t\t\t\t\t\ttraitsVisibility: {\n\t\t\t\t\t\t\talign: false,\n\t\t\t\t\t\t\tweight: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\talignmentAccordionOptions: {\n\t\t\t\t\t\tinnerContentVAlignment: {\n\t\t\t\t\t\t\tactive: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinnerImageVAlignment: {\n\t\t\t\t\t\t\tactive: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\titemType: 'button',\n\t\t\titemOptions: {\n\t\t\t\ttext: 'Button'\n\t\t\t},\n\t\t\titemPropsMap: buttonPropsMap\n\t\t},\n\t\tcategory: 'content',\n\t\tmedia: icons.buttonHorizontalList\n\t});\n};\n","import { addClassesString, setContent } from 'datatalks-utils';\n\n/**\n * The options to configure the Dropdown Item for the Rich Text Editor's Dropdown\n * @typedef { Object } DropdownItemOptions\n * @property { boolean= } active - Whether or not the item should start active. @default false\n * @property { DropdownItemCallback= } onSelect - A callback function to call when the item is selected. @default null\n * @property { DropdownItemCallback= } onDeselect - A callback function to call when the item is deselected. @default null\n * @property { DropdownItemCallback= } onClick - A callback function to call when the item is clicked. @default null\n * @property { HTMLString | string= } content - The HTML content to render on the item. @default ''\n * @property { string= } classPrefix - A prefix to add to all the class names. @default ''\n * @property { string= } cssClass - The base CSS class to add to the item. @default 'dropdown-item'\n * @property { string= } extendedClasses - The CSS classes to extend the item's style. @default ''\n */\n\n/**\n * The callbacks functions called on the onSelect, onDeselect and OnClick events of the Dropdown Item.\n * @callback DropdownItemCallback\n * @param {DropdownItem} item - The Item itself\n * @param {any} value - The value stored by the Item\n */\n\n/**\n * Class representing a Dropdown Item to be used as an option inside the Dropdown.\n * @class\n * @property { DropdownItemOptions } options - The passed options merged with the default\n * values to configure the Dropdown Item.\n * @property { HTMLElement } el - The element that wraps the Dropdown Item.\n * @property { boolean } isActive - Whether or not the item is in the active state.\n * @property { any } value - A value stored by the dropdown item.\n */\nexport default class DropdownItem {\n\t/**\n\t * Creates the needed properties to build the Dropdown Item and calls init method.\n\t * @constructor\n\t * @param { DropdownItemOptions } options - The options to configure the Dropdown Item.\n\t */\n\tconstructor(options = {}) {\n\t\tconst defaults = {\n\t\t\tactive: false,\n\t\t\tclassPrefix: 'eb-',\n\t\t\tcssClass: 'dropdown-item',\n\t\t\textendedClasses: '',\n\t\t\tcontent: '',\n\t\t\tonSelect: null,\n\t\t\tonDeselect: null,\n\t\t\tonClick: null,\n\t\t\tvalue: null,\n\t\t\tisDefault: false\n\t\t};\n\n\t\tthis.options = {\n\t\t\t...defaults,\n\t\t\t...options\n\t\t};\n\n\t\tthis.className = `${this.options.classPrefix}${this.options.cssClass}`;\n\n\t\tthis.el = null;\n\t\tthis.isActive = this.options.active;\n\t\tthis.value = this.options.value;\n\t\tthis.content = this.options.content || this.options.value;\n\t\tthis.isDefault = this.options.isDefault;\n\t\tthis.init();\n\t}\n\n\t/**\n\t * Creates the wrapper element, assigns it to the 'el' property and adds the attributes.\n\t * Adds a click event listener to call onItemClick method. Sets the inner HTML of the element\n\t * provided through the content option\n\t * @method\n\t */\n\tinit() {\n\t\tconst item = this;\n\t\titem.el = document.createElement('div');\n\t\titem.el.classList.add(item.className);\n\t\tthis.setContent(this.options.content);\n\t\tif (item.options.extendedClasses)\n\t\t\taddClassesString(item.el, item.options.extendedClasses);\n\t\titem.el.addEventListener('click', e => {\n\t\t\titem.onItemClick.call(item);\n\t\t});\n\t}\n\n\t/**\n\t * Sets the content of the Item by replacing it's inner HTML with the given content\n\t * @param { (HTMLString | string) } content - The new HTML content of the item\n\t * @method\n\t */\n\tsetContent(content) {\n\t\tsetContent(this.el, content);\n\t}\n\n\t/**\n\t * Sets the default value for the dropdown item.\n\t * @param {boolean} isDefault - The value indicating whether the item is default or not.\n\t */\n\tsetDefault(isDefault = true) {\n\t\tthis.isDefault = isDefault;\n\t}\n\n\t/**\n\t * Checks if the dropdown item is the default item.\n\t * @return {boolean} True if the dropdown item is the default item, false otherwise.\n\t */\n\tisDefaultItem() {\n\t\treturn this.isDefault;\n\t}\n\n\t/**\n\t * Calls onClick function passed through options and calls the select method\n\t * @method\n\t */\n\tonItemClick() {\n\t\tconst item = this;\n\t\tif (typeof this.options.onClick === 'function')\n\t\t\tthis.options.onClick.call(null, this, this.value);\n\t\titem.select.call(item);\n\t}\n\n\t/**\n\t * Selects the item by setting 'isActive' property to 'true'.\n\t * Calls options.onSelect if it's valid function\n\t * @method\n\t */\n\tselect() {\n\t\tthis.isActive = true;\n\t\tthis.el.classList.add(`${this.className}--active`);\n\t\tif (typeof this.options.onSelect === 'function')\n\t\t\tthis.options.onSelect.call(null, this, this.value);\n\t}\n\n\t/**\n\t * Deselects the item by setting 'isActive' property to 'false'.\n\t * Calls options.onDeselect if it's valid function\n\t * @method\n\t */\n\tdeselect() {\n\t\tthis.isActive = false;\n\t\tthis.el.classList.remove(`${this.className}--active`);\n\t\tif (typeof this.options.onDeselect === 'function')\n\t\t\tthis.options.onDeselect.call(null, this, this.value);\n\t}\n\n\t/**\n\t * Gets the wrapper element (Item.el)\n\t * @method\n\t * @return {HTMLElement} The wrapper element\n\t */\n\tgetEl() {\n\t\treturn this.el;\n\t}\n\n\t/**\n\t * Returns whether or not the item is active;\n\t * @method\n\t * @return {boolean} whether or not the item is active\n\t */\n\tgetIsActive() {\n\t\treturn this.isActive;\n\t}\n\n\t/**\n\t * Returns the value stored by the Item;\n\t * @method\n\t * @return {any} the value stored by the Item\n\t */\n\tgetValue() {\n\t\treturn this.value;\n\t}\n}\n","import { addClassesString } from 'datatalks-utils';\n\n/* eslint-disable require-jsdoc */\nexport default class Icon {\n\tconstructor(options = {}) {\n\t\tconst defaults = {\n\t\t\ticonName: '',\n\t\t\tcssClass: 'eb-i',\n\t\t\ttagName: 'i',\n\t\t\textendedClasses: '',\n\t\t\tsize: '',\n\t\t\tavailableSizes: [\n\t\t\t\t'xs',\n\t\t\t\t'sm',\n\t\t\t\t'default',\n\t\t\t\t'md',\n\t\t\t\t'ml',\n\t\t\t\t'lg',\n\t\t\t\t'xl',\n\t\t\t\t'xxl'\n\t\t\t]\n\t\t};\n\n\t\tthis.options = {\n\t\t\t...defaults,\n\t\t\t...options\n\t\t};\n\n\t\tthis.element = null;\n\t\tthis.init();\n\t}\n\n\tinit() {\n\t\tthis.element = document.createElement('i');\n\t\tthis.element.className = `${this.options.cssClass} ${this.options.cssClass}-${this.options.iconName}`;\n\t\tif (this.options.extendedClasses)\n\t\t\taddClassesString(this.element, this.options.extendedClasses);\n\t\tif (this.options.size && this.validateSize())\n\t\t\tthis.element.classList.add(\n\t\t\t\t`${this.options.cssClass}--${this.options.size.trim()}`\n\t\t\t);\n\t}\n\n\tvalidateSize() {\n\t\treturn this.options.availableSizes.includes(this.options.size.trim());\n\t}\n\n\tgetEl() {\n\t\treturn this.element;\n\t}\n}\n","// import { camelCase } from 'lodash-es';\nimport Icon from './_component';\n// import icons from './_iconsList';\n\n// const obj = {};\n\n// icons.forEach(iconName => {\n// \tobj[camelCase(iconName)] = getIcon.bind(null, iconName);\n// });\n\n/**\n * Creates an icon with the icon class and returns the icon element.\n * @param { string } iconName - The name of the icon to get.\n * @param { object } iconOptions - The options to configure the icon.\n * @return { HTMLElement } The icon element created with the Icon class\n * @function\n */\nexport function getIcon(iconName, iconOptions = {}) {\n\treturn new Icon({ iconName, ...iconOptions }).getEl();\n}\n\n// export default obj;\n","/**\n * Custom positioning reference element.\n * @see https://floating-ui.com/docs/virtual-elements\n */\n\nconst sides = ['top', 'right', 'bottom', 'left'];\nconst alignments = ['start', 'end'];\nconst placements = /*#__PURE__*/sides.reduce((acc, side) => acc.concat(side, side + \"-\" + alignments[0], side + \"-\" + alignments[1]), []);\nconst min = Math.min;\nconst max = Math.max;\nconst round = Math.round;\nconst floor = Math.floor;\nconst createCoords = v => ({\n x: v,\n y: v\n});\nconst oppositeSideMap = {\n left: 'right',\n right: 'left',\n bottom: 'top',\n top: 'bottom'\n};\nconst oppositeAlignmentMap = {\n start: 'end',\n end: 'start'\n};\nfunction clamp(start, value, end) {\n return max(start, min(value, end));\n}\nfunction evaluate(value, param) {\n return typeof value === 'function' ? value(param) : value;\n}\nfunction getSide(placement) {\n return placement.split('-')[0];\n}\nfunction getAlignment(placement) {\n return placement.split('-')[1];\n}\nfunction getOppositeAxis(axis) {\n return axis === 'x' ? 'y' : 'x';\n}\nfunction getAxisLength(axis) {\n return axis === 'y' ? 'height' : 'width';\n}\nfunction getSideAxis(placement) {\n return ['top', 'bottom'].includes(getSide(placement)) ? 'y' : 'x';\n}\nfunction getAlignmentAxis(placement) {\n return getOppositeAxis(getSideAxis(placement));\n}\nfunction getAlignmentSides(placement, rects, rtl) {\n if (rtl === void 0) {\n rtl = false;\n }\n const alignment = getAlignment(placement);\n const alignmentAxis = getAlignmentAxis(placement);\n const length = getAxisLength(alignmentAxis);\n let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';\n if (rects.reference[length] > rects.floating[length]) {\n mainAlignmentSide = getOppositePlacement(mainAlignmentSide);\n }\n return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];\n}\nfunction getExpandedPlacements(placement) {\n const oppositePlacement = getOppositePlacement(placement);\n return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];\n}\nfunction getOppositeAlignmentPlacement(placement) {\n return placement.replace(/start|end/g, alignment => oppositeAlignmentMap[alignment]);\n}\nfunction getSideList(side, isStart, rtl) {\n const lr = ['left', 'right'];\n const rl = ['right', 'left'];\n const tb = ['top', 'bottom'];\n const bt = ['bottom', 'top'];\n switch (side) {\n case 'top':\n case 'bottom':\n if (rtl) return isStart ? rl : lr;\n return isStart ? lr : rl;\n case 'left':\n case 'right':\n return isStart ? tb : bt;\n default:\n return [];\n }\n}\nfunction getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {\n const alignment = getAlignment(placement);\n let list = getSideList(getSide(placement), direction === 'start', rtl);\n if (alignment) {\n list = list.map(side => side + \"-\" + alignment);\n if (flipAlignment) {\n list = list.concat(list.map(getOppositeAlignmentPlacement));\n }\n }\n return list;\n}\nfunction getOppositePlacement(placement) {\n return placement.replace(/left|right|bottom|top/g, side => oppositeSideMap[side]);\n}\nfunction expandPaddingObject(padding) {\n return {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n ...padding\n };\n}\nfunction getPaddingObject(padding) {\n return typeof padding !== 'number' ? expandPaddingObject(padding) : {\n top: padding,\n right: padding,\n bottom: padding,\n left: padding\n };\n}\nfunction rectToClientRect(rect) {\n const {\n x,\n y,\n width,\n height\n } = rect;\n return {\n width,\n height,\n top: y,\n left: x,\n right: x + width,\n bottom: y + height,\n x,\n y\n };\n}\n\nexport { alignments, clamp, createCoords, evaluate, expandPaddingObject, floor, getAlignment, getAlignmentAxis, getAlignmentSides, getAxisLength, getExpandedPlacements, getOppositeAlignmentPlacement, getOppositeAxis, getOppositeAxisPlacements, getOppositePlacement, getPaddingObject, getSide, getSideAxis, max, min, placements, rectToClientRect, round, sides };\n","import { getSideAxis, getAlignmentAxis, getAxisLength, getSide, getAlignment, evaluate, getPaddingObject, rectToClientRect, min, clamp, placements, getAlignmentSides, getOppositeAlignmentPlacement, getOppositePlacement, getExpandedPlacements, getOppositeAxisPlacements, sides, max, getOppositeAxis } from '@floating-ui/utils';\nexport { rectToClientRect } from '@floating-ui/utils';\n\nfunction computeCoordsFromPlacement(_ref, placement, rtl) {\n let {\n reference,\n floating\n } = _ref;\n const sideAxis = getSideAxis(placement);\n const alignmentAxis = getAlignmentAxis(placement);\n const alignLength = getAxisLength(alignmentAxis);\n const side = getSide(placement);\n const isVertical = sideAxis === 'y';\n const commonX = reference.x + reference.width / 2 - floating.width / 2;\n const commonY = reference.y + reference.height / 2 - floating.height / 2;\n const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;\n let coords;\n switch (side) {\n case 'top':\n coords = {\n x: commonX,\n y: reference.y - floating.height\n };\n break;\n case 'bottom':\n coords = {\n x: commonX,\n y: reference.y + reference.height\n };\n break;\n case 'right':\n coords = {\n x: reference.x + reference.width,\n y: commonY\n };\n break;\n case 'left':\n coords = {\n x: reference.x - floating.width,\n y: commonY\n };\n break;\n default:\n coords = {\n x: reference.x,\n y: reference.y\n };\n }\n switch (getAlignment(placement)) {\n case 'start':\n coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);\n break;\n case 'end':\n coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);\n break;\n }\n return coords;\n}\n\n/**\n * Computes the `x` and `y` coordinates that will place the floating element\n * next to a given reference element.\n *\n * This export does not have any `platform` interface logic. You will need to\n * write one for the platform you are using Floating UI with.\n */\nconst computePosition = async (reference, floating, config) => {\n const {\n placement = 'bottom',\n strategy = 'absolute',\n middleware = [],\n platform\n } = config;\n const validMiddleware = middleware.filter(Boolean);\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));\n let rects = await platform.getElementRects({\n reference,\n floating,\n strategy\n });\n let {\n x,\n y\n } = computeCoordsFromPlacement(rects, placement, rtl);\n let statefulPlacement = placement;\n let middlewareData = {};\n let resetCount = 0;\n for (let i = 0; i < validMiddleware.length; i++) {\n const {\n name,\n fn\n } = validMiddleware[i];\n const {\n x: nextX,\n y: nextY,\n data,\n reset\n } = await fn({\n x,\n y,\n initialPlacement: placement,\n placement: statefulPlacement,\n strategy,\n middlewareData,\n rects,\n platform,\n elements: {\n reference,\n floating\n }\n });\n x = nextX != null ? nextX : x;\n y = nextY != null ? nextY : y;\n middlewareData = {\n ...middlewareData,\n [name]: {\n ...middlewareData[name],\n ...data\n }\n };\n if (reset && resetCount <= 50) {\n resetCount++;\n if (typeof reset === 'object') {\n if (reset.placement) {\n statefulPlacement = reset.placement;\n }\n if (reset.rects) {\n rects = reset.rects === true ? await platform.getElementRects({\n reference,\n floating,\n strategy\n }) : reset.rects;\n }\n ({\n x,\n y\n } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));\n }\n i = -1;\n }\n }\n return {\n x,\n y,\n placement: statefulPlacement,\n strategy,\n middlewareData\n };\n};\n\n/**\n * Resolves with an object of overflow side offsets that determine how much the\n * element is overflowing a given clipping boundary on each side.\n * - positive = overflowing the boundary by that number of pixels\n * - negative = how many pixels left before it will overflow\n * - 0 = lies flush with the boundary\n * @see https://floating-ui.com/docs/detectOverflow\n */\nasync function detectOverflow(state, options) {\n var _await$platform$isEle;\n if (options === void 0) {\n options = {};\n }\n const {\n x,\n y,\n platform,\n rects,\n elements,\n strategy\n } = state;\n const {\n boundary = 'clippingAncestors',\n rootBoundary = 'viewport',\n elementContext = 'floating',\n altBoundary = false,\n padding = 0\n } = evaluate(options, state);\n const paddingObject = getPaddingObject(padding);\n const altContext = elementContext === 'floating' ? 'reference' : 'floating';\n const element = elements[altBoundary ? altContext : elementContext];\n const clippingClientRect = rectToClientRect(await platform.getClippingRect({\n element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),\n boundary,\n rootBoundary,\n strategy\n }));\n const rect = elementContext === 'floating' ? {\n x,\n y,\n width: rects.floating.width,\n height: rects.floating.height\n } : rects.reference;\n const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));\n const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {\n x: 1,\n y: 1\n } : {\n x: 1,\n y: 1\n };\n const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({\n elements,\n rect,\n offsetParent,\n strategy\n }) : rect);\n return {\n top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,\n bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,\n left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,\n right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x\n };\n}\n\n/**\n * Provides data to position an inner element of the floating element so that it\n * appears centered to the reference element.\n * @see https://floating-ui.com/docs/arrow\n */\nconst arrow = options => ({\n name: 'arrow',\n options,\n async fn(state) {\n const {\n x,\n y,\n placement,\n rects,\n platform,\n elements,\n middlewareData\n } = state;\n // Since `element` is required, we don't Partial<> the type.\n const {\n element,\n padding = 0\n } = evaluate(options, state) || {};\n if (element == null) {\n return {};\n }\n const paddingObject = getPaddingObject(padding);\n const coords = {\n x,\n y\n };\n const axis = getAlignmentAxis(placement);\n const length = getAxisLength(axis);\n const arrowDimensions = await platform.getDimensions(element);\n const isYAxis = axis === 'y';\n const minProp = isYAxis ? 'top' : 'left';\n const maxProp = isYAxis ? 'bottom' : 'right';\n const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';\n const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];\n const startDiff = coords[axis] - rects.reference[axis];\n const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element));\n let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;\n\n // DOM platform can return `window` as the `offsetParent`.\n if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) {\n clientSize = elements.floating[clientProp] || rects.floating[length];\n }\n const centerToReference = endDiff / 2 - startDiff / 2;\n\n // If the padding is large enough that it causes the arrow to no longer be\n // centered, modify the padding so that it is centered.\n const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;\n const minPadding = min(paddingObject[minProp], largestPossiblePadding);\n const maxPadding = min(paddingObject[maxProp], largestPossiblePadding);\n\n // Make sure the arrow doesn't overflow the floating element if the center\n // point is outside the floating element's bounds.\n const min$1 = minPadding;\n const max = clientSize - arrowDimensions[length] - maxPadding;\n const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;\n const offset = clamp(min$1, center, max);\n\n // If the reference is small enough that the arrow's padding causes it to\n // to point to nothing for an aligned placement, adjust the offset of the\n // floating element itself. To ensure `shift()` continues to take action,\n // a single reset is performed when this is true.\n const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;\n const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0;\n return {\n [axis]: coords[axis] + alignmentOffset,\n data: {\n [axis]: offset,\n centerOffset: center - offset - alignmentOffset,\n ...(shouldAddOffset && {\n alignmentOffset\n })\n },\n reset: shouldAddOffset\n };\n }\n});\n\nfunction getPlacementList(alignment, autoAlignment, allowedPlacements) {\n const allowedPlacementsSortedByAlignment = alignment ? [...allowedPlacements.filter(placement => getAlignment(placement) === alignment), ...allowedPlacements.filter(placement => getAlignment(placement) !== alignment)] : allowedPlacements.filter(placement => getSide(placement) === placement);\n return allowedPlacementsSortedByAlignment.filter(placement => {\n if (alignment) {\n return getAlignment(placement) === alignment || (autoAlignment ? getOppositeAlignmentPlacement(placement) !== placement : false);\n }\n return true;\n });\n}\n/**\n * Optimizes the visibility of the floating element by choosing the placement\n * that has the most space available automatically, without needing to specify a\n * preferred placement. Alternative to `flip`.\n * @see https://floating-ui.com/docs/autoPlacement\n */\nconst autoPlacement = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'autoPlacement',\n options,\n async fn(state) {\n var _middlewareData$autoP, _middlewareData$autoP2, _placementsThatFitOnE;\n const {\n rects,\n middlewareData,\n placement,\n platform,\n elements\n } = state;\n const {\n crossAxis = false,\n alignment,\n allowedPlacements = placements,\n autoAlignment = true,\n ...detectOverflowOptions\n } = evaluate(options, state);\n const placements$1 = alignment !== undefined || allowedPlacements === placements ? getPlacementList(alignment || null, autoAlignment, allowedPlacements) : allowedPlacements;\n const overflow = await detectOverflow(state, detectOverflowOptions);\n const currentIndex = ((_middlewareData$autoP = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP.index) || 0;\n const currentPlacement = placements$1[currentIndex];\n if (currentPlacement == null) {\n return {};\n }\n const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));\n\n // Make `computeCoords` start from the right place.\n if (placement !== currentPlacement) {\n return {\n reset: {\n placement: placements$1[0]\n }\n };\n }\n const currentOverflows = [overflow[getSide(currentPlacement)], overflow[alignmentSides[0]], overflow[alignmentSides[1]]];\n const allOverflows = [...(((_middlewareData$autoP2 = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP2.overflows) || []), {\n placement: currentPlacement,\n overflows: currentOverflows\n }];\n const nextPlacement = placements$1[currentIndex + 1];\n\n // There are more placements to check.\n if (nextPlacement) {\n return {\n data: {\n index: currentIndex + 1,\n overflows: allOverflows\n },\n reset: {\n placement: nextPlacement\n }\n };\n }\n const placementsSortedByMostSpace = allOverflows.map(d => {\n const alignment = getAlignment(d.placement);\n return [d.placement, alignment && crossAxis ?\n // Check along the mainAxis and main crossAxis side.\n d.overflows.slice(0, 2).reduce((acc, v) => acc + v, 0) :\n // Check only the mainAxis.\n d.overflows[0], d.overflows];\n }).sort((a, b) => a[1] - b[1]);\n const placementsThatFitOnEachSide = placementsSortedByMostSpace.filter(d => d[2].slice(0,\n // Aligned placements should not check their opposite crossAxis\n // side.\n getAlignment(d[0]) ? 2 : 3).every(v => v <= 0));\n const resetPlacement = ((_placementsThatFitOnE = placementsThatFitOnEachSide[0]) == null ? void 0 : _placementsThatFitOnE[0]) || placementsSortedByMostSpace[0][0];\n if (resetPlacement !== placement) {\n return {\n data: {\n index: currentIndex + 1,\n overflows: allOverflows\n },\n reset: {\n placement: resetPlacement\n }\n };\n }\n return {};\n }\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by flipping the `placement`\n * in order to keep it in view when the preferred placement(s) will overflow the\n * clipping boundary. Alternative to `autoPlacement`.\n * @see https://floating-ui.com/docs/flip\n */\nconst flip = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'flip',\n options,\n async fn(state) {\n var _middlewareData$arrow, _middlewareData$flip;\n const {\n placement,\n middlewareData,\n rects,\n initialPlacement,\n platform,\n elements\n } = state;\n const {\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = true,\n fallbackPlacements: specifiedFallbackPlacements,\n fallbackStrategy = 'bestFit',\n fallbackAxisSideDirection = 'none',\n flipAlignment = true,\n ...detectOverflowOptions\n } = evaluate(options, state);\n\n // If a reset by the arrow was caused due to an alignment offset being\n // added, we should skip any logic now since `flip()` has already done its\n // work.\n // https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643\n if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {\n return {};\n }\n const side = getSide(placement);\n const initialSideAxis = getSideAxis(initialPlacement);\n const isBasePlacement = getSide(initialPlacement) === initialPlacement;\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));\n const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));\n const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== 'none';\n if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) {\n fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));\n }\n const placements = [initialPlacement, ...fallbackPlacements];\n const overflow = await detectOverflow(state, detectOverflowOptions);\n const overflows = [];\n let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];\n if (checkMainAxis) {\n overflows.push(overflow[side]);\n }\n if (checkCrossAxis) {\n const sides = getAlignmentSides(placement, rects, rtl);\n overflows.push(overflow[sides[0]], overflow[sides[1]]);\n }\n overflowsData = [...overflowsData, {\n placement,\n overflows\n }];\n\n // One or more sides is overflowing.\n if (!overflows.every(side => side <= 0)) {\n var _middlewareData$flip2, _overflowsData$filter;\n const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;\n const nextPlacement = placements[nextIndex];\n if (nextPlacement) {\n // Try next placement and re-run the lifecycle.\n return {\n data: {\n index: nextIndex,\n overflows: overflowsData\n },\n reset: {\n placement: nextPlacement\n }\n };\n }\n\n // First, find the candidates that fit on the mainAxis side of overflow,\n // then find the placement that fits the best on the main crossAxis side.\n let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;\n\n // Otherwise fallback.\n if (!resetPlacement) {\n switch (fallbackStrategy) {\n case 'bestFit':\n {\n var _overflowsData$filter2;\n const placement = (_overflowsData$filter2 = overflowsData.filter(d => {\n if (hasFallbackAxisSideDirection) {\n const currentSideAxis = getSideAxis(d.placement);\n return currentSideAxis === initialSideAxis ||\n // Create a bias to the `y` side axis due to horizontal\n // reading directions favoring greater width.\n currentSideAxis === 'y';\n }\n return true;\n }).map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0];\n if (placement) {\n resetPlacement = placement;\n }\n break;\n }\n case 'initialPlacement':\n resetPlacement = initialPlacement;\n break;\n }\n }\n if (placement !== resetPlacement) {\n return {\n reset: {\n placement: resetPlacement\n }\n };\n }\n }\n return {};\n }\n };\n};\n\nfunction getSideOffsets(overflow, rect) {\n return {\n top: overflow.top - rect.height,\n right: overflow.right - rect.width,\n bottom: overflow.bottom - rect.height,\n left: overflow.left - rect.width\n };\n}\nfunction isAnySideFullyClipped(overflow) {\n return sides.some(side => overflow[side] >= 0);\n}\n/**\n * Provides data to hide the floating element in applicable situations, such as\n * when it is not in the same clipping context as the reference element.\n * @see https://floating-ui.com/docs/hide\n */\nconst hide = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'hide',\n options,\n async fn(state) {\n const {\n rects\n } = state;\n const {\n strategy = 'referenceHidden',\n ...detectOverflowOptions\n } = evaluate(options, state);\n switch (strategy) {\n case 'referenceHidden':\n {\n const overflow = await detectOverflow(state, {\n ...detectOverflowOptions,\n elementContext: 'reference'\n });\n const offsets = getSideOffsets(overflow, rects.reference);\n return {\n data: {\n referenceHiddenOffsets: offsets,\n referenceHidden: isAnySideFullyClipped(offsets)\n }\n };\n }\n case 'escaped':\n {\n const overflow = await detectOverflow(state, {\n ...detectOverflowOptions,\n altBoundary: true\n });\n const offsets = getSideOffsets(overflow, rects.floating);\n return {\n data: {\n escapedOffsets: offsets,\n escaped: isAnySideFullyClipped(offsets)\n }\n };\n }\n default:\n {\n return {};\n }\n }\n }\n };\n};\n\nfunction getBoundingRect(rects) {\n const minX = min(...rects.map(rect => rect.left));\n const minY = min(...rects.map(rect => rect.top));\n const maxX = max(...rects.map(rect => rect.right));\n const maxY = max(...rects.map(rect => rect.bottom));\n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY\n };\n}\nfunction getRectsByLine(rects) {\n const sortedRects = rects.slice().sort((a, b) => a.y - b.y);\n const groups = [];\n let prevRect = null;\n for (let i = 0; i < sortedRects.length; i++) {\n const rect = sortedRects[i];\n if (!prevRect || rect.y - prevRect.y > prevRect.height / 2) {\n groups.push([rect]);\n } else {\n groups[groups.length - 1].push(rect);\n }\n prevRect = rect;\n }\n return groups.map(rect => rectToClientRect(getBoundingRect(rect)));\n}\n/**\n * Provides improved positioning for inline reference elements that can span\n * over multiple lines, such as hyperlinks or range selections.\n * @see https://floating-ui.com/docs/inline\n */\nconst inline = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'inline',\n options,\n async fn(state) {\n const {\n placement,\n elements,\n rects,\n platform,\n strategy\n } = state;\n // A MouseEvent's client{X,Y} coords can be up to 2 pixels off a\n // ClientRect's bounds, despite the event listener being triggered. A\n // padding of 2 seems to handle this issue.\n const {\n padding = 2,\n x,\n y\n } = evaluate(options, state);\n const nativeClientRects = Array.from((await (platform.getClientRects == null ? void 0 : platform.getClientRects(elements.reference))) || []);\n const clientRects = getRectsByLine(nativeClientRects);\n const fallback = rectToClientRect(getBoundingRect(nativeClientRects));\n const paddingObject = getPaddingObject(padding);\n function getBoundingClientRect() {\n // There are two rects and they are disjoined.\n if (clientRects.length === 2 && clientRects[0].left > clientRects[1].right && x != null && y != null) {\n // Find the first rect in which the point is fully inside.\n return clientRects.find(rect => x > rect.left - paddingObject.left && x < rect.right + paddingObject.right && y > rect.top - paddingObject.top && y < rect.bottom + paddingObject.bottom) || fallback;\n }\n\n // There are 2 or more connected rects.\n if (clientRects.length >= 2) {\n if (getSideAxis(placement) === 'y') {\n const firstRect = clientRects[0];\n const lastRect = clientRects[clientRects.length - 1];\n const isTop = getSide(placement) === 'top';\n const top = firstRect.top;\n const bottom = lastRect.bottom;\n const left = isTop ? firstRect.left : lastRect.left;\n const right = isTop ? firstRect.right : lastRect.right;\n const width = right - left;\n const height = bottom - top;\n return {\n top,\n bottom,\n left,\n right,\n width,\n height,\n x: left,\n y: top\n };\n }\n const isLeftSide = getSide(placement) === 'left';\n const maxRight = max(...clientRects.map(rect => rect.right));\n const minLeft = min(...clientRects.map(rect => rect.left));\n const measureRects = clientRects.filter(rect => isLeftSide ? rect.left === minLeft : rect.right === maxRight);\n const top = measureRects[0].top;\n const bottom = measureRects[measureRects.length - 1].bottom;\n const left = minLeft;\n const right = maxRight;\n const width = right - left;\n const height = bottom - top;\n return {\n top,\n bottom,\n left,\n right,\n width,\n height,\n x: left,\n y: top\n };\n }\n return fallback;\n }\n const resetRects = await platform.getElementRects({\n reference: {\n getBoundingClientRect\n },\n floating: elements.floating,\n strategy\n });\n if (rects.reference.x !== resetRects.reference.x || rects.reference.y !== resetRects.reference.y || rects.reference.width !== resetRects.reference.width || rects.reference.height !== resetRects.reference.height) {\n return {\n reset: {\n rects: resetRects\n }\n };\n }\n return {};\n }\n };\n};\n\n// For type backwards-compatibility, the `OffsetOptions` type was also\n// Derivable.\n\nasync function convertValueToCoords(state, options) {\n const {\n placement,\n platform,\n elements\n } = state;\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));\n const side = getSide(placement);\n const alignment = getAlignment(placement);\n const isVertical = getSideAxis(placement) === 'y';\n const mainAxisMulti = ['left', 'top'].includes(side) ? -1 : 1;\n const crossAxisMulti = rtl && isVertical ? -1 : 1;\n const rawValue = evaluate(options, state);\n\n // eslint-disable-next-line prefer-const\n let {\n mainAxis,\n crossAxis,\n alignmentAxis\n } = typeof rawValue === 'number' ? {\n mainAxis: rawValue,\n crossAxis: 0,\n alignmentAxis: null\n } : {\n mainAxis: 0,\n crossAxis: 0,\n alignmentAxis: null,\n ...rawValue\n };\n if (alignment && typeof alignmentAxis === 'number') {\n crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;\n }\n return isVertical ? {\n x: crossAxis * crossAxisMulti,\n y: mainAxis * mainAxisMulti\n } : {\n x: mainAxis * mainAxisMulti,\n y: crossAxis * crossAxisMulti\n };\n}\n\n/**\n * Modifies the placement by translating the floating element along the\n * specified axes.\n * A number (shorthand for `mainAxis` or distance), or an axes configuration\n * object may be passed.\n * @see https://floating-ui.com/docs/offset\n */\nconst offset = function (options) {\n if (options === void 0) {\n options = 0;\n }\n return {\n name: 'offset',\n options,\n async fn(state) {\n var _middlewareData$offse, _middlewareData$arrow;\n const {\n x,\n y,\n placement,\n middlewareData\n } = state;\n const diffCoords = await convertValueToCoords(state, options);\n\n // If the placement is the same and the arrow caused an alignment offset\n // then we don't need to change the positioning coordinates.\n if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {\n return {};\n }\n return {\n x: x + diffCoords.x,\n y: y + diffCoords.y,\n data: {\n ...diffCoords,\n placement\n }\n };\n }\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by shifting it in order to\n * keep it in view when it will overflow the clipping boundary.\n * @see https://floating-ui.com/docs/shift\n */\nconst shift = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'shift',\n options,\n async fn(state) {\n const {\n x,\n y,\n placement\n } = state;\n const {\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = false,\n limiter = {\n fn: _ref => {\n let {\n x,\n y\n } = _ref;\n return {\n x,\n y\n };\n }\n },\n ...detectOverflowOptions\n } = evaluate(options, state);\n const coords = {\n x,\n y\n };\n const overflow = await detectOverflow(state, detectOverflowOptions);\n const crossAxis = getSideAxis(getSide(placement));\n const mainAxis = getOppositeAxis(crossAxis);\n let mainAxisCoord = coords[mainAxis];\n let crossAxisCoord = coords[crossAxis];\n if (checkMainAxis) {\n const minSide = mainAxis === 'y' ? 'top' : 'left';\n const maxSide = mainAxis === 'y' ? 'bottom' : 'right';\n const min = mainAxisCoord + overflow[minSide];\n const max = mainAxisCoord - overflow[maxSide];\n mainAxisCoord = clamp(min, mainAxisCoord, max);\n }\n if (checkCrossAxis) {\n const minSide = crossAxis === 'y' ? 'top' : 'left';\n const maxSide = crossAxis === 'y' ? 'bottom' : 'right';\n const min = crossAxisCoord + overflow[minSide];\n const max = crossAxisCoord - overflow[maxSide];\n crossAxisCoord = clamp(min, crossAxisCoord, max);\n }\n const limitedCoords = limiter.fn({\n ...state,\n [mainAxis]: mainAxisCoord,\n [crossAxis]: crossAxisCoord\n });\n return {\n ...limitedCoords,\n data: {\n x: limitedCoords.x - x,\n y: limitedCoords.y - y\n }\n };\n }\n };\n};\n/**\n * Built-in `limiter` that will stop `shift()` at a certain point.\n */\nconst limitShift = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n options,\n fn(state) {\n const {\n x,\n y,\n placement,\n rects,\n middlewareData\n } = state;\n const {\n offset = 0,\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = true\n } = evaluate(options, state);\n const coords = {\n x,\n y\n };\n const crossAxis = getSideAxis(placement);\n const mainAxis = getOppositeAxis(crossAxis);\n let mainAxisCoord = coords[mainAxis];\n let crossAxisCoord = coords[crossAxis];\n const rawOffset = evaluate(offset, state);\n const computedOffset = typeof rawOffset === 'number' ? {\n mainAxis: rawOffset,\n crossAxis: 0\n } : {\n mainAxis: 0,\n crossAxis: 0,\n ...rawOffset\n };\n if (checkMainAxis) {\n const len = mainAxis === 'y' ? 'height' : 'width';\n const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis;\n const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis;\n if (mainAxisCoord < limitMin) {\n mainAxisCoord = limitMin;\n } else if (mainAxisCoord > limitMax) {\n mainAxisCoord = limitMax;\n }\n }\n if (checkCrossAxis) {\n var _middlewareData$offse, _middlewareData$offse2;\n const len = mainAxis === 'y' ? 'width' : 'height';\n const isOriginSide = ['top', 'left'].includes(getSide(placement));\n const limitMin = rects.reference[crossAxis] - rects.floating[len] + (isOriginSide ? ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse[crossAxis]) || 0 : 0) + (isOriginSide ? 0 : computedOffset.crossAxis);\n const limitMax = rects.reference[crossAxis] + rects.reference[len] + (isOriginSide ? 0 : ((_middlewareData$offse2 = middlewareData.offset) == null ? void 0 : _middlewareData$offse2[crossAxis]) || 0) - (isOriginSide ? computedOffset.crossAxis : 0);\n if (crossAxisCoord < limitMin) {\n crossAxisCoord = limitMin;\n } else if (crossAxisCoord > limitMax) {\n crossAxisCoord = limitMax;\n }\n }\n return {\n [mainAxis]: mainAxisCoord,\n [crossAxis]: crossAxisCoord\n };\n }\n };\n};\n\n/**\n * Provides data that allows you to change the size of the floating element —\n * for instance, prevent it from overflowing the clipping boundary or match the\n * width of the reference element.\n * @see https://floating-ui.com/docs/size\n */\nconst size = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'size',\n options,\n async fn(state) {\n const {\n placement,\n rects,\n platform,\n elements\n } = state;\n const {\n apply = () => {},\n ...detectOverflowOptions\n } = evaluate(options, state);\n const overflow = await detectOverflow(state, detectOverflowOptions);\n const side = getSide(placement);\n const alignment = getAlignment(placement);\n const isYAxis = getSideAxis(placement) === 'y';\n const {\n width,\n height\n } = rects.floating;\n let heightSide;\n let widthSide;\n if (side === 'top' || side === 'bottom') {\n heightSide = side;\n widthSide = alignment === ((await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))) ? 'start' : 'end') ? 'left' : 'right';\n } else {\n widthSide = side;\n heightSide = alignment === 'end' ? 'top' : 'bottom';\n }\n const maximumClippingHeight = height - overflow.top - overflow.bottom;\n const maximumClippingWidth = width - overflow.left - overflow.right;\n const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);\n const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);\n const noShift = !state.middlewareData.shift;\n let availableHeight = overflowAvailableHeight;\n let availableWidth = overflowAvailableWidth;\n if (isYAxis) {\n availableWidth = alignment || noShift ? min(overflowAvailableWidth, maximumClippingWidth) : maximumClippingWidth;\n } else {\n availableHeight = alignment || noShift ? min(overflowAvailableHeight, maximumClippingHeight) : maximumClippingHeight;\n }\n if (noShift && !alignment) {\n const xMin = max(overflow.left, 0);\n const xMax = max(overflow.right, 0);\n const yMin = max(overflow.top, 0);\n const yMax = max(overflow.bottom, 0);\n if (isYAxis) {\n availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right));\n } else {\n availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom));\n }\n }\n await apply({\n ...state,\n availableWidth,\n availableHeight\n });\n const nextDimensions = await platform.getDimensions(elements.floating);\n if (width !== nextDimensions.width || height !== nextDimensions.height) {\n return {\n reset: {\n rects: true\n }\n };\n }\n return {};\n }\n };\n};\n\nexport { arrow, autoPlacement, computePosition, detectOverflow, flip, hide, inline, limitShift, offset, shift, size };\n","function getNodeName(node) {\n if (isNode(node)) {\n return (node.nodeName || '').toLowerCase();\n }\n // Mocked nodes in testing environments may not be instances of Node. By\n // returning `#document` an infinite loop won't occur.\n // https://github.com/floating-ui/floating-ui/issues/2317\n return '#document';\n}\nfunction getWindow(node) {\n var _node$ownerDocument;\n return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;\n}\nfunction getDocumentElement(node) {\n var _ref;\n return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;\n}\nfunction isNode(value) {\n return value instanceof Node || value instanceof getWindow(value).Node;\n}\nfunction isElement(value) {\n return value instanceof Element || value instanceof getWindow(value).Element;\n}\nfunction isHTMLElement(value) {\n return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;\n}\nfunction isShadowRoot(value) {\n // Browsers without `ShadowRoot` support.\n if (typeof ShadowRoot === 'undefined') {\n return false;\n }\n return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;\n}\nfunction isOverflowElement(element) {\n const {\n overflow,\n overflowX,\n overflowY,\n display\n } = getComputedStyle(element);\n return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !['inline', 'contents'].includes(display);\n}\nfunction isTableElement(element) {\n return ['table', 'td', 'th'].includes(getNodeName(element));\n}\nfunction isTopLayer(element) {\n return [':popover-open', ':modal'].some(selector => {\n try {\n return element.matches(selector);\n } catch (e) {\n return false;\n }\n });\n}\nfunction isContainingBlock(element) {\n const webkit = isWebKit();\n const css = getComputedStyle(element);\n\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n return css.transform !== 'none' || css.perspective !== 'none' || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value));\n}\nfunction getContainingBlock(element) {\n let currentNode = getParentNode(element);\n while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {\n if (isTopLayer(currentNode)) {\n return null;\n }\n if (isContainingBlock(currentNode)) {\n return currentNode;\n }\n currentNode = getParentNode(currentNode);\n }\n return null;\n}\nfunction isWebKit() {\n if (typeof CSS === 'undefined' || !CSS.supports) return false;\n return CSS.supports('-webkit-backdrop-filter', 'none');\n}\nfunction isLastTraversableNode(node) {\n return ['html', 'body', '#document'].includes(getNodeName(node));\n}\nfunction getComputedStyle(element) {\n return getWindow(element).getComputedStyle(element);\n}\nfunction getNodeScroll(element) {\n if (isElement(element)) {\n return {\n scrollLeft: element.scrollLeft,\n scrollTop: element.scrollTop\n };\n }\n return {\n scrollLeft: element.scrollX,\n scrollTop: element.scrollY\n };\n}\nfunction getParentNode(node) {\n if (getNodeName(node) === 'html') {\n return node;\n }\n const result =\n // Step into the shadow DOM of the parent of a slotted node.\n node.assignedSlot ||\n // DOM Element detected.\n node.parentNode ||\n // ShadowRoot detected.\n isShadowRoot(node) && node.host ||\n // Fallback.\n getDocumentElement(node);\n return isShadowRoot(result) ? result.host : result;\n}\nfunction getNearestOverflowAncestor(node) {\n const parentNode = getParentNode(node);\n if (isLastTraversableNode(parentNode)) {\n return node.ownerDocument ? node.ownerDocument.body : node.body;\n }\n if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {\n return parentNode;\n }\n return getNearestOverflowAncestor(parentNode);\n}\nfunction getOverflowAncestors(node, list, traverseIframes) {\n var _node$ownerDocument2;\n if (list === void 0) {\n list = [];\n }\n if (traverseIframes === void 0) {\n traverseIframes = true;\n }\n const scrollableAncestor = getNearestOverflowAncestor(node);\n const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);\n const win = getWindow(scrollableAncestor);\n if (isBody) {\n return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], win.frameElement && traverseIframes ? getOverflowAncestors(win.frameElement) : []);\n }\n return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));\n}\n\nexport { getComputedStyle, getContainingBlock, getDocumentElement, getNearestOverflowAncestor, getNodeName, getNodeScroll, getOverflowAncestors, getParentNode, getWindow, isContainingBlock, isElement, isHTMLElement, isLastTraversableNode, isNode, isOverflowElement, isShadowRoot, isTableElement, isTopLayer, isWebKit };\n","import { rectToClientRect, detectOverflow as detectOverflow$1, offset as offset$1, autoPlacement as autoPlacement$1, shift as shift$1, flip as flip$1, size as size$1, hide as hide$1, arrow as arrow$1, inline as inline$1, limitShift as limitShift$1, computePosition as computePosition$1 } from '@floating-ui/core';\nimport { round, createCoords, max, min, floor } from '@floating-ui/utils';\nimport { getComputedStyle, isHTMLElement, isElement, getWindow, isWebKit, getDocumentElement, isTopLayer, getNodeName, isOverflowElement, getNodeScroll, getOverflowAncestors, getParentNode, isLastTraversableNode, isContainingBlock, isTableElement, getContainingBlock } from '@floating-ui/utils/dom';\nexport { getOverflowAncestors } from '@floating-ui/utils/dom';\n\nfunction getCssDimensions(element) {\n const css = getComputedStyle(element);\n // In testing environments, the `width` and `height` properties are empty\n // strings for SVG elements, returning NaN. Fallback to `0` in this case.\n let width = parseFloat(css.width) || 0;\n let height = parseFloat(css.height) || 0;\n const hasOffset = isHTMLElement(element);\n const offsetWidth = hasOffset ? element.offsetWidth : width;\n const offsetHeight = hasOffset ? element.offsetHeight : height;\n const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;\n if (shouldFallback) {\n width = offsetWidth;\n height = offsetHeight;\n }\n return {\n width,\n height,\n $: shouldFallback\n };\n}\n\nfunction unwrapElement(element) {\n return !isElement(element) ? element.contextElement : element;\n}\n\nfunction getScale(element) {\n const domElement = unwrapElement(element);\n if (!isHTMLElement(domElement)) {\n return createCoords(1);\n }\n const rect = domElement.getBoundingClientRect();\n const {\n width,\n height,\n $\n } = getCssDimensions(domElement);\n let x = ($ ? round(rect.width) : rect.width) / width;\n let y = ($ ? round(rect.height) : rect.height) / height;\n\n // 0, NaN, or Infinity should always fallback to 1.\n\n if (!x || !Number.isFinite(x)) {\n x = 1;\n }\n if (!y || !Number.isFinite(y)) {\n y = 1;\n }\n return {\n x,\n y\n };\n}\n\nconst noOffsets = /*#__PURE__*/createCoords(0);\nfunction getVisualOffsets(element) {\n const win = getWindow(element);\n if (!isWebKit() || !win.visualViewport) {\n return noOffsets;\n }\n return {\n x: win.visualViewport.offsetLeft,\n y: win.visualViewport.offsetTop\n };\n}\nfunction shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {\n if (isFixed === void 0) {\n isFixed = false;\n }\n if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {\n return false;\n }\n return isFixed;\n}\n\nfunction getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {\n if (includeScale === void 0) {\n includeScale = false;\n }\n if (isFixedStrategy === void 0) {\n isFixedStrategy = false;\n }\n const clientRect = element.getBoundingClientRect();\n const domElement = unwrapElement(element);\n let scale = createCoords(1);\n if (includeScale) {\n if (offsetParent) {\n if (isElement(offsetParent)) {\n scale = getScale(offsetParent);\n }\n } else {\n scale = getScale(element);\n }\n }\n const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);\n let x = (clientRect.left + visualOffsets.x) / scale.x;\n let y = (clientRect.top + visualOffsets.y) / scale.y;\n let width = clientRect.width / scale.x;\n let height = clientRect.height / scale.y;\n if (domElement) {\n const win = getWindow(domElement);\n const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;\n let currentWin = win;\n let currentIFrame = currentWin.frameElement;\n while (currentIFrame && offsetParent && offsetWin !== currentWin) {\n const iframeScale = getScale(currentIFrame);\n const iframeRect = currentIFrame.getBoundingClientRect();\n const css = getComputedStyle(currentIFrame);\n const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;\n const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;\n x *= iframeScale.x;\n y *= iframeScale.y;\n width *= iframeScale.x;\n height *= iframeScale.y;\n x += left;\n y += top;\n currentWin = getWindow(currentIFrame);\n currentIFrame = currentWin.frameElement;\n }\n }\n return rectToClientRect({\n width,\n height,\n x,\n y\n });\n}\n\nfunction convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {\n let {\n elements,\n rect,\n offsetParent,\n strategy\n } = _ref;\n const isFixed = strategy === 'fixed';\n const documentElement = getDocumentElement(offsetParent);\n const topLayer = elements ? isTopLayer(elements.floating) : false;\n if (offsetParent === documentElement || topLayer && isFixed) {\n return rect;\n }\n let scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n let scale = createCoords(1);\n const offsets = createCoords(0);\n const isOffsetParentAnElement = isHTMLElement(offsetParent);\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n if (isHTMLElement(offsetParent)) {\n const offsetRect = getBoundingClientRect(offsetParent);\n scale = getScale(offsetParent);\n offsets.x = offsetRect.x + offsetParent.clientLeft;\n offsets.y = offsetRect.y + offsetParent.clientTop;\n }\n }\n return {\n width: rect.width * scale.x,\n height: rect.height * scale.y,\n x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x,\n y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y\n };\n}\n\nfunction getClientRects(element) {\n return Array.from(element.getClientRects());\n}\n\nfunction getWindowScrollBarX(element) {\n // If has a CSS width greater than the viewport, then this will be\n // incorrect for RTL.\n return getBoundingClientRect(getDocumentElement(element)).left + getNodeScroll(element).scrollLeft;\n}\n\n// Gets the entire size of the scrollable document area, even extending outside\n// of the `` and `` rect bounds if horizontally scrollable.\nfunction getDocumentRect(element) {\n const html = getDocumentElement(element);\n const scroll = getNodeScroll(element);\n const body = element.ownerDocument.body;\n const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);\n const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);\n let x = -scroll.scrollLeft + getWindowScrollBarX(element);\n const y = -scroll.scrollTop;\n if (getComputedStyle(body).direction === 'rtl') {\n x += max(html.clientWidth, body.clientWidth) - width;\n }\n return {\n width,\n height,\n x,\n y\n };\n}\n\nfunction getViewportRect(element, strategy) {\n const win = getWindow(element);\n const html = getDocumentElement(element);\n const visualViewport = win.visualViewport;\n let width = html.clientWidth;\n let height = html.clientHeight;\n let x = 0;\n let y = 0;\n if (visualViewport) {\n width = visualViewport.width;\n height = visualViewport.height;\n const visualViewportBased = isWebKit();\n if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {\n x = visualViewport.offsetLeft;\n y = visualViewport.offsetTop;\n }\n }\n return {\n width,\n height,\n x,\n y\n };\n}\n\n// Returns the inner client rect, subtracting scrollbars if present.\nfunction getInnerBoundingClientRect(element, strategy) {\n const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');\n const top = clientRect.top + element.clientTop;\n const left = clientRect.left + element.clientLeft;\n const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);\n const width = element.clientWidth * scale.x;\n const height = element.clientHeight * scale.y;\n const x = left * scale.x;\n const y = top * scale.y;\n return {\n width,\n height,\n x,\n y\n };\n}\nfunction getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {\n let rect;\n if (clippingAncestor === 'viewport') {\n rect = getViewportRect(element, strategy);\n } else if (clippingAncestor === 'document') {\n rect = getDocumentRect(getDocumentElement(element));\n } else if (isElement(clippingAncestor)) {\n rect = getInnerBoundingClientRect(clippingAncestor, strategy);\n } else {\n const visualOffsets = getVisualOffsets(element);\n rect = {\n ...clippingAncestor,\n x: clippingAncestor.x - visualOffsets.x,\n y: clippingAncestor.y - visualOffsets.y\n };\n }\n return rectToClientRect(rect);\n}\nfunction hasFixedPositionAncestor(element, stopNode) {\n const parentNode = getParentNode(element);\n if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {\n return false;\n }\n return getComputedStyle(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);\n}\n\n// A \"clipping ancestor\" is an `overflow` element with the characteristic of\n// clipping (or hiding) child elements. This returns all clipping ancestors\n// of the given element up the tree.\nfunction getClippingElementAncestors(element, cache) {\n const cachedResult = cache.get(element);\n if (cachedResult) {\n return cachedResult;\n }\n let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');\n let currentContainingBlockComputedStyle = null;\n const elementIsFixed = getComputedStyle(element).position === 'fixed';\n let currentNode = elementIsFixed ? getParentNode(element) : element;\n\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {\n const computedStyle = getComputedStyle(currentNode);\n const currentNodeIsContaining = isContainingBlock(currentNode);\n if (!currentNodeIsContaining && computedStyle.position === 'fixed') {\n currentContainingBlockComputedStyle = null;\n }\n const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && ['absolute', 'fixed'].includes(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);\n if (shouldDropCurrentNode) {\n // Drop non-containing blocks.\n result = result.filter(ancestor => ancestor !== currentNode);\n } else {\n // Record last containing block for next iteration.\n currentContainingBlockComputedStyle = computedStyle;\n }\n currentNode = getParentNode(currentNode);\n }\n cache.set(element, result);\n return result;\n}\n\n// Gets the maximum area that the element is visible in due to any number of\n// clipping ancestors.\nfunction getClippingRect(_ref) {\n let {\n element,\n boundary,\n rootBoundary,\n strategy\n } = _ref;\n const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);\n const clippingAncestors = [...elementClippingAncestors, rootBoundary];\n const firstClippingAncestor = clippingAncestors[0];\n const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {\n const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy);\n accRect.top = max(rect.top, accRect.top);\n accRect.right = min(rect.right, accRect.right);\n accRect.bottom = min(rect.bottom, accRect.bottom);\n accRect.left = max(rect.left, accRect.left);\n return accRect;\n }, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy));\n return {\n width: clippingRect.right - clippingRect.left,\n height: clippingRect.bottom - clippingRect.top,\n x: clippingRect.left,\n y: clippingRect.top\n };\n}\n\nfunction getDimensions(element) {\n const {\n width,\n height\n } = getCssDimensions(element);\n return {\n width,\n height\n };\n}\n\nfunction getRectRelativeToOffsetParent(element, offsetParent, strategy) {\n const isOffsetParentAnElement = isHTMLElement(offsetParent);\n const documentElement = getDocumentElement(offsetParent);\n const isFixed = strategy === 'fixed';\n const rect = getBoundingClientRect(element, true, isFixed, offsetParent);\n let scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n const offsets = createCoords(0);\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n if (isOffsetParentAnElement) {\n const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);\n offsets.x = offsetRect.x + offsetParent.clientLeft;\n offsets.y = offsetRect.y + offsetParent.clientTop;\n } else if (documentElement) {\n offsets.x = getWindowScrollBarX(documentElement);\n }\n }\n const x = rect.left + scroll.scrollLeft - offsets.x;\n const y = rect.top + scroll.scrollTop - offsets.y;\n return {\n x,\n y,\n width: rect.width,\n height: rect.height\n };\n}\n\nfunction isStaticPositioned(element) {\n return getComputedStyle(element).position === 'static';\n}\n\nfunction getTrueOffsetParent(element, polyfill) {\n if (!isHTMLElement(element) || getComputedStyle(element).position === 'fixed') {\n return null;\n }\n if (polyfill) {\n return polyfill(element);\n }\n return element.offsetParent;\n}\n\n// Gets the closest ancestor positioned element. Handles some edge cases,\n// such as table ancestors and cross browser bugs.\nfunction getOffsetParent(element, polyfill) {\n const win = getWindow(element);\n if (isTopLayer(element)) {\n return win;\n }\n if (!isHTMLElement(element)) {\n let svgOffsetParent = getParentNode(element);\n while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {\n if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {\n return svgOffsetParent;\n }\n svgOffsetParent = getParentNode(svgOffsetParent);\n }\n return win;\n }\n let offsetParent = getTrueOffsetParent(element, polyfill);\n while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {\n offsetParent = getTrueOffsetParent(offsetParent, polyfill);\n }\n if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) {\n return win;\n }\n return offsetParent || getContainingBlock(element) || win;\n}\n\nconst getElementRects = async function (data) {\n const getOffsetParentFn = this.getOffsetParent || getOffsetParent;\n const getDimensionsFn = this.getDimensions;\n const floatingDimensions = await getDimensionsFn(data.floating);\n return {\n reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),\n floating: {\n x: 0,\n y: 0,\n width: floatingDimensions.width,\n height: floatingDimensions.height\n }\n };\n};\n\nfunction isRTL(element) {\n return getComputedStyle(element).direction === 'rtl';\n}\n\nconst platform = {\n convertOffsetParentRelativeRectToViewportRelativeRect,\n getDocumentElement,\n getClippingRect,\n getOffsetParent,\n getElementRects,\n getClientRects,\n getDimensions,\n getScale,\n isElement,\n isRTL\n};\n\n// https://samthor.au/2021/observing-dom/\nfunction observeMove(element, onMove) {\n let io = null;\n let timeoutId;\n const root = getDocumentElement(element);\n function cleanup() {\n var _io;\n clearTimeout(timeoutId);\n (_io = io) == null || _io.disconnect();\n io = null;\n }\n function refresh(skip, threshold) {\n if (skip === void 0) {\n skip = false;\n }\n if (threshold === void 0) {\n threshold = 1;\n }\n cleanup();\n const {\n left,\n top,\n width,\n height\n } = element.getBoundingClientRect();\n if (!skip) {\n onMove();\n }\n if (!width || !height) {\n return;\n }\n const insetTop = floor(top);\n const insetRight = floor(root.clientWidth - (left + width));\n const insetBottom = floor(root.clientHeight - (top + height));\n const insetLeft = floor(left);\n const rootMargin = -insetTop + \"px \" + -insetRight + \"px \" + -insetBottom + \"px \" + -insetLeft + \"px\";\n const options = {\n rootMargin,\n threshold: max(0, min(1, threshold)) || 1\n };\n let isFirstUpdate = true;\n function handleObserve(entries) {\n const ratio = entries[0].intersectionRatio;\n if (ratio !== threshold) {\n if (!isFirstUpdate) {\n return refresh();\n }\n if (!ratio) {\n // If the reference is clipped, the ratio is 0. Throttle the refresh\n // to prevent an infinite loop of updates.\n timeoutId = setTimeout(() => {\n refresh(false, 1e-7);\n }, 1000);\n } else {\n refresh(false, ratio);\n }\n }\n isFirstUpdate = false;\n }\n\n // Older browsers don't support a `document` as the root and will throw an\n // error.\n try {\n io = new IntersectionObserver(handleObserve, {\n ...options,\n // Handle