`).get(0);\n var marginEls = ppfx + marginName + '-el';\n var paddingEls = ppfx + paddingName + '-el';\n const fullMargName = `${marginEls} ${ppfx + marginName}`;\n const fullPadName = `${paddingEls} ${ppfx + paddingName}`;\n marginT = $(`
`).get(0);\n marginB = $(`
`).get(0);\n marginL = $(`
`).get(0);\n marginR = $(`
`).get(0);\n padT = $(`
`).get(0);\n padB = $(`
`).get(0);\n padL = $(`
`).get(0);\n padR = $(`
`).get(0);\n this['marginT' + state] = marginT;\n this['marginB' + state] = marginB;\n this['marginL' + state] = marginL;\n this['marginR' + state] = marginR;\n this['padT' + state] = padT;\n this['padB' + state] = padB;\n this['padL' + state] = padL;\n this['padR' + state] = padR;\n marginV.appendChild(marginT);\n marginV.appendChild(marginB);\n marginV.appendChild(marginL);\n marginV.appendChild(marginR);\n paddingV.appendChild(padT);\n paddingV.appendChild(padB);\n paddingV.appendChild(padL);\n paddingV.appendChild(padR);\n offsetViewer.appendChild(marginV);\n offsetViewer.appendChild(paddingV);\n this[stateVar] = '1';\n }\n\n var unit = 'px';\n var marginLeftSt = parseFloat(style.marginLeft.replace(unit, '')) * zoom;\n var marginRightSt = parseFloat(style.marginRight.replace(unit, '')) * zoom;\n var marginTopSt = parseFloat(style.marginTop.replace(unit, '')) * zoom;\n var marginBottomSt = parseFloat(style.marginBottom.replace(unit, '')) * zoom;\n var mtStyle = marginT.style;\n var mbStyle = marginB.style;\n var mlStyle = marginL.style;\n var mrStyle = marginR.style;\n var ptStyle = padT.style;\n var pbStyle = padB.style;\n var plStyle = padL.style;\n var prStyle = padR.style;\n var posLeft = parseFloat(pos.left);\n var widthEl = parseFloat(style.width) * zoom + unit;\n\n // Margin style\n mtStyle.height = marginTopSt + unit;\n mtStyle.width = widthEl;\n mtStyle.top = pos.top - marginTopSt + unit;\n mtStyle.left = posLeft + unit;\n\n mbStyle.height = marginBottomSt + unit;\n mbStyle.width = widthEl;\n mbStyle.top = pos.top + pos.height + unit;\n mbStyle.left = posLeft + unit;\n\n var marginSideH = pos.height + marginTopSt + marginBottomSt + unit;\n var marginSideT = pos.top - marginTopSt + unit;\n mlStyle.height = marginSideH;\n mlStyle.width = marginLeftSt + unit;\n mlStyle.top = marginSideT;\n mlStyle.left = posLeft - marginLeftSt + unit;\n\n mrStyle.height = marginSideH;\n mrStyle.width = marginRightSt + unit;\n mrStyle.top = marginSideT;\n mrStyle.left = posLeft + pos.width + unit;\n\n // Padding style\n var padTop = parseFloat(style.paddingTop) * zoom;\n ptStyle.height = padTop + unit;\n // ptStyle.width = widthEl;\n // ptStyle.top = pos.top + unit;\n // ptStyle.left = posLeft + unit;\n\n var padBot = parseFloat(style.paddingBottom) * zoom;\n pbStyle.height = padBot + unit;\n // pbStyle.width = widthEl;\n // pbStyle.top = pos.top + pos.height - padBot + unit;\n // pbStyle.left = posLeft + unit;\n\n var padSideH = pos.height - padBot - padTop + unit;\n var padSideT = pos.top + padTop + unit;\n plStyle.height = padSideH;\n plStyle.width = parseFloat(style.paddingLeft) * zoom + unit;\n plStyle.top = padSideT;\n // plStyle.left = pos.left + unit;\n // plStyle.right = 0;\n\n var padRight = parseFloat(style.paddingRight) * zoom;\n prStyle.height = padSideH;\n prStyle.width = padRight + unit;\n prStyle.top = padSideT;\n // prStyle.left = pos.left + pos.width - padRight + unit;\n // prStyle.left = 0;\n },\n\n stop(editor, sender, opts = {}) {\n var opt = opts || {};\n var state = opt.state || '';\n var method = this.getOffsetMethod(state);\n var canvas = editor.Canvas;\n var offsetViewer = canvas[method](opts.view);\n offsetViewer.style.opacity = 0;\n },\n};\n","import { bindAll } from 'underscore';\n\nexport default {\n init() {\n bindAll(this, '_onFramesChange');\n },\n\n run(ed) {\n this.toggleVis(ed);\n },\n\n stop(ed) {\n this.toggleVis(ed, 0);\n },\n\n toggleVis(ed, active = 1) {\n if (!ed.Commands.isActive('preview')) {\n const cv = ed.Canvas;\n const mth = active ? 'on' : 'off';\n cv.getFrames().forEach(frame => this._upFrame(frame, active));\n cv.getModel()[mth]('change:frames', this._onFramesChange);\n }\n },\n\n _onFramesChange(m, frames) {\n frames.forEach(frame => frame.once('loaded', () => this._upFrame(frame, true)));\n },\n\n _upFrame(frame, active) {\n const method = active ? 'add' : 'remove';\n frame.view.getBody().classList[method](`${this.ppfx}dashed`);\n },\n};\n","import { isString, isElement } from 'underscore';\nimport { createId, deepMerge, isDef } from 'utils/mixins';\n\nexport default {\n getConfig(name) {\n return this.__getConfig(name);\n },\n\n getProjectData(data) {\n const obj = {};\n const key = this.storageKey;\n if (key) {\n obj[key] = data || this.getAll();\n }\n return obj;\n },\n\n loadProjectData(data = {}, { all, onResult, reset } = {}) {\n const key = this.storageKey;\n const opts = { action: 'load' };\n const coll = all || this.getAll();\n let result = data[key];\n\n if (typeof result == 'string') {\n try {\n result = JSON.parse(result);\n } catch (err) {\n this.__logWarn('Data parsing failed', { input: result });\n }\n }\n\n reset && result && coll.reset(null, opts);\n\n if (onResult) {\n result && onResult(result, opts);\n } else if (result && isDef(result.length)) {\n coll.reset(result, opts);\n }\n\n return result;\n },\n\n clear(opts = {}) {\n const { all } = this;\n all && all.reset(null, opts);\n return this;\n },\n\n __getConfig(name) {\n const res = this.config || {};\n return name ? res[name] : res;\n },\n\n getAll(opts = {}) {\n return this.all ? (opts.array ? [...this.all.models] : this.all) : [];\n },\n\n getAllMap() {\n return this.getAll().reduce((acc, i) => {\n acc[i.get(i.idAttribute)] = i;\n return acc;\n }, {});\n },\n\n __initConfig(def = {}, conf = {}) {\n this.config = deepMerge(def, conf);\n this.em = this.config.em;\n this.cls = [];\n },\n\n __initListen(opts = {}) {\n const { all, em, events } = this;\n all &&\n em &&\n all\n .on('add', (m, c, o) => em.trigger(events.add, m, o))\n .on('remove', (m, c, o) => em.trigger(events.remove, m, o))\n .on('change', (p, c) => em.trigger(events.update, p, p.changedAttributes(), c))\n .on('all', this.__catchAllEvent, this);\n // Register collections\n this.cls = [all].concat(opts.collections || []);\n // Propagate events\n (opts.propagate || []).forEach(({ entity, event }) => {\n entity.on('all', (ev, model, coll, opts) => {\n const options = opts || coll;\n const opt = { event: ev, ...options };\n [em, all].map(md => md.trigger(event, model, opt));\n });\n });\n },\n\n __remove(model, opts = {}) {\n const { em } = this;\n const md = isString(model) ? this.get(model) : model;\n const rm = () => {\n md && this.all.remove(md, opts);\n return md;\n };\n !opts.silent && em && em.trigger(this.events.removeBefore, md, rm, opts);\n return !opts.abort && rm();\n },\n\n __catchAllEvent(event, model, coll, opts) {\n const { em, events } = this;\n const options = opts || coll;\n em && events.all && em.trigger(events.all, { event, model, options });\n this.__onAllEvent();\n },\n\n __appendTo() {\n const elTo = this.getConfig().appendTo;\n\n if (elTo) {\n const el = isElement(elTo) ? elTo : document.querySelector(elTo);\n if (!el) return this.__logWarn('\"appendTo\" element not found');\n el.appendChild(this.render());\n }\n },\n\n __onAllEvent() {},\n\n __logWarn(str, opts) {\n this.em.logWarning(`[${this.name}]: ${str}`, opts);\n },\n\n _createId(len = 16) {\n const all = this.getAll();\n const ln = all.length + len;\n const allMap = this.getAllMap();\n let id;\n\n do {\n id = createId(ln);\n } while (allMap[id]);\n\n return id;\n },\n\n __listenAdd(model, event) {\n model.on('add', (m, c, o) => this.em.trigger(event, m, o));\n },\n\n __listenRemove(model, event) {\n model.on('remove', (m, c, o) => this.em.trigger(event, m, o));\n },\n\n __listenUpdate(model, event) {\n model.on('change', (p, c) => this.em.trigger(event, p, p.changedAttributes(), c));\n },\n\n __destroy() {\n this.cls.forEach(coll => {\n coll.stopListening();\n coll.reset();\n });\n this.em = 0;\n this.config = 0;\n this.view?.remove();\n this.view = 0;\n },\n};\n","import { isUndefined } from 'underscore';\nimport { Model } from '../../common';\n\n/**\n * @typedef Trait\n * @property {String} id Trait id, eg. `my-trait-id`.\n * @property {String} type Trait type, defines how the trait should rendered. Possible values: `text` (default), `number`, `select`, `checkbox`, `color`, `button`\n * @property {String} label The trait label to show for the rendered trait.\n * @property {String} name The name of the trait used as a key for the attribute/property. By default, the name is used as attribute name or property in case `changeProp` in enabled.\n * @property {Boolean} changeProp If `true` the trait value is applied on component\n *\n */\nexport default class Trait extends Model {\n initialize() {\n const { target, name, changeProp } = this.attributes;\n !this.get('id') && this.set('id', name);\n\n if (target) {\n this.target = target;\n this.unset('target');\n const targetEvent = changeProp ? `change:${name}` : `change:attributes:${name}`;\n this.listenTo(target, targetEvent, this.targetUpdated);\n }\n }\n\n /**\n * Get the trait id.\n * @returns {String}\n */\n getId() {\n return this.get('id');\n }\n\n /**\n * Get the trait type.\n * @returns {String}\n */\n getType() {\n return this.get('type');\n }\n\n /**\n * Get the trait name.\n * @returns {String}\n */\n getName() {\n return this.get('name');\n }\n\n /**\n * Get the trait label.\n * @param {Object} [opts={}] Options.\n * @param {Boolean} [opts.locale=true] Use the locale string from i18n module.\n * @returns {String}\n */\n getLabel(opts = {}) {\n const { locale = true } = opts;\n const id = this.getId();\n const name = this.get('label') || this.getName();\n return (locale && this.em?.t(`traitManager.traits.labels.${id}`)) || name;\n }\n\n /**\n * Get the trait value.\n * The value is taken from component attributes by default or from properties if the trait has the `changeProp` enabled.\n * @returns {any}\n */\n getValue() {\n return this.getTargetValue();\n }\n\n /**\n * Update the trait value.\n * The value is applied on component attributes by default or on properties if the trait has the `changeProp` enabled.\n * @param {any} value Value of the trait.\n * @param {Object} [opts={}] Options.\n * @param {Boolean} [opts.partial] If `true` the update won't be considered complete (not stored in UndoManager).\n */\n setValue(value, opts = {}) {\n const valueOpts = {};\n\n if (opts.partial) {\n valueOpts.avoidStore = true;\n }\n\n this.setTargetValue(value, valueOpts);\n\n if (opts.partial === false) {\n this.setTargetValue('');\n this.setTargetValue(value);\n }\n }\n\n props() {\n return this.attributes;\n }\n\n targetUpdated() {\n const value = this.getTargetValue();\n this.set({ value }, { fromTarget: 1 });\n this.em?.trigger('trait:update', {\n trait: this,\n component: this.target,\n });\n }\n\n getTargetValue() {\n const name = this.get('name');\n const target = this.target;\n let value;\n\n if (this.get('changeProp')) {\n value = target.get(name);\n } else {\n value = target.getAttributes()[name];\n }\n\n return !isUndefined(value) ? value : '';\n }\n\n setTargetValue(value, opts = {}) {\n const target = this.target;\n const name = this.get('name');\n if (isUndefined(value)) return;\n let valueToSet = value;\n\n if (value === 'false') {\n valueToSet = false;\n } else if (value === 'true') {\n valueToSet = true;\n }\n\n if (this.get('changeProp')) {\n target.set(name, valueToSet, opts);\n } else {\n target.addAttributes({ [name]: valueToSet }, opts);\n }\n }\n\n setValueFromInput(value, final = 1, opts = {}) {\n const toSet = { value };\n this.set(toSet, { ...opts, avoidStore: 1 });\n\n // Have to trigger the change\n if (final) {\n this.set('value', '', opts);\n this.set(toSet, opts);\n }\n }\n\n getInitValue() {\n const target = this.target;\n const name = this.get('name');\n let value;\n\n if (target) {\n const attrs = target.get('attributes');\n value = this.get('changeProp') ? target.get(name) : attrs[name];\n }\n\n return value || this.get('value') || this.get('default');\n }\n}\n\nTrait.prototype.defaults = {\n type: 'text',\n label: '',\n name: '',\n min: '',\n max: '',\n unit: '',\n step: 1,\n value: '',\n target: '',\n default: '',\n placeholder: '',\n changeProp: 0,\n options: [],\n};\n","import { isString, isArray } from 'underscore';\nimport { Collection } from '../../common';\nimport Trait from './Trait';\nimport TraitFactory from './TraitFactory';\n\nexport default class Traits extends Collection {\n initialize(coll, options = {}) {\n this.em = options.em;\n this.listenTo(this, 'add', this.handleAdd);\n this.listenTo(this, 'reset', this.handleReset);\n }\n\n handleReset(coll, { previousModels = [] } = {}) {\n previousModels.forEach(model => model.trigger('remove'));\n }\n\n handleAdd(model) {\n model.em = this.em;\n const target = this.target;\n\n if (target) {\n model.target = target;\n }\n }\n\n setTarget(target) {\n this.target = target;\n }\n\n add(models, opt) {\n const em = this.em;\n\n // Use TraitFactory if necessary\n if (isString(models) || isArray(models)) {\n const tm = em && em.get && em.get('TraitManager');\n const tmOpts = tm && tm.getConfig();\n const tf = TraitFactory(tmOpts);\n\n if (isString(models)) {\n models = [models];\n }\n\n for (var i = 0, len = models.length; i < len; i++) {\n const str = models[i];\n const model = isString(str) ? tf.build(str)[0] : str;\n model.target = this.target;\n models[i] = model;\n }\n }\n\n return Collection.prototype.add.apply(this, [models, opt]);\n }\n}\n\nTraits.prototype.model = Trait;\n","export default (config = {}) => ({\n /**\n * Build props object by their name\n * @param {Array
|string} props Array of properties name\n * @return {Array