@themarioga/grid-editor 7.3.0 → 8.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +34 -30
  3. package/UPGRADING.md +55 -0
  4. package/dist/grideditor.bundle.min.js +3 -3
  5. package/dist/grideditor.css +72 -6
  6. package/dist/grideditor.d.ts +24 -3
  7. package/dist/grideditor.esm.js +7 -58
  8. package/dist/grideditor.jquery.js +0 -13
  9. package/dist/grideditor.jquery.min.js +1 -1
  10. package/dist/grideditor.jquery.min.js.map +3 -3
  11. package/dist/grideditor.js +7 -58
  12. package/dist/grideditor.min.css +1 -1
  13. package/dist/grideditor.min.css.map +1 -1
  14. package/dist/grideditor.min.js +2 -2
  15. package/dist/grideditor.min.js.map +3 -3
  16. package/dist/locales/grideditor.es.esm.js +30 -6
  17. package/dist/locales/grideditor.es.js +30 -6
  18. package/dist/locales/grideditor.es.min.js +1 -1
  19. package/dist/locales/grideditor.es.min.js.map +2 -2
  20. package/dist/plugins/grideditor.accordion.min.js.map +2 -2
  21. package/dist/plugins/grideditor.alignment.esm.js +11 -38
  22. package/dist/plugins/grideditor.alignment.js +11 -38
  23. package/dist/plugins/grideditor.alignment.min.js +1 -1
  24. package/dist/plugins/grideditor.alignment.min.js.map +3 -3
  25. package/dist/plugins/grideditor.card.min.js.map +1 -1
  26. package/dist/plugins/grideditor.ckeditor.esm.js +0 -5
  27. package/dist/plugins/grideditor.ckeditor.js +0 -5
  28. package/dist/plugins/grideditor.ckeditor.min.js +1 -1
  29. package/dist/plugins/grideditor.ckeditor.min.js.map +3 -3
  30. package/dist/plugins/grideditor.clipboard.min.js.map +1 -1
  31. package/dist/plugins/grideditor.codemirror-inline.min.js.map +1 -1
  32. package/dist/plugins/grideditor.codemirror.min.js.map +1 -1
  33. package/dist/plugins/grideditor.elements.min.js.map +2 -2
  34. package/dist/plugins/grideditor.gutters.min.js.map +1 -1
  35. package/dist/plugins/grideditor.order.min.js.map +1 -1
  36. package/dist/plugins/grideditor.popup.min.js.map +1 -1
  37. package/dist/plugins/grideditor.sections.min.js.map +2 -2
  38. package/dist/plugins/grideditor.style.esm.js +393 -60
  39. package/dist/plugins/grideditor.style.js +387 -56
  40. package/dist/plugins/grideditor.style.min.js +4 -2
  41. package/dist/plugins/grideditor.style.min.js.map +4 -4
  42. package/dist/plugins/grideditor.summernote.min.js.map +2 -2
  43. package/dist/plugins/grideditor.tabs.esm.js +274 -6
  44. package/dist/plugins/grideditor.tabs.js +274 -6
  45. package/dist/plugins/grideditor.tabs.min.js +1 -1
  46. package/dist/plugins/grideditor.tabs.min.js.map +3 -3
  47. package/dist/plugins/grideditor.tinymce.esm.js +1 -8
  48. package/dist/plugins/grideditor.tinymce.js +1 -8
  49. package/dist/plugins/grideditor.tinymce.min.js +1 -1
  50. package/dist/plugins/grideditor.tinymce.min.js.map +3 -3
  51. package/docs/events.md +4 -6
  52. package/docs/locale-keys.md +35 -13
  53. package/docs/plugins.md +15 -35
  54. package/example/ckeditor.html +0 -5
  55. package/example/containers.html +64 -2
  56. package/example/index.html +5 -4
  57. package/example/style.html +16 -4
  58. package/example/utilities.html +12 -11
  59. package/package.json +1 -1
  60. package/src/js/dom.js +1 -2
  61. package/src/js/grideditor.jquery.js +7 -28
  62. package/src/js/grideditor.js +12 -81
  63. package/src/js/locales/grideditor.es.js +30 -6
  64. package/src/js/plugins/grideditor.alignment.js +21 -50
  65. package/src/js/plugins/grideditor.ckeditor.js +10 -23
  66. package/src/js/plugins/grideditor.style.js +18 -12
  67. package/src/js/plugins/grideditor.summernote.js +4 -5
  68. package/src/js/plugins/grideditor.tabs.js +311 -5
  69. package/src/js/plugins/grideditor.tinymce.js +4 -17
  70. package/src/js/style/accordion.js +14 -3
  71. package/src/js/style/display.js +229 -0
  72. package/src/js/style/drawerflow.js +118 -0
  73. package/src/js/style/flex.js +156 -0
  74. package/src/js/style/float.js +2 -4
  75. package/src/js/style/options.js +5 -20
  76. package/src/js/style/sections.js +42 -15
  77. package/src/js/style/spacing.js +2 -4
  78. package/src/js/style/sticky.js +39 -0
  79. package/src/js/style/textalign.js +2 -4
  80. package/src/js/text/grideditor.text.js +1 -1
  81. package/src/less/grideditor.less +68 -10
  82. package/types/grideditor.d.ts +24 -3
  83. package/dist/plugins/grideditor.float.esm.js +0 -43
  84. package/dist/plugins/grideditor.float.js +0 -47
  85. package/dist/plugins/grideditor.float.min.js +0 -1
  86. package/dist/plugins/grideditor.float.min.js.map +0 -7
  87. package/dist/plugins/grideditor.spacing.esm.js +0 -327
  88. package/dist/plugins/grideditor.spacing.js +0 -329
  89. package/dist/plugins/grideditor.spacing.min.js +0 -1
  90. package/dist/plugins/grideditor.spacing.min.js.map +0 -7
  91. package/dist/plugins/grideditor.textalign.esm.js +0 -49
  92. package/dist/plugins/grideditor.textalign.js +0 -53
  93. package/dist/plugins/grideditor.textalign.min.js +0 -1
  94. package/dist/plugins/grideditor.textalign.min.js.map +0 -7
  95. package/dist/plugins/grideditor.visibility.esm.js +0 -167
  96. package/dist/plugins/grideditor.visibility.js +0 -169
  97. package/dist/plugins/grideditor.visibility.min.js +0 -1
  98. package/dist/plugins/grideditor.visibility.min.js.map +0 -7
  99. package/src/js/plugins/grideditor.float.js +0 -29
  100. package/src/js/plugins/grideditor.spacing.js +0 -31
  101. package/src/js/plugins/grideditor.textalign.js +0 -27
  102. package/src/js/plugins/grideditor.visibility.js +0 -32
  103. package/src/js/style/visibility.js +0 -160
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/js/register.js", "../../src/js/dom.js", "../../src/js/plugins/grideditor.clipboard.js"],
4
- "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * The DOM, the way grid-editor uses it.\n *\n * Small helpers over the browser's own API, for the core and the shipped\n * plugins. Not a public API: a plugin of a host's own is free to write its\n * DOM code however it likes, and this file makes no promise to it.\n *\n * Stateless on purpose. The build puts a copy of this file in each plugin's\n * classic script, so anything kept here would be kept once per copy; a\n * module that needs to remember something about a node keeps its own\n * WeakMap.\n */\n\n/** Every element under `root` matching `selector`, as an array. */\nexport function all(root, selector) {\n return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];\n}\n\n/** The first element under `root` matching `selector`, or null. */\nexport function one(root, selector) {\n return root ? root.querySelector(selector) : null;\n}\n\n/** `root` itself when it matches, then every element under it that does. */\nexport function selfAndAll(root, selector) {\n if (!root) { return []; }\n\n var found = all(root, selector);\n if (root.nodeType === 1 && root.matches(selector)) { found.unshift(root); }\n return found;\n}\n\n/** The element children of `node`, those matching `selector` if one is given. */\nexport function children(node, selector) {\n if (!node) { return []; }\n\n return Array.prototype.filter.call(node.children, function(each) {\n return !selector || each.matches(selector);\n });\n}\n\n/** The first element child matching `selector`, or null. */\nexport function child(node, selector) {\n return children(node, selector)[0] || null;\n}\n\n/** The nearest ancestor-or-self matching `selector` below `stopAt`, or null. */\nexport function closest(node, selector, stopAt) {\n var found = node && node.nodeType === 1 ? node.closest(selector) : null;\n\n if (found && stopAt && found !== stopAt && !stopAt.contains(found)) { return null; }\n return found;\n}\n\n/** Whether `node` is an element matching `selector`. */\nexport function is(node, selector) {\n return !!node && node.nodeType === 1 && node.matches(selector);\n}\n\n/** Whether `node` is in the document. */\nexport function attached(node) {\n return !!node && document.documentElement.contains(node);\n}\n\n/** The element siblings after `node` that match `selector`. */\nexport function nextAll(node, selector) {\n var found = [];\n\n for (var next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (!selector || next.matches(selector)) { found.push(next); }\n }\n return found;\n}\n\n/** The ancestors of `node` up to, and not including, `stop`, nearest first. */\nexport function parentsUntil(node, stop) {\n var found = [];\n\n for (var parent = node.parentElement; parent && parent !== stop; parent = parent.parentElement) {\n found.push(parent);\n }\n return found;\n}\n\n/**\n * The nodes the html parses into, detached. Parsed the way innerHTML parses,\n * so a <script> in it never runs, here or once it is in the page.\n */\nexport function parse(html) {\n var template = document.createElement('template');\n template.innerHTML = html;\n return Array.prototype.slice.call(template.content.childNodes);\n}\n\n/** The one element the html is, detached. */\nexport function create(html) {\n var nodes = parse(html.trim());\n\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i].nodeType === 1) { return nodes[i]; }\n }\n return null;\n}\n\n/** An element of `tag`, with `attributes` and `text`. */\nexport function element(tag, attributes, text) {\n var node = document.createElement(tag);\n\n Object.keys(attributes || {}).forEach(function(name) {\n var value = attributes[name];\n if (value !== null && value !== undefined && value !== false) { node.setAttribute(name, value); }\n });\n if (text !== undefined && text !== null) { node.textContent = text; }\n\n return node;\n}\n\n/** Replace what `node` holds with `html`. A <script> in it does not run. */\nexport function setHtml(node, html) {\n node.innerHTML = html === undefined || html === null ? '' : String(html);\n return node;\n}\n\n/** Add one or several space separated classes. */\nexport function addClass(node, names) {\n split(names).forEach(function(name) { node.classList.add(name); });\n return node;\n}\n\nexport function removeClass(node, names) {\n split(names).forEach(function(name) { node.classList.remove(name); });\n return node;\n}\n\n/** Each class on, or off, or flipped when `on` is not given. */\nexport function toggleClass(node, names, state) {\n split(names).forEach(function(name) {\n if (state === undefined) {\n node.classList.toggle(name);\n } else {\n node.classList.toggle(name, !!state);\n }\n });\n return node;\n}\n\nexport function hasClass(node, name) {\n return !!node && node.nodeType === 1 && node.classList.contains(name);\n}\n\nfunction split(names) {\n return String(names || '').split(/\\s+/).filter(Boolean);\n}\n\n/** Take the class attribute off when there is nothing left in it. */\nexport function dropEmptyClass(node) {\n if (!node.getAttribute('class')) { node.removeAttribute('class'); }\n return node;\n}\n\n/** Take the style attribute off when there is nothing left in it. */\nexport function dropEmptyStyle(node) {\n if (!node.getAttribute('style')) { node.removeAttribute('style'); }\n return node;\n}\n\n/** Set attributes; a null or undefined value takes the attribute off. */\nexport function attr(node, attributes) {\n Object.keys(attributes).forEach(function(name) {\n var value = attributes[name];\n\n if (value === null || value === undefined) {\n node.removeAttribute(name);\n } else {\n node.setAttribute(name, value);\n }\n });\n return node;\n}\n\n/**\n * Inline styles, by css property name. A number is pixels for the properties\n * that take a length, as jQuery had it; an empty string takes one off.\n */\nexport function css(node, styles) {\n Object.keys(styles).forEach(function(property) {\n var value = styles[property];\n\n if (typeof value === 'number' && !UNITLESS[property]) { value = value + 'px'; }\n node.style.setProperty(property, value === null || value === undefined ? '' : String(value));\n });\n return node;\n}\n\nvar UNITLESS = { opacity: true, 'z-index': true, 'flex-grow': true, 'flex-shrink': true, order: true };\n\n/** What an element of this tag shows as when nothing hides it. */\nvar defaultDisplays = {};\n\nfunction defaultDisplay(node) {\n var tag = node.nodeName;\n\n if (!defaultDisplays[tag]) {\n var probe = document.body.appendChild(document.createElement(tag));\n defaultDisplays[tag] = getComputedStyle(probe).display;\n probe.remove();\n if (defaultDisplays[tag] === 'none') { defaultDisplays[tag] = 'block'; }\n }\n return defaultDisplays[tag];\n}\n\n/** Show a node: its inline display:none off, and a display of its own if a stylesheet hides it. */\nexport function show(node) {\n node.style.removeProperty('display');\n if (getComputedStyle(node).display === 'none') { node.style.display = defaultDisplay(node); }\n return node;\n}\n\nexport function hide(node) {\n node.style.display = 'none';\n return node;\n}\n\n/** Show or hide; flip when `on` is not given. */\nexport function toggle(node, state) {\n if (state === undefined) { state = !visible(node); }\n return state ? show(node) : hide(node);\n}\n\n/** Whether a node takes up room: what jQuery's :visible meant. */\nexport function visible(node) {\n return !!(node.offsetWidth || node.offsetHeight || node.getClientRects().length);\n}\n\n/** The border box's width, fractions included. */\nexport function outerWidth(node) {\n return node.getBoundingClientRect().width;\n}\n\nexport function outerHeight(node) {\n return node.getBoundingClientRect().height;\n}\n\n/** The content box's height, which is what jQuery's height() gave. */\nexport function contentHeight(node) {\n var style = getComputedStyle(node);\n return node.clientHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);\n}\n\n/** Where a node is on the page, not in the window. */\nexport function offset(node) {\n var box = node.getBoundingClientRect();\n return { top: box.top + window.pageYOffset, left: box.left + window.pageXOffset };\n}\n\n/** Its index among its parent's element children, those matching `selector` if given. */\nexport function indexIn(node, selector) {\n return children(node.parentElement, selector).indexOf(node);\n}\n\n/** Put `node` right after `reference`. */\nexport function insertAfter(node, reference) {\n reference.parentNode.insertBefore(node, reference.nextSibling);\n return node;\n}\n\n/** Replace `node` with what it holds. */\nexport function unwrap(node) {\n var parent = node.parentNode;\n\n while (node.firstChild) { parent.insertBefore(node.firstChild, node); }\n node.remove();\n}\n\n/** Put `node` inside `wrapper`, where `node` was. */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Listen on `root` for `types` (space separated) on descendants that match\n * `selector`, with `this` the matched element, as jQuery's delegated\n * handlers had it. Hands back the listener, for removeEventListener; a\n * signal in `options` removes it too.\n */\nexport function delegate(root, types, selector, handler, options) {\n var listener = function(event) {\n var match = closest(event.target, selector, root);\n if (match && root.contains(match)) { return handler.call(match, event); }\n return undefined;\n };\n\n split(types).forEach(function(type) { root.addEventListener(type, listener, options); });\n return listener;\n}\n\n/** Listen for several space separated event types with one handler. */\nexport function on(target, types, handler, options) {\n split(types).forEach(function(type) { target.addEventListener(type, handler, options); });\n return handler;\n}\n\nexport function off(target, types, handler, options) {\n split(types).forEach(function(type) { target.removeEventListener(type, handler, options); });\n}\n\n/** A mouse event of `type` sent to `node`, the way a pointer would. */\nexport function fire(node, type) {\n node.dispatchEvent(new MouseEvent(type, { bubbles: type !== 'mouseenter' && type !== 'mouseleave' }));\n}\n\n/* ------------------------------------------------------------------\n * Taking a node away, visibly.\n *\n * The durations are the ones 6.x had through jQuery: 400 ms unless the\n * caller says otherwise. `done` runs once the node is out of sight, which is\n * when the caller removes it; a node that is already out of sight is done at\n * once, on the next task, as jQuery had it.\n * ------------------------------------------------------------------ */\n\nvar DEFAULT_DURATION = 400;\n\nfunction animateAway(node, frames, duration, done) {\n duration = duration === undefined ? DEFAULT_DURATION : duration;\n\n var finish = function() {\n hide(node);\n if (done) { done(); }\n };\n\n if (!visible(node) || !node.animate || duration <= 0) {\n window.setTimeout(finish, 0);\n return;\n }\n\n var animation = node.animate(frames(getComputedStyle(node)), {\n duration: duration,\n easing: 'ease-in-out',\n });\n var called = false;\n var once = function() {\n if (called) { return; }\n called = true;\n finish();\n };\n\n animation.onfinish = once;\n animation.oncancel = once;\n}\n\n/** Fold a node up to nothing, then hide it. */\nexport function slideUp(node, duration, done) {\n if (typeof duration === 'function') {\n done = duration;\n duration = undefined;\n }\n\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n return [\n {\n height: style.height,\n paddingTop: style.paddingTop,\n paddingBottom: style.paddingBottom,\n marginTop: style.marginTop,\n marginBottom: style.marginBottom,\n },\n { height: '0px', paddingTop: '0px', paddingBottom: '0px', marginTop: '0px', marginBottom: '0px' },\n ];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n\n/** Fade a node out, then hide it. */\nexport function fadeOut(node, duration, done) {\n animateAway(node, function(style) {\n return [{ opacity: style.opacity }, { opacity: 0 }];\n }, duration, done);\n}\n\n/** Fade and fold a node, in height and, with `width`, sideways too, then hide it. */\nexport function shrinkAway(node, duration, done, width) {\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n var from = { opacity: style.opacity, height: style.height };\n var to = { opacity: 0, height: '0px' };\n\n if (width) {\n from.width = style.width;\n to.width = '0px';\n }\n return [from, to];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n", "/**\n * Copy and paste for grid-editor.\n *\n * A feature plugin: load this file after the editor and every row, column,\n * section, text block, container and element gets a copy tool, and every\n * place one of them can go gets a paste tool while there is something copied\n * that fits.\n * What it can ask the editor for is the handle its factory is called with,\n * described in docs/plugins.md.\n *\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.clipboard.min.js\"></script>\n *\n * What is copied is kept in localStorage, so it survives a reload and can be\n * pasted in another tab or another editor of the same site. A browser that\n * will not give the page its storage keeps it in memory, for this page only.\n *\n * A paste is an add like any other - before-add-* and after-add-*, with\n * `source: 'paste'` - so a host can turn one away.\n */\nimport { GridEditor } from '../grideditor.js';\nimport * as dom from '../dom.js';\n\nObject.assign(GridEditor.locales.en, {\n 'tool.copy': 'Copy',\n 'tool.paste': 'Paste',\n 'clipboard.paste_row': 'Paste row',\n 'clipboard.paste_section': 'Paste section',\n});\n\nvar STORAGE_ITEM = 'grideditor.clipboard';\nvar CHANGE = 'grideditor-clipboard';\nvar VERSION = 1;\n\n/** Where nothing can be stored, what was copied lives here, for this page. */\nvar memory = null;\n\n/**\n * What each drawer takes when something is pasted into it, by the kind of the\n * node the drawer belongs to. A category is what was copied: a row, a column,\n * a section, a text block, a container of any type, an element.\n */\nvar TARGETS = {\n column: ['row', 'text', 'container', 'element'],\n row: ['column'],\n section: ['row'],\n};\n\n/**\n * The attributes that point at an id, as the id itself or as a #selector.\n * A pasted copy that has to take new ids takes them here too, so its tabs,\n * its accordion and its popups still point at their own panes.\n */\nvar REFERENCES = ['data-bs-target', 'data-bs-parent', 'href', 'aria-controls', 'aria-labelledby',\n 'aria-describedby', 'for', 'data-ge-popup-id', 'data-ge-popup-target'];\n\n/** An id grid-editor generated: ge-{type}-{counter}-{random}. */\nvar GENERATED_ID = /^ge-([a-z][a-z-]*?)-\\d+-[a-z0-9]+$/;\n\nfunction read() {\n var raw;\n\n try {\n raw = window.localStorage.getItem(STORAGE_ITEM);\n } catch (error) {\n return memory;\n }\n if (raw === null) { return memory; }\n\n try {\n var clip = JSON.parse(raw);\n return clip && clip.version === VERSION && clip.html ? clip : null;\n } catch (error) {\n return null;\n }\n}\n\nfunction write(clip) {\n try {\n window.localStorage.setItem(STORAGE_ITEM, JSON.stringify(clip));\n memory = null;\n } catch (error) {\n memory = clip;\n }\n\n announce();\n}\n\n/** Every editor on the page looks at the clipboard again. */\nfunction announce() {\n document.dispatchEvent(new CustomEvent(CHANGE));\n}\n\n// Another tab copied something: every editor here looks again\nwindow.addEventListener('storage', function(e) {\n if (e.key === STORAGE_ITEM) { announce(); }\n});\n\nGridEditor.features.clipboard = function(ge) {\n\n var shown = null; // What the toolbar's paste buttons stand for\n var listening = false; // Whether refresh is on the document's change event\n\n function used(name) {\n return !ge.settings.plugins || ge.settings.plugins.indexOf(name) !== -1;\n }\n\n /** A category this editor can take: the plugin that makes it is here. */\n function available(clip) {\n if (clip.category === 'container') {\n return !!GridEditor.containers[clip.kind] && used(clip.kind);\n }\n if (clip.category === 'section') { return !!GridEditor.features.sections && used('sections'); }\n if (clip.category === 'element') { return !!GridEditor.features.elements && used('elements'); }\n\n return true;\n }\n\n function fits(clip, categories) {\n return !!clip && categories.indexOf(clip.category) !== -1 && available(clip);\n }\n\n function categoryOf(kind) {\n if (GridEditor.containers[kind]) { return 'container'; }\n\n return ['row', 'column', 'section', 'text', 'element'].indexOf(kind) !== -1 ? kind : null;\n }\n\n function copy(node, kind) {\n var html = ge.nodeHtml(node);\n\n write({ version: VERSION, category: categoryOf(kind), kind: kind, html: html });\n ge.emit('after-copy', ge.payloadFor(kind, node, { source: 'tool' }));\n\n // The canvas came back with new drawers: the one to flash is the\n // node's new copy tool\n var tool = dom.child(ge.drawerOf(node), '.ge-copy');\n if (!tool) { return; }\n\n var icon = dom.one(tool, 'i');\n dom.addClass(tool, 'ge-copied');\n if (icon) { icon.setAttribute('class', 'bi bi-check2'); }\n setTimeout(function() {\n dom.removeClass(tool, 'ge-copied');\n if (icon) { icon.setAttribute('class', 'bi bi-copy'); }\n }, 1200);\n }\n\n function paste(target, categories) {\n var clip = read();\n if (!fits(clip, categories)) { return; }\n\n ge.place(fresh(clip.html), clip.kind, { appendTo: target, source: 'paste' });\n }\n\n /**\n * The copied markup as a node, with new ids where the page already has\n * them: two copies of a tab strip pointing at one set of panes is a tab\n * strip that opens the other copy's tabs. An id the page does not have\n * is kept, so pasting into another page changes nothing.\n *\n * Parsed the way innerHTML parses, so a <script> in what was copied is\n * markup, pasted like the rest, and does not run in the editor.\n */\n function fresh(html) {\n var node = dom.create(html);\n var renamed = {};\n var taken = function(id) {\n return !!document.getElementById(id) || Object.keys(renamed).some(function(old) {\n return renamed[old] === id;\n });\n };\n\n dom.selfAndAll(node, '[id]').forEach(function(element) {\n var id = element.id;\n if (!document.getElementById(id)) { return; }\n\n var generated = GENERATED_ID.exec(id);\n var next;\n\n if (generated) {\n do { next = ge.containerId(generated[1]); } while (taken(next));\n } else {\n var n = 2;\n while (taken(id + '-' + n)) { n++; }\n next = id + '-' + n;\n }\n\n renamed[id] = next;\n element.id = next;\n });\n\n if (!Object.keys(renamed).length) { return node; }\n\n dom.selfAndAll(node, '*').forEach(function(element) {\n REFERENCES.forEach(function(name) {\n var value = element.getAttribute(name);\n if (value === null) { return; }\n if (name === 'href' && value.charAt(0) !== '#') { return; }\n\n var rewritten = value.split(/(\\s+)/).map(function(token) {\n if (renamed[token]) { return renamed[token]; }\n if (token.charAt(0) === '#' && renamed[token.slice(1)]) { return '#' + renamed[token.slice(1)]; }\n\n return token;\n }).join('');\n\n if (rewritten !== value) { element.setAttribute(name, rewritten); }\n });\n });\n\n return node;\n }\n\n /** Show the paste tools, and the toolbar's paste buttons, that fit what is copied. */\n function refresh() {\n var clip = read();\n\n dom.all(ge.canvas, '.ge-paste').forEach(function(tool) {\n dom.toggle(tool, fits(clip, tool.getAttribute('data-ge-paste').split(' ')));\n });\n\n ge.toolbarItems('clipboard').forEach(function(button) {\n var item = TOOLBAR[parseInt(button.getAttribute('data-ge-item'), 10)];\n dom.toggle(button, fits(clip, [item.kind]));\n });\n\n shown = clip;\n }\n\n var TOOLBAR = [\n { kind: 'row', labelKey: 'clipboard.paste_row' },\n { kind: 'section', labelKey: 'clipboard.paste_section' },\n ].map(function(item) {\n return Object.assign(item, {\n iconClass: 'bi bi-clipboard-plus',\n // On the right, as an icon: pasting is not one of the things\n // the add buttons make\n align: 'end',\n source: 'paste',\n // What the button showed, even if another tab has copied\n // something else since\n create: function() { return fresh(shown.html); },\n });\n });\n\n return {\n drawerTools: function(drawer, node, kind) {\n if (categoryOf(kind)) {\n ge.createTool(drawer, ge.t('tool.copy'), 'ge-copy', 'bi bi-copy', function() {\n copy(node, kind);\n });\n }\n\n var categories = TARGETS[kind];\n if (!categories) { return; }\n\n var tool = ge.createTool(drawer, ge.t('tool.paste'), 'ge-paste', 'bi bi-clipboard-plus', function() {\n paste(node, categories);\n });\n tool.setAttribute('data-ge-paste', categories.join(' '));\n dom.toggle(tool, fits(read(), categories));\n },\n\n toolbar: TOOLBAR,\n\n onInit: function() {\n refresh();\n if (!listening) {\n document.addEventListener(CHANGE, refresh);\n listening = true;\n }\n },\n\n onDeinit: function() {\n document.removeEventListener(CHANGE, refresh);\n listening = false;\n },\n };\n};\n"],
4
+ "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * The DOM, the way grid-editor uses it.\n *\n * Small helpers over the browser's own API, for the core and the shipped\n * plugins. Not a public API: a plugin of a host's own is free to write its\n * DOM code however it likes, and this file makes no promise to it.\n *\n * Stateless on purpose. The build puts a copy of this file in each plugin's\n * classic script, so anything kept here would be kept once per copy; a\n * module that needs to remember something about a node keeps its own\n * WeakMap.\n */\n\n/** Every element under `root` matching `selector`, as an array. */\nexport function all(root, selector) {\n return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];\n}\n\n/** The first element under `root` matching `selector`, or null. */\nexport function one(root, selector) {\n return root ? root.querySelector(selector) : null;\n}\n\n/** `root` itself when it matches, then every element under it that does. */\nexport function selfAndAll(root, selector) {\n if (!root) { return []; }\n\n var found = all(root, selector);\n if (root.nodeType === 1 && root.matches(selector)) { found.unshift(root); }\n return found;\n}\n\n/** The element children of `node`, those matching `selector` if one is given. */\nexport function children(node, selector) {\n if (!node) { return []; }\n\n return Array.prototype.filter.call(node.children, function(each) {\n return !selector || each.matches(selector);\n });\n}\n\n/** The first element child matching `selector`, or null. */\nexport function child(node, selector) {\n return children(node, selector)[0] || null;\n}\n\n/** The nearest ancestor-or-self matching `selector` below `stopAt`, or null. */\nexport function closest(node, selector, stopAt) {\n var found = node && node.nodeType === 1 ? node.closest(selector) : null;\n\n if (found && stopAt && found !== stopAt && !stopAt.contains(found)) { return null; }\n return found;\n}\n\n/** Whether `node` is an element matching `selector`. */\nexport function is(node, selector) {\n return !!node && node.nodeType === 1 && node.matches(selector);\n}\n\n/** Whether `node` is in the document. */\nexport function attached(node) {\n return !!node && document.documentElement.contains(node);\n}\n\n/** The element siblings after `node` that match `selector`. */\nexport function nextAll(node, selector) {\n var found = [];\n\n for (var next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (!selector || next.matches(selector)) { found.push(next); }\n }\n return found;\n}\n\n/** The ancestors of `node` up to, and not including, `stop`, nearest first. */\nexport function parentsUntil(node, stop) {\n var found = [];\n\n for (var parent = node.parentElement; parent && parent !== stop; parent = parent.parentElement) {\n found.push(parent);\n }\n return found;\n}\n\n/**\n * The nodes the html parses into, detached. Parsed the way innerHTML parses,\n * so a <script> in it never runs, here or once it is in the page.\n */\nexport function parse(html) {\n var template = document.createElement('template');\n template.innerHTML = html;\n return Array.prototype.slice.call(template.content.childNodes);\n}\n\n/** The one element the html is, detached. */\nexport function create(html) {\n var nodes = parse(html.trim());\n\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i].nodeType === 1) { return nodes[i]; }\n }\n return null;\n}\n\n/** An element of `tag`, with `attributes` and `text`. */\nexport function element(tag, attributes, text) {\n var node = document.createElement(tag);\n\n Object.keys(attributes || {}).forEach(function(name) {\n var value = attributes[name];\n if (value !== null && value !== undefined && value !== false) { node.setAttribute(name, value); }\n });\n if (text !== undefined && text !== null) { node.textContent = text; }\n\n return node;\n}\n\n/** Replace what `node` holds with `html`. A <script> in it does not run. */\nexport function setHtml(node, html) {\n node.innerHTML = html === undefined || html === null ? '' : String(html);\n return node;\n}\n\n/** Add one or several space separated classes. */\nexport function addClass(node, names) {\n split(names).forEach(function(name) { node.classList.add(name); });\n return node;\n}\n\nexport function removeClass(node, names) {\n split(names).forEach(function(name) { node.classList.remove(name); });\n return node;\n}\n\n/** Each class on, or off, or flipped when `on` is not given. */\nexport function toggleClass(node, names, state) {\n split(names).forEach(function(name) {\n if (state === undefined) {\n node.classList.toggle(name);\n } else {\n node.classList.toggle(name, !!state);\n }\n });\n return node;\n}\n\nexport function hasClass(node, name) {\n return !!node && node.nodeType === 1 && node.classList.contains(name);\n}\n\nfunction split(names) {\n return String(names || '').split(/\\s+/).filter(Boolean);\n}\n\n/** Take the class attribute off when there is nothing left in it. */\nexport function dropEmptyClass(node) {\n if (!node.getAttribute('class')) { node.removeAttribute('class'); }\n return node;\n}\n\n/** Take the style attribute off when there is nothing left in it. */\nexport function dropEmptyStyle(node) {\n if (!node.getAttribute('style')) { node.removeAttribute('style'); }\n return node;\n}\n\n/** Set attributes; a null or undefined value takes the attribute off. */\nexport function attr(node, attributes) {\n Object.keys(attributes).forEach(function(name) {\n var value = attributes[name];\n\n if (value === null || value === undefined) {\n node.removeAttribute(name);\n } else {\n node.setAttribute(name, value);\n }\n });\n return node;\n}\n\n/**\n * Inline styles, by css property name. A number is pixels for the properties\n * that take a length, as jQuery had it; an empty string takes one off.\n */\nexport function css(node, styles) {\n Object.keys(styles).forEach(function(property) {\n var value = styles[property];\n\n if (typeof value === 'number' && !UNITLESS[property]) { value = value + 'px'; }\n node.style.setProperty(property, value === null || value === undefined ? '' : String(value));\n });\n return node;\n}\n\nvar UNITLESS = { opacity: true, 'z-index': true, 'flex-grow': true, 'flex-shrink': true, order: true };\n\n/** What an element of this tag shows as when nothing hides it. */\nvar defaultDisplays = {};\n\nfunction defaultDisplay(node) {\n var tag = node.nodeName;\n\n if (!defaultDisplays[tag]) {\n var probe = document.body.appendChild(document.createElement(tag));\n defaultDisplays[tag] = getComputedStyle(probe).display;\n probe.remove();\n if (defaultDisplays[tag] === 'none') { defaultDisplays[tag] = 'block'; }\n }\n return defaultDisplays[tag];\n}\n\n/** Show a node: its inline display:none off, and a display of its own if a stylesheet hides it. */\nexport function show(node) {\n node.style.removeProperty('display');\n if (getComputedStyle(node).display === 'none') { node.style.display = defaultDisplay(node); }\n return node;\n}\n\nexport function hide(node) {\n node.style.display = 'none';\n return node;\n}\n\n/** Show or hide; flip when `on` is not given. */\nexport function toggle(node, state) {\n if (state === undefined) { state = !visible(node); }\n return state ? show(node) : hide(node);\n}\n\n/** Whether a node takes up room: what jQuery's :visible meant. */\nexport function visible(node) {\n return !!(node.offsetWidth || node.offsetHeight || node.getClientRects().length);\n}\n\n/** The border box's width, fractions included. */\nexport function outerWidth(node) {\n return node.getBoundingClientRect().width;\n}\n\nexport function outerHeight(node) {\n return node.getBoundingClientRect().height;\n}\n\n/** The content box's height, which is what jQuery's height() gave. */\nexport function contentHeight(node) {\n var style = getComputedStyle(node);\n return node.clientHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);\n}\n\n/** Where a node is on the page, not in the window. */\nexport function offset(node) {\n var box = node.getBoundingClientRect();\n return { top: box.top + window.pageYOffset, left: box.left + window.pageXOffset };\n}\n\n/** Its index among its parent's element children, those matching `selector` if given. */\nexport function indexIn(node, selector) {\n return children(node.parentElement, selector).indexOf(node);\n}\n\n/** Put `node` right after `reference`. */\nexport function insertAfter(node, reference) {\n reference.parentNode.insertBefore(node, reference.nextSibling);\n return node;\n}\n\n/** Replace `node` with what it holds. */\nexport function unwrap(node) {\n var parent = node.parentNode;\n\n while (node.firstChild) { parent.insertBefore(node.firstChild, node); }\n node.remove();\n}\n\n/** Put `node` inside `wrapper`, where `node` was. */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Listen on `root` for `types` (space separated) on descendants that match\n * `selector`, with `this` the matched element, as jQuery's delegated\n * handlers had it. Hands back the listener, for removeEventListener; a\n * signal in `options` removes it too.\n */\nexport function delegate(root, types, selector, handler, options) {\n var listener = function(event) {\n var match = closest(event.target, selector, root);\n if (match && root.contains(match)) { return handler.call(match, event); }\n return undefined;\n };\n\n split(types).forEach(function(type) { root.addEventListener(type, listener, options); });\n return listener;\n}\n\n/** Listen for several space separated event types with one handler. */\nexport function on(target, types, handler, options) {\n split(types).forEach(function(type) { target.addEventListener(type, handler, options); });\n return handler;\n}\n\nexport function off(target, types, handler, options) {\n split(types).forEach(function(type) { target.removeEventListener(type, handler, options); });\n}\n\n/** A mouse event of `type` sent to `node`, the way a pointer would. */\nexport function fire(node, type) {\n node.dispatchEvent(new MouseEvent(type, { bubbles: type !== 'mouseenter' && type !== 'mouseleave' }));\n}\n\n/* ------------------------------------------------------------------\n * Taking a node away, visibly.\n *\n * The durations are jQuery's: 400 ms unless the caller says otherwise. `done` runs once the node is out of sight, which is\n * when the caller removes it; a node that is already out of sight is done at\n * once, on the next task, as jQuery had it.\n * ------------------------------------------------------------------ */\n\nvar DEFAULT_DURATION = 400;\n\nfunction animateAway(node, frames, duration, done) {\n duration = duration === undefined ? DEFAULT_DURATION : duration;\n\n var finish = function() {\n hide(node);\n if (done) { done(); }\n };\n\n if (!visible(node) || !node.animate || duration <= 0) {\n window.setTimeout(finish, 0);\n return;\n }\n\n var animation = node.animate(frames(getComputedStyle(node)), {\n duration: duration,\n easing: 'ease-in-out',\n });\n var called = false;\n var once = function() {\n if (called) { return; }\n called = true;\n finish();\n };\n\n animation.onfinish = once;\n animation.oncancel = once;\n}\n\n/** Fold a node up to nothing, then hide it. */\nexport function slideUp(node, duration, done) {\n if (typeof duration === 'function') {\n done = duration;\n duration = undefined;\n }\n\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n return [\n {\n height: style.height,\n paddingTop: style.paddingTop,\n paddingBottom: style.paddingBottom,\n marginTop: style.marginTop,\n marginBottom: style.marginBottom,\n },\n { height: '0px', paddingTop: '0px', paddingBottom: '0px', marginTop: '0px', marginBottom: '0px' },\n ];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n\n/** Fade a node out, then hide it. */\nexport function fadeOut(node, duration, done) {\n animateAway(node, function(style) {\n return [{ opacity: style.opacity }, { opacity: 0 }];\n }, duration, done);\n}\n\n/** Fade and fold a node, in height and, with `width`, sideways too, then hide it. */\nexport function shrinkAway(node, duration, done, width) {\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n var from = { opacity: style.opacity, height: style.height };\n var to = { opacity: 0, height: '0px' };\n\n if (width) {\n from.width = style.width;\n to.width = '0px';\n }\n return [from, to];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n", "/**\n * Copy and paste for grid-editor.\n *\n * A feature plugin: load this file after the editor and every row, column,\n * section, text block, container and element gets a copy tool, and every\n * place one of them can go gets a paste tool while there is something copied\n * that fits.\n * What it can ask the editor for is the handle its factory is called with,\n * described in docs/plugins.md.\n *\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.clipboard.min.js\"></script>\n *\n * What is copied is kept in localStorage, so it survives a reload and can be\n * pasted in another tab or another editor of the same site. A browser that\n * will not give the page its storage keeps it in memory, for this page only.\n *\n * A paste is an add like any other - before-add-* and after-add-*, with\n * `source: 'paste'` - so a host can turn one away.\n */\nimport { GridEditor } from '../grideditor.js';\nimport * as dom from '../dom.js';\n\nObject.assign(GridEditor.locales.en, {\n 'tool.copy': 'Copy',\n 'tool.paste': 'Paste',\n 'clipboard.paste_row': 'Paste row',\n 'clipboard.paste_section': 'Paste section',\n});\n\nvar STORAGE_ITEM = 'grideditor.clipboard';\nvar CHANGE = 'grideditor-clipboard';\nvar VERSION = 1;\n\n/** Where nothing can be stored, what was copied lives here, for this page. */\nvar memory = null;\n\n/**\n * What each drawer takes when something is pasted into it, by the kind of the\n * node the drawer belongs to. A category is what was copied: a row, a column,\n * a section, a text block, a container of any type, an element.\n */\nvar TARGETS = {\n column: ['row', 'text', 'container', 'element'],\n row: ['column'],\n section: ['row'],\n};\n\n/**\n * The attributes that point at an id, as the id itself or as a #selector.\n * A pasted copy that has to take new ids takes them here too, so its tabs,\n * its accordion and its popups still point at their own panes.\n */\nvar REFERENCES = ['data-bs-target', 'data-bs-parent', 'href', 'aria-controls', 'aria-labelledby',\n 'aria-describedby', 'for', 'data-ge-popup-id', 'data-ge-popup-target'];\n\n/** An id grid-editor generated: ge-{type}-{counter}-{random}. */\nvar GENERATED_ID = /^ge-([a-z][a-z-]*?)-\\d+-[a-z0-9]+$/;\n\nfunction read() {\n var raw;\n\n try {\n raw = window.localStorage.getItem(STORAGE_ITEM);\n } catch (error) {\n return memory;\n }\n if (raw === null) { return memory; }\n\n try {\n var clip = JSON.parse(raw);\n return clip && clip.version === VERSION && clip.html ? clip : null;\n } catch (error) {\n return null;\n }\n}\n\nfunction write(clip) {\n try {\n window.localStorage.setItem(STORAGE_ITEM, JSON.stringify(clip));\n memory = null;\n } catch (error) {\n memory = clip;\n }\n\n announce();\n}\n\n/** Every editor on the page looks at the clipboard again. */\nfunction announce() {\n document.dispatchEvent(new CustomEvent(CHANGE));\n}\n\n// Another tab copied something: every editor here looks again\nwindow.addEventListener('storage', function(e) {\n if (e.key === STORAGE_ITEM) { announce(); }\n});\n\nGridEditor.features.clipboard = function(ge) {\n\n var shown = null; // What the toolbar's paste buttons stand for\n var listening = false; // Whether refresh is on the document's change event\n\n function used(name) {\n return !ge.settings.plugins || ge.settings.plugins.indexOf(name) !== -1;\n }\n\n /** A category this editor can take: the plugin that makes it is here. */\n function available(clip) {\n if (clip.category === 'container') {\n return !!GridEditor.containers[clip.kind] && used(clip.kind);\n }\n if (clip.category === 'section') { return !!GridEditor.features.sections && used('sections'); }\n if (clip.category === 'element') { return !!GridEditor.features.elements && used('elements'); }\n\n return true;\n }\n\n function fits(clip, categories) {\n return !!clip && categories.indexOf(clip.category) !== -1 && available(clip);\n }\n\n function categoryOf(kind) {\n if (GridEditor.containers[kind]) { return 'container'; }\n\n return ['row', 'column', 'section', 'text', 'element'].indexOf(kind) !== -1 ? kind : null;\n }\n\n function copy(node, kind) {\n var html = ge.nodeHtml(node);\n\n write({ version: VERSION, category: categoryOf(kind), kind: kind, html: html });\n ge.emit('after-copy', ge.payloadFor(kind, node, { source: 'tool' }));\n\n // The canvas came back with new drawers: the one to flash is the\n // node's new copy tool\n var tool = dom.child(ge.drawerOf(node), '.ge-copy');\n if (!tool) { return; }\n\n var icon = dom.one(tool, 'i');\n dom.addClass(tool, 'ge-copied');\n if (icon) { icon.setAttribute('class', 'bi bi-check2'); }\n setTimeout(function() {\n dom.removeClass(tool, 'ge-copied');\n if (icon) { icon.setAttribute('class', 'bi bi-copy'); }\n }, 1200);\n }\n\n function paste(target, categories) {\n var clip = read();\n if (!fits(clip, categories)) { return; }\n\n ge.place(fresh(clip.html), clip.kind, { appendTo: target, source: 'paste' });\n }\n\n /**\n * The copied markup as a node, with new ids where the page already has\n * them: two copies of a tab strip pointing at one set of panes is a tab\n * strip that opens the other copy's tabs. An id the page does not have\n * is kept, so pasting into another page changes nothing.\n *\n * Parsed the way innerHTML parses, so a <script> in what was copied is\n * markup, pasted like the rest, and does not run in the editor.\n */\n function fresh(html) {\n var node = dom.create(html);\n var renamed = {};\n var taken = function(id) {\n return !!document.getElementById(id) || Object.keys(renamed).some(function(old) {\n return renamed[old] === id;\n });\n };\n\n dom.selfAndAll(node, '[id]').forEach(function(element) {\n var id = element.id;\n if (!document.getElementById(id)) { return; }\n\n var generated = GENERATED_ID.exec(id);\n var next;\n\n if (generated) {\n do { next = ge.containerId(generated[1]); } while (taken(next));\n } else {\n var n = 2;\n while (taken(id + '-' + n)) { n++; }\n next = id + '-' + n;\n }\n\n renamed[id] = next;\n element.id = next;\n });\n\n if (!Object.keys(renamed).length) { return node; }\n\n dom.selfAndAll(node, '*').forEach(function(element) {\n REFERENCES.forEach(function(name) {\n var value = element.getAttribute(name);\n if (value === null) { return; }\n if (name === 'href' && value.charAt(0) !== '#') { return; }\n\n var rewritten = value.split(/(\\s+)/).map(function(token) {\n if (renamed[token]) { return renamed[token]; }\n if (token.charAt(0) === '#' && renamed[token.slice(1)]) { return '#' + renamed[token.slice(1)]; }\n\n return token;\n }).join('');\n\n if (rewritten !== value) { element.setAttribute(name, rewritten); }\n });\n });\n\n return node;\n }\n\n /** Show the paste tools, and the toolbar's paste buttons, that fit what is copied. */\n function refresh() {\n var clip = read();\n\n dom.all(ge.canvas, '.ge-paste').forEach(function(tool) {\n dom.toggle(tool, fits(clip, tool.getAttribute('data-ge-paste').split(' ')));\n });\n\n ge.toolbarItems('clipboard').forEach(function(button) {\n var item = TOOLBAR[parseInt(button.getAttribute('data-ge-item'), 10)];\n dom.toggle(button, fits(clip, [item.kind]));\n });\n\n shown = clip;\n }\n\n var TOOLBAR = [\n { kind: 'row', labelKey: 'clipboard.paste_row' },\n { kind: 'section', labelKey: 'clipboard.paste_section' },\n ].map(function(item) {\n return Object.assign(item, {\n iconClass: 'bi bi-clipboard-plus',\n // On the right, as an icon: pasting is not one of the things\n // the add buttons make\n align: 'end',\n source: 'paste',\n // What the button showed, even if another tab has copied\n // something else since\n create: function() { return fresh(shown.html); },\n });\n });\n\n return {\n drawerTools: function(drawer, node, kind) {\n if (categoryOf(kind)) {\n ge.createTool(drawer, ge.t('tool.copy'), 'ge-copy', 'bi bi-copy', function() {\n copy(node, kind);\n });\n }\n\n var categories = TARGETS[kind];\n if (!categories) { return; }\n\n var tool = ge.createTool(drawer, ge.t('tool.paste'), 'ge-paste', 'bi bi-clipboard-plus', function() {\n paste(node, categories);\n });\n tool.setAttribute('data-ge-paste', categories.join(' '));\n dom.toggle(tool, fits(read(), categories));\n },\n\n toolbar: TOOLBAR,\n\n onInit: function() {\n refresh();\n if (!listening) {\n document.addEventListener(CHANGE, refresh);\n listening = true;\n }\n },\n\n onDeinit: function() {\n document.removeEventListener(CHANGE, refresh);\n listening = false;\n },\n };\n};\n"],
5
5
  "mappings": "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",
6
6
  "names": ["GridEditor", "all", "root", "selector", "one", "selfAndAll", "found", "children", "node", "each", "child", "parse", "html", "template", "create", "nodes", "i", "addClass", "node", "names", "split", "name", "removeClass", "split", "names", "defaultDisplays", "defaultDisplay", "node", "tag", "probe", "show", "hide", "toggle", "state", "visible", "GridEditor", "STORAGE_ITEM", "CHANGE", "VERSION", "memory", "TARGETS", "REFERENCES", "GENERATED_ID", "read", "raw", "error", "clip", "write", "announce", "e", "ge", "shown", "listening", "used", "name", "available", "fits", "categories", "categoryOf", "kind", "copy", "node", "html", "tool", "child", "icon", "one", "addClass", "removeClass", "paste", "target", "fresh", "create", "renamed", "taken", "id", "old", "selfAndAll", "element", "generated", "next", "n", "value", "rewritten", "token", "refresh", "all", "toggle", "button", "item", "TOOLBAR", "drawer"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/js/register.js", "../../src/js/dom.js", "../../src/js/plugins/grideditor.codemirror-inline.js"],
4
- "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * The DOM, the way grid-editor uses it.\n *\n * Small helpers over the browser's own API, for the core and the shipped\n * plugins. Not a public API: a plugin of a host's own is free to write its\n * DOM code however it likes, and this file makes no promise to it.\n *\n * Stateless on purpose. The build puts a copy of this file in each plugin's\n * classic script, so anything kept here would be kept once per copy; a\n * module that needs to remember something about a node keeps its own\n * WeakMap.\n */\n\n/** Every element under `root` matching `selector`, as an array. */\nexport function all(root, selector) {\n return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];\n}\n\n/** The first element under `root` matching `selector`, or null. */\nexport function one(root, selector) {\n return root ? root.querySelector(selector) : null;\n}\n\n/** `root` itself when it matches, then every element under it that does. */\nexport function selfAndAll(root, selector) {\n if (!root) { return []; }\n\n var found = all(root, selector);\n if (root.nodeType === 1 && root.matches(selector)) { found.unshift(root); }\n return found;\n}\n\n/** The element children of `node`, those matching `selector` if one is given. */\nexport function children(node, selector) {\n if (!node) { return []; }\n\n return Array.prototype.filter.call(node.children, function(each) {\n return !selector || each.matches(selector);\n });\n}\n\n/** The first element child matching `selector`, or null. */\nexport function child(node, selector) {\n return children(node, selector)[0] || null;\n}\n\n/** The nearest ancestor-or-self matching `selector` below `stopAt`, or null. */\nexport function closest(node, selector, stopAt) {\n var found = node && node.nodeType === 1 ? node.closest(selector) : null;\n\n if (found && stopAt && found !== stopAt && !stopAt.contains(found)) { return null; }\n return found;\n}\n\n/** Whether `node` is an element matching `selector`. */\nexport function is(node, selector) {\n return !!node && node.nodeType === 1 && node.matches(selector);\n}\n\n/** Whether `node` is in the document. */\nexport function attached(node) {\n return !!node && document.documentElement.contains(node);\n}\n\n/** The element siblings after `node` that match `selector`. */\nexport function nextAll(node, selector) {\n var found = [];\n\n for (var next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (!selector || next.matches(selector)) { found.push(next); }\n }\n return found;\n}\n\n/** The ancestors of `node` up to, and not including, `stop`, nearest first. */\nexport function parentsUntil(node, stop) {\n var found = [];\n\n for (var parent = node.parentElement; parent && parent !== stop; parent = parent.parentElement) {\n found.push(parent);\n }\n return found;\n}\n\n/**\n * The nodes the html parses into, detached. Parsed the way innerHTML parses,\n * so a <script> in it never runs, here or once it is in the page.\n */\nexport function parse(html) {\n var template = document.createElement('template');\n template.innerHTML = html;\n return Array.prototype.slice.call(template.content.childNodes);\n}\n\n/** The one element the html is, detached. */\nexport function create(html) {\n var nodes = parse(html.trim());\n\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i].nodeType === 1) { return nodes[i]; }\n }\n return null;\n}\n\n/** An element of `tag`, with `attributes` and `text`. */\nexport function element(tag, attributes, text) {\n var node = document.createElement(tag);\n\n Object.keys(attributes || {}).forEach(function(name) {\n var value = attributes[name];\n if (value !== null && value !== undefined && value !== false) { node.setAttribute(name, value); }\n });\n if (text !== undefined && text !== null) { node.textContent = text; }\n\n return node;\n}\n\n/** Replace what `node` holds with `html`. A <script> in it does not run. */\nexport function setHtml(node, html) {\n node.innerHTML = html === undefined || html === null ? '' : String(html);\n return node;\n}\n\n/** Add one or several space separated classes. */\nexport function addClass(node, names) {\n split(names).forEach(function(name) { node.classList.add(name); });\n return node;\n}\n\nexport function removeClass(node, names) {\n split(names).forEach(function(name) { node.classList.remove(name); });\n return node;\n}\n\n/** Each class on, or off, or flipped when `on` is not given. */\nexport function toggleClass(node, names, state) {\n split(names).forEach(function(name) {\n if (state === undefined) {\n node.classList.toggle(name);\n } else {\n node.classList.toggle(name, !!state);\n }\n });\n return node;\n}\n\nexport function hasClass(node, name) {\n return !!node && node.nodeType === 1 && node.classList.contains(name);\n}\n\nfunction split(names) {\n return String(names || '').split(/\\s+/).filter(Boolean);\n}\n\n/** Take the class attribute off when there is nothing left in it. */\nexport function dropEmptyClass(node) {\n if (!node.getAttribute('class')) { node.removeAttribute('class'); }\n return node;\n}\n\n/** Take the style attribute off when there is nothing left in it. */\nexport function dropEmptyStyle(node) {\n if (!node.getAttribute('style')) { node.removeAttribute('style'); }\n return node;\n}\n\n/** Set attributes; a null or undefined value takes the attribute off. */\nexport function attr(node, attributes) {\n Object.keys(attributes).forEach(function(name) {\n var value = attributes[name];\n\n if (value === null || value === undefined) {\n node.removeAttribute(name);\n } else {\n node.setAttribute(name, value);\n }\n });\n return node;\n}\n\n/**\n * Inline styles, by css property name. A number is pixels for the properties\n * that take a length, as jQuery had it; an empty string takes one off.\n */\nexport function css(node, styles) {\n Object.keys(styles).forEach(function(property) {\n var value = styles[property];\n\n if (typeof value === 'number' && !UNITLESS[property]) { value = value + 'px'; }\n node.style.setProperty(property, value === null || value === undefined ? '' : String(value));\n });\n return node;\n}\n\nvar UNITLESS = { opacity: true, 'z-index': true, 'flex-grow': true, 'flex-shrink': true, order: true };\n\n/** What an element of this tag shows as when nothing hides it. */\nvar defaultDisplays = {};\n\nfunction defaultDisplay(node) {\n var tag = node.nodeName;\n\n if (!defaultDisplays[tag]) {\n var probe = document.body.appendChild(document.createElement(tag));\n defaultDisplays[tag] = getComputedStyle(probe).display;\n probe.remove();\n if (defaultDisplays[tag] === 'none') { defaultDisplays[tag] = 'block'; }\n }\n return defaultDisplays[tag];\n}\n\n/** Show a node: its inline display:none off, and a display of its own if a stylesheet hides it. */\nexport function show(node) {\n node.style.removeProperty('display');\n if (getComputedStyle(node).display === 'none') { node.style.display = defaultDisplay(node); }\n return node;\n}\n\nexport function hide(node) {\n node.style.display = 'none';\n return node;\n}\n\n/** Show or hide; flip when `on` is not given. */\nexport function toggle(node, state) {\n if (state === undefined) { state = !visible(node); }\n return state ? show(node) : hide(node);\n}\n\n/** Whether a node takes up room: what jQuery's :visible meant. */\nexport function visible(node) {\n return !!(node.offsetWidth || node.offsetHeight || node.getClientRects().length);\n}\n\n/** The border box's width, fractions included. */\nexport function outerWidth(node) {\n return node.getBoundingClientRect().width;\n}\n\nexport function outerHeight(node) {\n return node.getBoundingClientRect().height;\n}\n\n/** The content box's height, which is what jQuery's height() gave. */\nexport function contentHeight(node) {\n var style = getComputedStyle(node);\n return node.clientHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);\n}\n\n/** Where a node is on the page, not in the window. */\nexport function offset(node) {\n var box = node.getBoundingClientRect();\n return { top: box.top + window.pageYOffset, left: box.left + window.pageXOffset };\n}\n\n/** Its index among its parent's element children, those matching `selector` if given. */\nexport function indexIn(node, selector) {\n return children(node.parentElement, selector).indexOf(node);\n}\n\n/** Put `node` right after `reference`. */\nexport function insertAfter(node, reference) {\n reference.parentNode.insertBefore(node, reference.nextSibling);\n return node;\n}\n\n/** Replace `node` with what it holds. */\nexport function unwrap(node) {\n var parent = node.parentNode;\n\n while (node.firstChild) { parent.insertBefore(node.firstChild, node); }\n node.remove();\n}\n\n/** Put `node` inside `wrapper`, where `node` was. */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Listen on `root` for `types` (space separated) on descendants that match\n * `selector`, with `this` the matched element, as jQuery's delegated\n * handlers had it. Hands back the listener, for removeEventListener; a\n * signal in `options` removes it too.\n */\nexport function delegate(root, types, selector, handler, options) {\n var listener = function(event) {\n var match = closest(event.target, selector, root);\n if (match && root.contains(match)) { return handler.call(match, event); }\n return undefined;\n };\n\n split(types).forEach(function(type) { root.addEventListener(type, listener, options); });\n return listener;\n}\n\n/** Listen for several space separated event types with one handler. */\nexport function on(target, types, handler, options) {\n split(types).forEach(function(type) { target.addEventListener(type, handler, options); });\n return handler;\n}\n\nexport function off(target, types, handler, options) {\n split(types).forEach(function(type) { target.removeEventListener(type, handler, options); });\n}\n\n/** A mouse event of `type` sent to `node`, the way a pointer would. */\nexport function fire(node, type) {\n node.dispatchEvent(new MouseEvent(type, { bubbles: type !== 'mouseenter' && type !== 'mouseleave' }));\n}\n\n/* ------------------------------------------------------------------\n * Taking a node away, visibly.\n *\n * The durations are the ones 6.x had through jQuery: 400 ms unless the\n * caller says otherwise. `done` runs once the node is out of sight, which is\n * when the caller removes it; a node that is already out of sight is done at\n * once, on the next task, as jQuery had it.\n * ------------------------------------------------------------------ */\n\nvar DEFAULT_DURATION = 400;\n\nfunction animateAway(node, frames, duration, done) {\n duration = duration === undefined ? DEFAULT_DURATION : duration;\n\n var finish = function() {\n hide(node);\n if (done) { done(); }\n };\n\n if (!visible(node) || !node.animate || duration <= 0) {\n window.setTimeout(finish, 0);\n return;\n }\n\n var animation = node.animate(frames(getComputedStyle(node)), {\n duration: duration,\n easing: 'ease-in-out',\n });\n var called = false;\n var once = function() {\n if (called) { return; }\n called = true;\n finish();\n };\n\n animation.onfinish = once;\n animation.oncancel = once;\n}\n\n/** Fold a node up to nothing, then hide it. */\nexport function slideUp(node, duration, done) {\n if (typeof duration === 'function') {\n done = duration;\n duration = undefined;\n }\n\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n return [\n {\n height: style.height,\n paddingTop: style.paddingTop,\n paddingBottom: style.paddingBottom,\n marginTop: style.marginTop,\n marginBottom: style.marginBottom,\n },\n { height: '0px', paddingTop: '0px', paddingBottom: '0px', marginTop: '0px', marginBottom: '0px' },\n ];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n\n/** Fade a node out, then hide it. */\nexport function fadeOut(node, duration, done) {\n animateAway(node, function(style) {\n return [{ opacity: style.opacity }, { opacity: 0 }];\n }, duration, done);\n}\n\n/** Fade and fold a node, in height and, with `width`, sideways too, then hide it. */\nexport function shrinkAway(node, duration, done, width) {\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n var from = { opacity: style.opacity, height: style.height };\n var to = { opacity: 0, height: '0px' };\n\n if (width) {\n from.width = style.width;\n to.width = '0px';\n }\n return [from, to];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n", "/**\n * A block's html, edited in place with CodeMirror.\n *\n * A feature plugin: load this file after the editor, and CodeMirror 5 with\n * its html mode after or before it, and every drawer of a row, a column, a\n * text, the host's plain content, an element, a section or a container has a\n * </> tool. It opens the block's html - the block itself and everything in\n * it, as getHtml would give it - in CodeMirror where the block was, and\n * Apply puts what was written in the block's place. What it can ask the\n * editor for is the handle its factory is called with, described in\n * docs/plugins.md.\n *\n * <link rel=\"stylesheet\" href=\"codemirror/lib/codemirror.css\">\n * <script src=\"codemirror/lib/codemirror.js\"></script>\n * <script src=\"codemirror/mode/xml/xml.js\"></script>\n * <script src=\"codemirror/mode/javascript/javascript.js\"></script>\n * <script src=\"codemirror/mode/css/css.js\"></script>\n * <script src=\"codemirror/mode/htmlmixed/htmlmixed.js\"></script>\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.codemirror-inline.min.js\"></script>\n *\n * Without CodeMirror on the page the html is edited in a plain textarea.\n * CodeMirror's options are the codemirror plugin's, codemirror.config.\n */\nimport { GridEditor } from '../grideditor.js';\nimport * as dom from '../dom.js';\n\nObject.assign(GridEditor.locales.en, {\n 'tool.edit_html': 'Edit html',\n 'codemirror.apply': 'Apply',\n 'codemirror.cancel': 'Cancel',\n});\n\n/** What has html of its own to edit: a pane's is split between its button and its body. */\nvar KINDS = ['row', 'column', 'text', 'plain', 'element', 'section'];\n\nGridEditor.features['codemirror-inline'] = function(ge) {\n\n var open = []; // The blocks being edited: { node, kind, from, wrapper, textarea, editor }\n\n function options() {\n var own = (ge.settings.codemirror && ge.settings.codemirror.config) || {};\n\n return Object.assign({\n mode: 'htmlmixed',\n lineNumbers: true,\n lineWrapping: true,\n tabSize: 2,\n indentUnit: 2,\n // As tall as what it holds, up to the css's limit\n viewportMargin: Infinity,\n }, own);\n }\n\n /** What stands for the node in its column: a text's text block, or the node. */\n function anchorOf(node) {\n var textBlock = node.parentElement;\n return dom.hasClass(textBlock, 'ge-text-block') ? textBlock : node;\n }\n\n function entryOf(node) {\n return open.filter(function(entry) { return entry.node === node; })[0] || null;\n }\n\n function editable(node, kind) {\n return KINDS.indexOf(kind) !== -1 || dom.is(node, '[data-ge-container]');\n }\n\n /** The editor where the block was, the block hidden behind it. */\n function show(entry) {\n var anchor = dom.addClass(anchorOf(entry.node), 'ge-code-hidden');\n dom.insertAfter(entry.wrapper, anchor);\n if (entry.editor) { entry.editor.refresh(); }\n }\n\n function hide(entry) {\n entry.wrapper.remove();\n dom.removeClass(anchorOf(entry.node), 'ge-code-hidden');\n dom.removeClass(entry.node, 'ge-code-hidden');\n }\n\n function close(entry) {\n hide(entry);\n if (entry.editor) { entry.editor.toTextArea(); }\n entry.wrapper.remove();\n open.splice(open.indexOf(entry), 1);\n }\n\n function openEditor(node) {\n if (entryOf(node)) { return; }\n\n var entry = {\n node: node,\n kind: ge.kindOf(node),\n // As getHtml gives it: no drawers, no editor open in it\n from: ge.nodeHtml(node),\n // A drawer, to the editor: never content, never a block to move\n wrapper: dom.element('div', { 'class': 'ge-tools-drawer ge-code-inline' }),\n editor: null,\n };\n entry.textarea = entry.wrapper.appendChild(dom.element('textarea', { 'class': 'ge-code-inline-source' }));\n entry.textarea.value = entry.from;\n\n var bar = entry.wrapper.appendChild(dom.element('div', { 'class': 'ge-code-inline-bar' }));\n var applyButton = bar.appendChild(dom.element('button', {\n type: 'button',\n 'class': 'btn btn-sm btn-primary ge-code-apply',\n }, ge.t('codemirror.apply')));\n applyButton.addEventListener('click', function() { apply(entry); });\n var cancelButton = bar.appendChild(dom.element('button', {\n type: 'button',\n 'class': 'btn btn-sm btn-outline-secondary ge-code-cancel',\n }, ge.t('codemirror.cancel')));\n cancelButton.addEventListener('click', function() { close(entry); });\n\n open.push(entry);\n show(entry);\n\n if (window.CodeMirror) {\n entry.editor = window.CodeMirror.fromTextArea(entry.textarea, options());\n dom.addClass(entry.editor.getWrapperElement(), 'ge-code-editor');\n entry.editor.focus();\n } else {\n entry.textarea.focus();\n }\n }\n\n /**\n * What was written, in the block's place, through the edit-html events.\n * The canvas leaves editing to take it in and comes back, as it does for\n * getHtml, so what was written is read as the editor reads any markup.\n */\n function apply(entry) {\n var to = entry.editor ? entry.editor.getValue() : entry.textarea.value;\n var payload = ge.payloadFor(entry.kind, entry.node, { source: 'tool', from: entry.from, to: to });\n\n // Canceled, the editor stays open with what was written in it\n if (!ge.emit('before-edit-html', payload)) { return; }\n\n close(entry);\n\n var instance = GridEditor.get(ge.canvas);\n instance.deinit();\n\n // Parsed as innerHTML parses: a <script> written here is markup,\n // and does not run in the editor\n var made = dom.parse(to);\n var parent = entry.node.parentElement;\n entry.node.replaceWith.apply(entry.node, made);\n\n instance.init();\n\n // The node is the first element written, or none when only text was;\n // `nodes` is every element written, which may be several\n var written = made.filter(function(node) { return node.nodeType === 1; });\n var first = written[0] || null;\n\n ge.emit('after-edit-html', ge.payloadFor(entry.kind, first || entry.node, {\n node: first,\n nodes: written,\n parent: first ? first.parentElement : parent,\n source: 'tool',\n from: entry.from,\n to: to,\n }));\n }\n\n function tool(drawer, node) {\n ge.createTool(drawer, ge.t('tool.edit_html'), 'ge-edit-html', 'bi bi-code-slash', function() {\n openEditor(node);\n });\n }\n\n return {\n drawerTools: function(drawer, node, kind) {\n if (editable(node, kind)) { tool(drawer, node); }\n },\n\n // Plain content has no gear, and so none of the drawerTools: its\n // html is what there is to edit about it\n plainTools: tool,\n\n // Every deinit - getHtml's among them - takes the editors off the\n // canvas, whatever is in them, and every init puts them back where\n // their block is. A block that is gone takes its editor with it.\n onBeforeDeinit: function() {\n open.forEach(hide);\n },\n\n onInit: function() {\n open.slice().forEach(function(entry) {\n if (!dom.attached(entry.node)) {\n if (entry.editor) { entry.editor.toTextArea(); }\n entry.wrapper.remove();\n open.splice(open.indexOf(entry), 1);\n return;\n }\n\n show(entry);\n });\n },\n };\n};\n"],
4
+ "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * The DOM, the way grid-editor uses it.\n *\n * Small helpers over the browser's own API, for the core and the shipped\n * plugins. Not a public API: a plugin of a host's own is free to write its\n * DOM code however it likes, and this file makes no promise to it.\n *\n * Stateless on purpose. The build puts a copy of this file in each plugin's\n * classic script, so anything kept here would be kept once per copy; a\n * module that needs to remember something about a node keeps its own\n * WeakMap.\n */\n\n/** Every element under `root` matching `selector`, as an array. */\nexport function all(root, selector) {\n return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];\n}\n\n/** The first element under `root` matching `selector`, or null. */\nexport function one(root, selector) {\n return root ? root.querySelector(selector) : null;\n}\n\n/** `root` itself when it matches, then every element under it that does. */\nexport function selfAndAll(root, selector) {\n if (!root) { return []; }\n\n var found = all(root, selector);\n if (root.nodeType === 1 && root.matches(selector)) { found.unshift(root); }\n return found;\n}\n\n/** The element children of `node`, those matching `selector` if one is given. */\nexport function children(node, selector) {\n if (!node) { return []; }\n\n return Array.prototype.filter.call(node.children, function(each) {\n return !selector || each.matches(selector);\n });\n}\n\n/** The first element child matching `selector`, or null. */\nexport function child(node, selector) {\n return children(node, selector)[0] || null;\n}\n\n/** The nearest ancestor-or-self matching `selector` below `stopAt`, or null. */\nexport function closest(node, selector, stopAt) {\n var found = node && node.nodeType === 1 ? node.closest(selector) : null;\n\n if (found && stopAt && found !== stopAt && !stopAt.contains(found)) { return null; }\n return found;\n}\n\n/** Whether `node` is an element matching `selector`. */\nexport function is(node, selector) {\n return !!node && node.nodeType === 1 && node.matches(selector);\n}\n\n/** Whether `node` is in the document. */\nexport function attached(node) {\n return !!node && document.documentElement.contains(node);\n}\n\n/** The element siblings after `node` that match `selector`. */\nexport function nextAll(node, selector) {\n var found = [];\n\n for (var next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (!selector || next.matches(selector)) { found.push(next); }\n }\n return found;\n}\n\n/** The ancestors of `node` up to, and not including, `stop`, nearest first. */\nexport function parentsUntil(node, stop) {\n var found = [];\n\n for (var parent = node.parentElement; parent && parent !== stop; parent = parent.parentElement) {\n found.push(parent);\n }\n return found;\n}\n\n/**\n * The nodes the html parses into, detached. Parsed the way innerHTML parses,\n * so a <script> in it never runs, here or once it is in the page.\n */\nexport function parse(html) {\n var template = document.createElement('template');\n template.innerHTML = html;\n return Array.prototype.slice.call(template.content.childNodes);\n}\n\n/** The one element the html is, detached. */\nexport function create(html) {\n var nodes = parse(html.trim());\n\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i].nodeType === 1) { return nodes[i]; }\n }\n return null;\n}\n\n/** An element of `tag`, with `attributes` and `text`. */\nexport function element(tag, attributes, text) {\n var node = document.createElement(tag);\n\n Object.keys(attributes || {}).forEach(function(name) {\n var value = attributes[name];\n if (value !== null && value !== undefined && value !== false) { node.setAttribute(name, value); }\n });\n if (text !== undefined && text !== null) { node.textContent = text; }\n\n return node;\n}\n\n/** Replace what `node` holds with `html`. A <script> in it does not run. */\nexport function setHtml(node, html) {\n node.innerHTML = html === undefined || html === null ? '' : String(html);\n return node;\n}\n\n/** Add one or several space separated classes. */\nexport function addClass(node, names) {\n split(names).forEach(function(name) { node.classList.add(name); });\n return node;\n}\n\nexport function removeClass(node, names) {\n split(names).forEach(function(name) { node.classList.remove(name); });\n return node;\n}\n\n/** Each class on, or off, or flipped when `on` is not given. */\nexport function toggleClass(node, names, state) {\n split(names).forEach(function(name) {\n if (state === undefined) {\n node.classList.toggle(name);\n } else {\n node.classList.toggle(name, !!state);\n }\n });\n return node;\n}\n\nexport function hasClass(node, name) {\n return !!node && node.nodeType === 1 && node.classList.contains(name);\n}\n\nfunction split(names) {\n return String(names || '').split(/\\s+/).filter(Boolean);\n}\n\n/** Take the class attribute off when there is nothing left in it. */\nexport function dropEmptyClass(node) {\n if (!node.getAttribute('class')) { node.removeAttribute('class'); }\n return node;\n}\n\n/** Take the style attribute off when there is nothing left in it. */\nexport function dropEmptyStyle(node) {\n if (!node.getAttribute('style')) { node.removeAttribute('style'); }\n return node;\n}\n\n/** Set attributes; a null or undefined value takes the attribute off. */\nexport function attr(node, attributes) {\n Object.keys(attributes).forEach(function(name) {\n var value = attributes[name];\n\n if (value === null || value === undefined) {\n node.removeAttribute(name);\n } else {\n node.setAttribute(name, value);\n }\n });\n return node;\n}\n\n/**\n * Inline styles, by css property name. A number is pixels for the properties\n * that take a length, as jQuery had it; an empty string takes one off.\n */\nexport function css(node, styles) {\n Object.keys(styles).forEach(function(property) {\n var value = styles[property];\n\n if (typeof value === 'number' && !UNITLESS[property]) { value = value + 'px'; }\n node.style.setProperty(property, value === null || value === undefined ? '' : String(value));\n });\n return node;\n}\n\nvar UNITLESS = { opacity: true, 'z-index': true, 'flex-grow': true, 'flex-shrink': true, order: true };\n\n/** What an element of this tag shows as when nothing hides it. */\nvar defaultDisplays = {};\n\nfunction defaultDisplay(node) {\n var tag = node.nodeName;\n\n if (!defaultDisplays[tag]) {\n var probe = document.body.appendChild(document.createElement(tag));\n defaultDisplays[tag] = getComputedStyle(probe).display;\n probe.remove();\n if (defaultDisplays[tag] === 'none') { defaultDisplays[tag] = 'block'; }\n }\n return defaultDisplays[tag];\n}\n\n/** Show a node: its inline display:none off, and a display of its own if a stylesheet hides it. */\nexport function show(node) {\n node.style.removeProperty('display');\n if (getComputedStyle(node).display === 'none') { node.style.display = defaultDisplay(node); }\n return node;\n}\n\nexport function hide(node) {\n node.style.display = 'none';\n return node;\n}\n\n/** Show or hide; flip when `on` is not given. */\nexport function toggle(node, state) {\n if (state === undefined) { state = !visible(node); }\n return state ? show(node) : hide(node);\n}\n\n/** Whether a node takes up room: what jQuery's :visible meant. */\nexport function visible(node) {\n return !!(node.offsetWidth || node.offsetHeight || node.getClientRects().length);\n}\n\n/** The border box's width, fractions included. */\nexport function outerWidth(node) {\n return node.getBoundingClientRect().width;\n}\n\nexport function outerHeight(node) {\n return node.getBoundingClientRect().height;\n}\n\n/** The content box's height, which is what jQuery's height() gave. */\nexport function contentHeight(node) {\n var style = getComputedStyle(node);\n return node.clientHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);\n}\n\n/** Where a node is on the page, not in the window. */\nexport function offset(node) {\n var box = node.getBoundingClientRect();\n return { top: box.top + window.pageYOffset, left: box.left + window.pageXOffset };\n}\n\n/** Its index among its parent's element children, those matching `selector` if given. */\nexport function indexIn(node, selector) {\n return children(node.parentElement, selector).indexOf(node);\n}\n\n/** Put `node` right after `reference`. */\nexport function insertAfter(node, reference) {\n reference.parentNode.insertBefore(node, reference.nextSibling);\n return node;\n}\n\n/** Replace `node` with what it holds. */\nexport function unwrap(node) {\n var parent = node.parentNode;\n\n while (node.firstChild) { parent.insertBefore(node.firstChild, node); }\n node.remove();\n}\n\n/** Put `node` inside `wrapper`, where `node` was. */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Listen on `root` for `types` (space separated) on descendants that match\n * `selector`, with `this` the matched element, as jQuery's delegated\n * handlers had it. Hands back the listener, for removeEventListener; a\n * signal in `options` removes it too.\n */\nexport function delegate(root, types, selector, handler, options) {\n var listener = function(event) {\n var match = closest(event.target, selector, root);\n if (match && root.contains(match)) { return handler.call(match, event); }\n return undefined;\n };\n\n split(types).forEach(function(type) { root.addEventListener(type, listener, options); });\n return listener;\n}\n\n/** Listen for several space separated event types with one handler. */\nexport function on(target, types, handler, options) {\n split(types).forEach(function(type) { target.addEventListener(type, handler, options); });\n return handler;\n}\n\nexport function off(target, types, handler, options) {\n split(types).forEach(function(type) { target.removeEventListener(type, handler, options); });\n}\n\n/** A mouse event of `type` sent to `node`, the way a pointer would. */\nexport function fire(node, type) {\n node.dispatchEvent(new MouseEvent(type, { bubbles: type !== 'mouseenter' && type !== 'mouseleave' }));\n}\n\n/* ------------------------------------------------------------------\n * Taking a node away, visibly.\n *\n * The durations are jQuery's: 400 ms unless the caller says otherwise. `done` runs once the node is out of sight, which is\n * when the caller removes it; a node that is already out of sight is done at\n * once, on the next task, as jQuery had it.\n * ------------------------------------------------------------------ */\n\nvar DEFAULT_DURATION = 400;\n\nfunction animateAway(node, frames, duration, done) {\n duration = duration === undefined ? DEFAULT_DURATION : duration;\n\n var finish = function() {\n hide(node);\n if (done) { done(); }\n };\n\n if (!visible(node) || !node.animate || duration <= 0) {\n window.setTimeout(finish, 0);\n return;\n }\n\n var animation = node.animate(frames(getComputedStyle(node)), {\n duration: duration,\n easing: 'ease-in-out',\n });\n var called = false;\n var once = function() {\n if (called) { return; }\n called = true;\n finish();\n };\n\n animation.onfinish = once;\n animation.oncancel = once;\n}\n\n/** Fold a node up to nothing, then hide it. */\nexport function slideUp(node, duration, done) {\n if (typeof duration === 'function') {\n done = duration;\n duration = undefined;\n }\n\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n return [\n {\n height: style.height,\n paddingTop: style.paddingTop,\n paddingBottom: style.paddingBottom,\n marginTop: style.marginTop,\n marginBottom: style.marginBottom,\n },\n { height: '0px', paddingTop: '0px', paddingBottom: '0px', marginTop: '0px', marginBottom: '0px' },\n ];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n\n/** Fade a node out, then hide it. */\nexport function fadeOut(node, duration, done) {\n animateAway(node, function(style) {\n return [{ opacity: style.opacity }, { opacity: 0 }];\n }, duration, done);\n}\n\n/** Fade and fold a node, in height and, with `width`, sideways too, then hide it. */\nexport function shrinkAway(node, duration, done, width) {\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n var from = { opacity: style.opacity, height: style.height };\n var to = { opacity: 0, height: '0px' };\n\n if (width) {\n from.width = style.width;\n to.width = '0px';\n }\n return [from, to];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n", "/**\n * A block's html, edited in place with CodeMirror.\n *\n * A feature plugin: load this file after the editor, and CodeMirror 5 with\n * its html mode after or before it, and every drawer of a row, a column, a\n * text, the host's plain content, an element, a section or a container has a\n * </> tool. It opens the block's html - the block itself and everything in\n * it, as getHtml would give it - in CodeMirror where the block was, and\n * Apply puts what was written in the block's place. What it can ask the\n * editor for is the handle its factory is called with, described in\n * docs/plugins.md.\n *\n * <link rel=\"stylesheet\" href=\"codemirror/lib/codemirror.css\">\n * <script src=\"codemirror/lib/codemirror.js\"></script>\n * <script src=\"codemirror/mode/xml/xml.js\"></script>\n * <script src=\"codemirror/mode/javascript/javascript.js\"></script>\n * <script src=\"codemirror/mode/css/css.js\"></script>\n * <script src=\"codemirror/mode/htmlmixed/htmlmixed.js\"></script>\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.codemirror-inline.min.js\"></script>\n *\n * Without CodeMirror on the page the html is edited in a plain textarea.\n * CodeMirror's options are the codemirror plugin's, codemirror.config.\n */\nimport { GridEditor } from '../grideditor.js';\nimport * as dom from '../dom.js';\n\nObject.assign(GridEditor.locales.en, {\n 'tool.edit_html': 'Edit html',\n 'codemirror.apply': 'Apply',\n 'codemirror.cancel': 'Cancel',\n});\n\n/** What has html of its own to edit: a pane's is split between its button and its body. */\nvar KINDS = ['row', 'column', 'text', 'plain', 'element', 'section'];\n\nGridEditor.features['codemirror-inline'] = function(ge) {\n\n var open = []; // The blocks being edited: { node, kind, from, wrapper, textarea, editor }\n\n function options() {\n var own = (ge.settings.codemirror && ge.settings.codemirror.config) || {};\n\n return Object.assign({\n mode: 'htmlmixed',\n lineNumbers: true,\n lineWrapping: true,\n tabSize: 2,\n indentUnit: 2,\n // As tall as what it holds, up to the css's limit\n viewportMargin: Infinity,\n }, own);\n }\n\n /** What stands for the node in its column: a text's text block, or the node. */\n function anchorOf(node) {\n var textBlock = node.parentElement;\n return dom.hasClass(textBlock, 'ge-text-block') ? textBlock : node;\n }\n\n function entryOf(node) {\n return open.filter(function(entry) { return entry.node === node; })[0] || null;\n }\n\n function editable(node, kind) {\n return KINDS.indexOf(kind) !== -1 || dom.is(node, '[data-ge-container]');\n }\n\n /** The editor where the block was, the block hidden behind it. */\n function show(entry) {\n var anchor = dom.addClass(anchorOf(entry.node), 'ge-code-hidden');\n dom.insertAfter(entry.wrapper, anchor);\n if (entry.editor) { entry.editor.refresh(); }\n }\n\n function hide(entry) {\n entry.wrapper.remove();\n dom.removeClass(anchorOf(entry.node), 'ge-code-hidden');\n dom.removeClass(entry.node, 'ge-code-hidden');\n }\n\n function close(entry) {\n hide(entry);\n if (entry.editor) { entry.editor.toTextArea(); }\n entry.wrapper.remove();\n open.splice(open.indexOf(entry), 1);\n }\n\n function openEditor(node) {\n if (entryOf(node)) { return; }\n\n var entry = {\n node: node,\n kind: ge.kindOf(node),\n // As getHtml gives it: no drawers, no editor open in it\n from: ge.nodeHtml(node),\n // A drawer, to the editor: never content, never a block to move\n wrapper: dom.element('div', { 'class': 'ge-tools-drawer ge-code-inline' }),\n editor: null,\n };\n entry.textarea = entry.wrapper.appendChild(dom.element('textarea', { 'class': 'ge-code-inline-source' }));\n entry.textarea.value = entry.from;\n\n var bar = entry.wrapper.appendChild(dom.element('div', { 'class': 'ge-code-inline-bar' }));\n var applyButton = bar.appendChild(dom.element('button', {\n type: 'button',\n 'class': 'btn btn-sm btn-primary ge-code-apply',\n }, ge.t('codemirror.apply')));\n applyButton.addEventListener('click', function() { apply(entry); });\n var cancelButton = bar.appendChild(dom.element('button', {\n type: 'button',\n 'class': 'btn btn-sm btn-outline-secondary ge-code-cancel',\n }, ge.t('codemirror.cancel')));\n cancelButton.addEventListener('click', function() { close(entry); });\n\n open.push(entry);\n show(entry);\n\n if (window.CodeMirror) {\n entry.editor = window.CodeMirror.fromTextArea(entry.textarea, options());\n dom.addClass(entry.editor.getWrapperElement(), 'ge-code-editor');\n entry.editor.focus();\n } else {\n entry.textarea.focus();\n }\n }\n\n /**\n * What was written, in the block's place, through the edit-html events.\n * The canvas leaves editing to take it in and comes back, as it does for\n * getHtml, so what was written is read as the editor reads any markup.\n */\n function apply(entry) {\n var to = entry.editor ? entry.editor.getValue() : entry.textarea.value;\n var payload = ge.payloadFor(entry.kind, entry.node, { source: 'tool', from: entry.from, to: to });\n\n // Canceled, the editor stays open with what was written in it\n if (!ge.emit('before-edit-html', payload)) { return; }\n\n close(entry);\n\n var instance = GridEditor.get(ge.canvas);\n instance.deinit();\n\n // Parsed as innerHTML parses: a <script> written here is markup,\n // and does not run in the editor\n var made = dom.parse(to);\n var parent = entry.node.parentElement;\n entry.node.replaceWith.apply(entry.node, made);\n\n instance.init();\n\n // The node is the first element written, or none when only text was;\n // `nodes` is every element written, which may be several\n var written = made.filter(function(node) { return node.nodeType === 1; });\n var first = written[0] || null;\n\n ge.emit('after-edit-html', ge.payloadFor(entry.kind, first || entry.node, {\n node: first,\n nodes: written,\n parent: first ? first.parentElement : parent,\n source: 'tool',\n from: entry.from,\n to: to,\n }));\n }\n\n function tool(drawer, node) {\n ge.createTool(drawer, ge.t('tool.edit_html'), 'ge-edit-html', 'bi bi-code-slash', function() {\n openEditor(node);\n });\n }\n\n return {\n drawerTools: function(drawer, node, kind) {\n if (editable(node, kind)) { tool(drawer, node); }\n },\n\n // Plain content has no gear, and so none of the drawerTools: its\n // html is what there is to edit about it\n plainTools: tool,\n\n // Every deinit - getHtml's among them - takes the editors off the\n // canvas, whatever is in them, and every init puts them back where\n // their block is. A block that is gone takes its editor with it.\n onBeforeDeinit: function() {\n open.forEach(hide);\n },\n\n onInit: function() {\n open.slice().forEach(function(entry) {\n if (!dom.attached(entry.node)) {\n if (entry.editor) { entry.editor.toTextArea(); }\n entry.wrapper.remove();\n open.splice(open.indexOf(entry), 1);\n return;\n }\n\n show(entry);\n });\n },\n };\n};\n"],
5
5
  "mappings": "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",
6
6
  "names": ["GridEditor", "is", "node", "selector", "attached", "parse", "html", "template", "element", "tag", "attributes", "text", "node", "name", "value", "addClass", "node", "names", "split", "name", "removeClass", "hasClass", "node", "name", "split", "names", "insertAfter", "node", "reference", "GridEditor", "KINDS", "ge", "open", "options", "own", "anchorOf", "node", "textBlock", "hasClass", "entryOf", "entry", "editable", "kind", "is", "show", "anchor", "addClass", "insertAfter", "hide", "removeClass", "close", "openEditor", "element", "bar", "applyButton", "apply", "cancelButton", "to", "payload", "instance", "made", "parse", "parent", "written", "first", "tool", "drawer", "attached"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/js/register.js", "../../src/js/dom.js", "../../src/js/plugins/grideditor.codemirror.js"],
4
- "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * The DOM, the way grid-editor uses it.\n *\n * Small helpers over the browser's own API, for the core and the shipped\n * plugins. Not a public API: a plugin of a host's own is free to write its\n * DOM code however it likes, and this file makes no promise to it.\n *\n * Stateless on purpose. The build puts a copy of this file in each plugin's\n * classic script, so anything kept here would be kept once per copy; a\n * module that needs to remember something about a node keeps its own\n * WeakMap.\n */\n\n/** Every element under `root` matching `selector`, as an array. */\nexport function all(root, selector) {\n return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];\n}\n\n/** The first element under `root` matching `selector`, or null. */\nexport function one(root, selector) {\n return root ? root.querySelector(selector) : null;\n}\n\n/** `root` itself when it matches, then every element under it that does. */\nexport function selfAndAll(root, selector) {\n if (!root) { return []; }\n\n var found = all(root, selector);\n if (root.nodeType === 1 && root.matches(selector)) { found.unshift(root); }\n return found;\n}\n\n/** The element children of `node`, those matching `selector` if one is given. */\nexport function children(node, selector) {\n if (!node) { return []; }\n\n return Array.prototype.filter.call(node.children, function(each) {\n return !selector || each.matches(selector);\n });\n}\n\n/** The first element child matching `selector`, or null. */\nexport function child(node, selector) {\n return children(node, selector)[0] || null;\n}\n\n/** The nearest ancestor-or-self matching `selector` below `stopAt`, or null. */\nexport function closest(node, selector, stopAt) {\n var found = node && node.nodeType === 1 ? node.closest(selector) : null;\n\n if (found && stopAt && found !== stopAt && !stopAt.contains(found)) { return null; }\n return found;\n}\n\n/** Whether `node` is an element matching `selector`. */\nexport function is(node, selector) {\n return !!node && node.nodeType === 1 && node.matches(selector);\n}\n\n/** Whether `node` is in the document. */\nexport function attached(node) {\n return !!node && document.documentElement.contains(node);\n}\n\n/** The element siblings after `node` that match `selector`. */\nexport function nextAll(node, selector) {\n var found = [];\n\n for (var next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (!selector || next.matches(selector)) { found.push(next); }\n }\n return found;\n}\n\n/** The ancestors of `node` up to, and not including, `stop`, nearest first. */\nexport function parentsUntil(node, stop) {\n var found = [];\n\n for (var parent = node.parentElement; parent && parent !== stop; parent = parent.parentElement) {\n found.push(parent);\n }\n return found;\n}\n\n/**\n * The nodes the html parses into, detached. Parsed the way innerHTML parses,\n * so a <script> in it never runs, here or once it is in the page.\n */\nexport function parse(html) {\n var template = document.createElement('template');\n template.innerHTML = html;\n return Array.prototype.slice.call(template.content.childNodes);\n}\n\n/** The one element the html is, detached. */\nexport function create(html) {\n var nodes = parse(html.trim());\n\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i].nodeType === 1) { return nodes[i]; }\n }\n return null;\n}\n\n/** An element of `tag`, with `attributes` and `text`. */\nexport function element(tag, attributes, text) {\n var node = document.createElement(tag);\n\n Object.keys(attributes || {}).forEach(function(name) {\n var value = attributes[name];\n if (value !== null && value !== undefined && value !== false) { node.setAttribute(name, value); }\n });\n if (text !== undefined && text !== null) { node.textContent = text; }\n\n return node;\n}\n\n/** Replace what `node` holds with `html`. A <script> in it does not run. */\nexport function setHtml(node, html) {\n node.innerHTML = html === undefined || html === null ? '' : String(html);\n return node;\n}\n\n/** Add one or several space separated classes. */\nexport function addClass(node, names) {\n split(names).forEach(function(name) { node.classList.add(name); });\n return node;\n}\n\nexport function removeClass(node, names) {\n split(names).forEach(function(name) { node.classList.remove(name); });\n return node;\n}\n\n/** Each class on, or off, or flipped when `on` is not given. */\nexport function toggleClass(node, names, state) {\n split(names).forEach(function(name) {\n if (state === undefined) {\n node.classList.toggle(name);\n } else {\n node.classList.toggle(name, !!state);\n }\n });\n return node;\n}\n\nexport function hasClass(node, name) {\n return !!node && node.nodeType === 1 && node.classList.contains(name);\n}\n\nfunction split(names) {\n return String(names || '').split(/\\s+/).filter(Boolean);\n}\n\n/** Take the class attribute off when there is nothing left in it. */\nexport function dropEmptyClass(node) {\n if (!node.getAttribute('class')) { node.removeAttribute('class'); }\n return node;\n}\n\n/** Take the style attribute off when there is nothing left in it. */\nexport function dropEmptyStyle(node) {\n if (!node.getAttribute('style')) { node.removeAttribute('style'); }\n return node;\n}\n\n/** Set attributes; a null or undefined value takes the attribute off. */\nexport function attr(node, attributes) {\n Object.keys(attributes).forEach(function(name) {\n var value = attributes[name];\n\n if (value === null || value === undefined) {\n node.removeAttribute(name);\n } else {\n node.setAttribute(name, value);\n }\n });\n return node;\n}\n\n/**\n * Inline styles, by css property name. A number is pixels for the properties\n * that take a length, as jQuery had it; an empty string takes one off.\n */\nexport function css(node, styles) {\n Object.keys(styles).forEach(function(property) {\n var value = styles[property];\n\n if (typeof value === 'number' && !UNITLESS[property]) { value = value + 'px'; }\n node.style.setProperty(property, value === null || value === undefined ? '' : String(value));\n });\n return node;\n}\n\nvar UNITLESS = { opacity: true, 'z-index': true, 'flex-grow': true, 'flex-shrink': true, order: true };\n\n/** What an element of this tag shows as when nothing hides it. */\nvar defaultDisplays = {};\n\nfunction defaultDisplay(node) {\n var tag = node.nodeName;\n\n if (!defaultDisplays[tag]) {\n var probe = document.body.appendChild(document.createElement(tag));\n defaultDisplays[tag] = getComputedStyle(probe).display;\n probe.remove();\n if (defaultDisplays[tag] === 'none') { defaultDisplays[tag] = 'block'; }\n }\n return defaultDisplays[tag];\n}\n\n/** Show a node: its inline display:none off, and a display of its own if a stylesheet hides it. */\nexport function show(node) {\n node.style.removeProperty('display');\n if (getComputedStyle(node).display === 'none') { node.style.display = defaultDisplay(node); }\n return node;\n}\n\nexport function hide(node) {\n node.style.display = 'none';\n return node;\n}\n\n/** Show or hide; flip when `on` is not given. */\nexport function toggle(node, state) {\n if (state === undefined) { state = !visible(node); }\n return state ? show(node) : hide(node);\n}\n\n/** Whether a node takes up room: what jQuery's :visible meant. */\nexport function visible(node) {\n return !!(node.offsetWidth || node.offsetHeight || node.getClientRects().length);\n}\n\n/** The border box's width, fractions included. */\nexport function outerWidth(node) {\n return node.getBoundingClientRect().width;\n}\n\nexport function outerHeight(node) {\n return node.getBoundingClientRect().height;\n}\n\n/** The content box's height, which is what jQuery's height() gave. */\nexport function contentHeight(node) {\n var style = getComputedStyle(node);\n return node.clientHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);\n}\n\n/** Where a node is on the page, not in the window. */\nexport function offset(node) {\n var box = node.getBoundingClientRect();\n return { top: box.top + window.pageYOffset, left: box.left + window.pageXOffset };\n}\n\n/** Its index among its parent's element children, those matching `selector` if given. */\nexport function indexIn(node, selector) {\n return children(node.parentElement, selector).indexOf(node);\n}\n\n/** Put `node` right after `reference`. */\nexport function insertAfter(node, reference) {\n reference.parentNode.insertBefore(node, reference.nextSibling);\n return node;\n}\n\n/** Replace `node` with what it holds. */\nexport function unwrap(node) {\n var parent = node.parentNode;\n\n while (node.firstChild) { parent.insertBefore(node.firstChild, node); }\n node.remove();\n}\n\n/** Put `node` inside `wrapper`, where `node` was. */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Listen on `root` for `types` (space separated) on descendants that match\n * `selector`, with `this` the matched element, as jQuery's delegated\n * handlers had it. Hands back the listener, for removeEventListener; a\n * signal in `options` removes it too.\n */\nexport function delegate(root, types, selector, handler, options) {\n var listener = function(event) {\n var match = closest(event.target, selector, root);\n if (match && root.contains(match)) { return handler.call(match, event); }\n return undefined;\n };\n\n split(types).forEach(function(type) { root.addEventListener(type, listener, options); });\n return listener;\n}\n\n/** Listen for several space separated event types with one handler. */\nexport function on(target, types, handler, options) {\n split(types).forEach(function(type) { target.addEventListener(type, handler, options); });\n return handler;\n}\n\nexport function off(target, types, handler, options) {\n split(types).forEach(function(type) { target.removeEventListener(type, handler, options); });\n}\n\n/** A mouse event of `type` sent to `node`, the way a pointer would. */\nexport function fire(node, type) {\n node.dispatchEvent(new MouseEvent(type, { bubbles: type !== 'mouseenter' && type !== 'mouseleave' }));\n}\n\n/* ------------------------------------------------------------------\n * Taking a node away, visibly.\n *\n * The durations are the ones 6.x had through jQuery: 400 ms unless the\n * caller says otherwise. `done` runs once the node is out of sight, which is\n * when the caller removes it; a node that is already out of sight is done at\n * once, on the next task, as jQuery had it.\n * ------------------------------------------------------------------ */\n\nvar DEFAULT_DURATION = 400;\n\nfunction animateAway(node, frames, duration, done) {\n duration = duration === undefined ? DEFAULT_DURATION : duration;\n\n var finish = function() {\n hide(node);\n if (done) { done(); }\n };\n\n if (!visible(node) || !node.animate || duration <= 0) {\n window.setTimeout(finish, 0);\n return;\n }\n\n var animation = node.animate(frames(getComputedStyle(node)), {\n duration: duration,\n easing: 'ease-in-out',\n });\n var called = false;\n var once = function() {\n if (called) { return; }\n called = true;\n finish();\n };\n\n animation.onfinish = once;\n animation.oncancel = once;\n}\n\n/** Fold a node up to nothing, then hide it. */\nexport function slideUp(node, duration, done) {\n if (typeof duration === 'function') {\n done = duration;\n duration = undefined;\n }\n\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n return [\n {\n height: style.height,\n paddingTop: style.paddingTop,\n paddingBottom: style.paddingBottom,\n marginTop: style.marginTop,\n marginBottom: style.marginBottom,\n },\n { height: '0px', paddingTop: '0px', paddingBottom: '0px', marginTop: '0px', marginBottom: '0px' },\n ];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n\n/** Fade a node out, then hide it. */\nexport function fadeOut(node, duration, done) {\n animateAway(node, function(style) {\n return [{ opacity: style.opacity }, { opacity: 0 }];\n }, duration, done);\n}\n\n/** Fade and fold a node, in height and, with `width`, sideways too, then hide it. */\nexport function shrinkAway(node, duration, done, width) {\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n var from = { opacity: style.opacity, height: style.height };\n var to = { opacity: 0, height: '0px' };\n\n if (width) {\n from.width = style.width;\n to.width = '0px';\n }\n return [from, to];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n", "/**\n * CodeMirror for grid-editor's source view.\n *\n * A feature plugin: load this file after the editor, and CodeMirror 5 with\n * its html mode after or before it, and the toolbar's source button edits the\n * canvas's html in CodeMirror - highlighted, with line numbers - rather than\n * in a plain textarea. What it can ask the editor for is the handle its\n * factory is called with, described in docs/plugins.md.\n *\n * <link rel=\"stylesheet\" href=\"codemirror/lib/codemirror.css\">\n * <script src=\"codemirror/lib/codemirror.js\"></script>\n * <script src=\"codemirror/mode/xml/xml.js\"></script>\n * <script src=\"codemirror/mode/javascript/javascript.js\"></script>\n * <script src=\"codemirror/mode/css/css.js\"></script>\n * <script src=\"codemirror/mode/htmlmixed/htmlmixed.js\"></script>\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.codemirror.min.js\"></script>\n *\n * CodeMirror 5 rather than 6: 6 comes as ES modules only, for a bundler,\n * where 5 loads from a script tag like the rest of the page. Without\n * CodeMirror on the page the source view is the textarea, as before, and\n * the console says why.\n */\nimport { GridEditor } from '../grideditor.js';\nimport * as dom from '../dom.js';\n\nObject.assign(GridEditor.locales.en, {\n 'error.codemirror_missing': 'CodeMirror not available! Make sure you loaded the CodeMirror js file; the source is edited in a plain textarea without it.',\n});\n\nGridEditor.features.codemirror = function(ge) {\n\n var editor = null;\n var warned = false;\n\n function options() {\n var own = (ge.settings.codemirror && ge.settings.codemirror.config) || {};\n\n return Object.assign({\n mode: 'htmlmixed',\n lineNumbers: true,\n lineWrapping: true,\n tabSize: 2,\n indentUnit: 2,\n }, own);\n }\n\n return {\n // Over the textarea the editor fills with the canvas's html: it goes\n // where the textarea was, as tall as the editor made the textarea\n onSourceOpen: function(textarea) {\n if (!window.CodeMirror) {\n if (!warned) {\n warned = true;\n ge.warn(ge.t('error.codemirror_missing'));\n }\n return;\n }\n\n var height = dom.outerHeight(textarea);\n\n editor = window.CodeMirror.fromTextArea(textarea, options());\n dom.addClass(editor.getWrapperElement(), 'ge-code-editor');\n editor.setSize(null, height);\n editor.focus();\n },\n\n // What it holds goes back in the textarea, which is what the canvas\n // is made of again, and the textarea is left as it found it\n onSourceClose: function() {\n if (!editor) { return; }\n\n editor.save();\n editor.toTextArea();\n editor = null;\n },\n };\n};\n"],
4
+ "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * The DOM, the way grid-editor uses it.\n *\n * Small helpers over the browser's own API, for the core and the shipped\n * plugins. Not a public API: a plugin of a host's own is free to write its\n * DOM code however it likes, and this file makes no promise to it.\n *\n * Stateless on purpose. The build puts a copy of this file in each plugin's\n * classic script, so anything kept here would be kept once per copy; a\n * module that needs to remember something about a node keeps its own\n * WeakMap.\n */\n\n/** Every element under `root` matching `selector`, as an array. */\nexport function all(root, selector) {\n return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];\n}\n\n/** The first element under `root` matching `selector`, or null. */\nexport function one(root, selector) {\n return root ? root.querySelector(selector) : null;\n}\n\n/** `root` itself when it matches, then every element under it that does. */\nexport function selfAndAll(root, selector) {\n if (!root) { return []; }\n\n var found = all(root, selector);\n if (root.nodeType === 1 && root.matches(selector)) { found.unshift(root); }\n return found;\n}\n\n/** The element children of `node`, those matching `selector` if one is given. */\nexport function children(node, selector) {\n if (!node) { return []; }\n\n return Array.prototype.filter.call(node.children, function(each) {\n return !selector || each.matches(selector);\n });\n}\n\n/** The first element child matching `selector`, or null. */\nexport function child(node, selector) {\n return children(node, selector)[0] || null;\n}\n\n/** The nearest ancestor-or-self matching `selector` below `stopAt`, or null. */\nexport function closest(node, selector, stopAt) {\n var found = node && node.nodeType === 1 ? node.closest(selector) : null;\n\n if (found && stopAt && found !== stopAt && !stopAt.contains(found)) { return null; }\n return found;\n}\n\n/** Whether `node` is an element matching `selector`. */\nexport function is(node, selector) {\n return !!node && node.nodeType === 1 && node.matches(selector);\n}\n\n/** Whether `node` is in the document. */\nexport function attached(node) {\n return !!node && document.documentElement.contains(node);\n}\n\n/** The element siblings after `node` that match `selector`. */\nexport function nextAll(node, selector) {\n var found = [];\n\n for (var next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (!selector || next.matches(selector)) { found.push(next); }\n }\n return found;\n}\n\n/** The ancestors of `node` up to, and not including, `stop`, nearest first. */\nexport function parentsUntil(node, stop) {\n var found = [];\n\n for (var parent = node.parentElement; parent && parent !== stop; parent = parent.parentElement) {\n found.push(parent);\n }\n return found;\n}\n\n/**\n * The nodes the html parses into, detached. Parsed the way innerHTML parses,\n * so a <script> in it never runs, here or once it is in the page.\n */\nexport function parse(html) {\n var template = document.createElement('template');\n template.innerHTML = html;\n return Array.prototype.slice.call(template.content.childNodes);\n}\n\n/** The one element the html is, detached. */\nexport function create(html) {\n var nodes = parse(html.trim());\n\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i].nodeType === 1) { return nodes[i]; }\n }\n return null;\n}\n\n/** An element of `tag`, with `attributes` and `text`. */\nexport function element(tag, attributes, text) {\n var node = document.createElement(tag);\n\n Object.keys(attributes || {}).forEach(function(name) {\n var value = attributes[name];\n if (value !== null && value !== undefined && value !== false) { node.setAttribute(name, value); }\n });\n if (text !== undefined && text !== null) { node.textContent = text; }\n\n return node;\n}\n\n/** Replace what `node` holds with `html`. A <script> in it does not run. */\nexport function setHtml(node, html) {\n node.innerHTML = html === undefined || html === null ? '' : String(html);\n return node;\n}\n\n/** Add one or several space separated classes. */\nexport function addClass(node, names) {\n split(names).forEach(function(name) { node.classList.add(name); });\n return node;\n}\n\nexport function removeClass(node, names) {\n split(names).forEach(function(name) { node.classList.remove(name); });\n return node;\n}\n\n/** Each class on, or off, or flipped when `on` is not given. */\nexport function toggleClass(node, names, state) {\n split(names).forEach(function(name) {\n if (state === undefined) {\n node.classList.toggle(name);\n } else {\n node.classList.toggle(name, !!state);\n }\n });\n return node;\n}\n\nexport function hasClass(node, name) {\n return !!node && node.nodeType === 1 && node.classList.contains(name);\n}\n\nfunction split(names) {\n return String(names || '').split(/\\s+/).filter(Boolean);\n}\n\n/** Take the class attribute off when there is nothing left in it. */\nexport function dropEmptyClass(node) {\n if (!node.getAttribute('class')) { node.removeAttribute('class'); }\n return node;\n}\n\n/** Take the style attribute off when there is nothing left in it. */\nexport function dropEmptyStyle(node) {\n if (!node.getAttribute('style')) { node.removeAttribute('style'); }\n return node;\n}\n\n/** Set attributes; a null or undefined value takes the attribute off. */\nexport function attr(node, attributes) {\n Object.keys(attributes).forEach(function(name) {\n var value = attributes[name];\n\n if (value === null || value === undefined) {\n node.removeAttribute(name);\n } else {\n node.setAttribute(name, value);\n }\n });\n return node;\n}\n\n/**\n * Inline styles, by css property name. A number is pixels for the properties\n * that take a length, as jQuery had it; an empty string takes one off.\n */\nexport function css(node, styles) {\n Object.keys(styles).forEach(function(property) {\n var value = styles[property];\n\n if (typeof value === 'number' && !UNITLESS[property]) { value = value + 'px'; }\n node.style.setProperty(property, value === null || value === undefined ? '' : String(value));\n });\n return node;\n}\n\nvar UNITLESS = { opacity: true, 'z-index': true, 'flex-grow': true, 'flex-shrink': true, order: true };\n\n/** What an element of this tag shows as when nothing hides it. */\nvar defaultDisplays = {};\n\nfunction defaultDisplay(node) {\n var tag = node.nodeName;\n\n if (!defaultDisplays[tag]) {\n var probe = document.body.appendChild(document.createElement(tag));\n defaultDisplays[tag] = getComputedStyle(probe).display;\n probe.remove();\n if (defaultDisplays[tag] === 'none') { defaultDisplays[tag] = 'block'; }\n }\n return defaultDisplays[tag];\n}\n\n/** Show a node: its inline display:none off, and a display of its own if a stylesheet hides it. */\nexport function show(node) {\n node.style.removeProperty('display');\n if (getComputedStyle(node).display === 'none') { node.style.display = defaultDisplay(node); }\n return node;\n}\n\nexport function hide(node) {\n node.style.display = 'none';\n return node;\n}\n\n/** Show or hide; flip when `on` is not given. */\nexport function toggle(node, state) {\n if (state === undefined) { state = !visible(node); }\n return state ? show(node) : hide(node);\n}\n\n/** Whether a node takes up room: what jQuery's :visible meant. */\nexport function visible(node) {\n return !!(node.offsetWidth || node.offsetHeight || node.getClientRects().length);\n}\n\n/** The border box's width, fractions included. */\nexport function outerWidth(node) {\n return node.getBoundingClientRect().width;\n}\n\nexport function outerHeight(node) {\n return node.getBoundingClientRect().height;\n}\n\n/** The content box's height, which is what jQuery's height() gave. */\nexport function contentHeight(node) {\n var style = getComputedStyle(node);\n return node.clientHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);\n}\n\n/** Where a node is on the page, not in the window. */\nexport function offset(node) {\n var box = node.getBoundingClientRect();\n return { top: box.top + window.pageYOffset, left: box.left + window.pageXOffset };\n}\n\n/** Its index among its parent's element children, those matching `selector` if given. */\nexport function indexIn(node, selector) {\n return children(node.parentElement, selector).indexOf(node);\n}\n\n/** Put `node` right after `reference`. */\nexport function insertAfter(node, reference) {\n reference.parentNode.insertBefore(node, reference.nextSibling);\n return node;\n}\n\n/** Replace `node` with what it holds. */\nexport function unwrap(node) {\n var parent = node.parentNode;\n\n while (node.firstChild) { parent.insertBefore(node.firstChild, node); }\n node.remove();\n}\n\n/** Put `node` inside `wrapper`, where `node` was. */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Listen on `root` for `types` (space separated) on descendants that match\n * `selector`, with `this` the matched element, as jQuery's delegated\n * handlers had it. Hands back the listener, for removeEventListener; a\n * signal in `options` removes it too.\n */\nexport function delegate(root, types, selector, handler, options) {\n var listener = function(event) {\n var match = closest(event.target, selector, root);\n if (match && root.contains(match)) { return handler.call(match, event); }\n return undefined;\n };\n\n split(types).forEach(function(type) { root.addEventListener(type, listener, options); });\n return listener;\n}\n\n/** Listen for several space separated event types with one handler. */\nexport function on(target, types, handler, options) {\n split(types).forEach(function(type) { target.addEventListener(type, handler, options); });\n return handler;\n}\n\nexport function off(target, types, handler, options) {\n split(types).forEach(function(type) { target.removeEventListener(type, handler, options); });\n}\n\n/** A mouse event of `type` sent to `node`, the way a pointer would. */\nexport function fire(node, type) {\n node.dispatchEvent(new MouseEvent(type, { bubbles: type !== 'mouseenter' && type !== 'mouseleave' }));\n}\n\n/* ------------------------------------------------------------------\n * Taking a node away, visibly.\n *\n * The durations are jQuery's: 400 ms unless the caller says otherwise. `done` runs once the node is out of sight, which is\n * when the caller removes it; a node that is already out of sight is done at\n * once, on the next task, as jQuery had it.\n * ------------------------------------------------------------------ */\n\nvar DEFAULT_DURATION = 400;\n\nfunction animateAway(node, frames, duration, done) {\n duration = duration === undefined ? DEFAULT_DURATION : duration;\n\n var finish = function() {\n hide(node);\n if (done) { done(); }\n };\n\n if (!visible(node) || !node.animate || duration <= 0) {\n window.setTimeout(finish, 0);\n return;\n }\n\n var animation = node.animate(frames(getComputedStyle(node)), {\n duration: duration,\n easing: 'ease-in-out',\n });\n var called = false;\n var once = function() {\n if (called) { return; }\n called = true;\n finish();\n };\n\n animation.onfinish = once;\n animation.oncancel = once;\n}\n\n/** Fold a node up to nothing, then hide it. */\nexport function slideUp(node, duration, done) {\n if (typeof duration === 'function') {\n done = duration;\n duration = undefined;\n }\n\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n return [\n {\n height: style.height,\n paddingTop: style.paddingTop,\n paddingBottom: style.paddingBottom,\n marginTop: style.marginTop,\n marginBottom: style.marginBottom,\n },\n { height: '0px', paddingTop: '0px', paddingBottom: '0px', marginTop: '0px', marginBottom: '0px' },\n ];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n\n/** Fade a node out, then hide it. */\nexport function fadeOut(node, duration, done) {\n animateAway(node, function(style) {\n return [{ opacity: style.opacity }, { opacity: 0 }];\n }, duration, done);\n}\n\n/** Fade and fold a node, in height and, with `width`, sideways too, then hide it. */\nexport function shrinkAway(node, duration, done, width) {\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n var from = { opacity: style.opacity, height: style.height };\n var to = { opacity: 0, height: '0px' };\n\n if (width) {\n from.width = style.width;\n to.width = '0px';\n }\n return [from, to];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n", "/**\n * CodeMirror for grid-editor's source view.\n *\n * A feature plugin: load this file after the editor, and CodeMirror 5 with\n * its html mode after or before it, and the toolbar's source button edits the\n * canvas's html in CodeMirror - highlighted, with line numbers - rather than\n * in a plain textarea. What it can ask the editor for is the handle its\n * factory is called with, described in docs/plugins.md.\n *\n * <link rel=\"stylesheet\" href=\"codemirror/lib/codemirror.css\">\n * <script src=\"codemirror/lib/codemirror.js\"></script>\n * <script src=\"codemirror/mode/xml/xml.js\"></script>\n * <script src=\"codemirror/mode/javascript/javascript.js\"></script>\n * <script src=\"codemirror/mode/css/css.js\"></script>\n * <script src=\"codemirror/mode/htmlmixed/htmlmixed.js\"></script>\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.codemirror.min.js\"></script>\n *\n * CodeMirror 5 rather than 6: 6 comes as ES modules only, for a bundler,\n * where 5 loads from a script tag like the rest of the page. Without\n * CodeMirror on the page the source view is the textarea, as before, and\n * the console says why.\n */\nimport { GridEditor } from '../grideditor.js';\nimport * as dom from '../dom.js';\n\nObject.assign(GridEditor.locales.en, {\n 'error.codemirror_missing': 'CodeMirror not available! Make sure you loaded the CodeMirror js file; the source is edited in a plain textarea without it.',\n});\n\nGridEditor.features.codemirror = function(ge) {\n\n var editor = null;\n var warned = false;\n\n function options() {\n var own = (ge.settings.codemirror && ge.settings.codemirror.config) || {};\n\n return Object.assign({\n mode: 'htmlmixed',\n lineNumbers: true,\n lineWrapping: true,\n tabSize: 2,\n indentUnit: 2,\n }, own);\n }\n\n return {\n // Over the textarea the editor fills with the canvas's html: it goes\n // where the textarea was, as tall as the editor made the textarea\n onSourceOpen: function(textarea) {\n if (!window.CodeMirror) {\n if (!warned) {\n warned = true;\n ge.warn(ge.t('error.codemirror_missing'));\n }\n return;\n }\n\n var height = dom.outerHeight(textarea);\n\n editor = window.CodeMirror.fromTextArea(textarea, options());\n dom.addClass(editor.getWrapperElement(), 'ge-code-editor');\n editor.setSize(null, height);\n editor.focus();\n },\n\n // What it holds goes back in the textarea, which is what the canvas\n // is made of again, and the textarea is left as it found it\n onSourceClose: function() {\n if (!editor) { return; }\n\n editor.save();\n editor.toTextArea();\n editor = null;\n },\n };\n};\n"],
5
5
  "mappings": "MASA,IAAIA,EAAa,OAAO,WAExB,GAAI,CAACA,GAAc,OAAOA,EAAW,KAAQ,WACzC,MAAM,IAAI,MAAM,wHAC0B,EC+GvC,SAASC,EAASC,EAAMC,EAAO,CAClC,OAAAC,EAAMD,CAAK,EAAE,QAAQ,SAASE,EAAM,CAAEH,EAAK,UAAU,IAAIG,CAAI,CAAG,CAAC,EAC1DH,CACX,CAuBA,SAASI,EAAMC,EAAO,CAClB,OAAO,OAAOA,GAAS,EAAE,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO,CAC1D,CAuFO,SAASC,EAAYC,EAAM,CAC9B,OAAOA,EAAK,sBAAsB,EAAE,MACxC,CCvNA,OAAO,OAAOC,EAAW,QAAQ,GAAI,CACjC,2BAA4B,6HAChC,CAAC,EAEDA,EAAW,SAAS,WAAa,SAASC,EAAI,CAE1C,IAAIC,EAAS,KACTC,EAAS,GAEb,SAASC,GAAU,CACf,IAAIC,EAAOJ,EAAG,SAAS,YAAcA,EAAG,SAAS,WAAW,QAAW,CAAC,EAExE,OAAO,OAAO,OAAO,CACjB,KAAM,YACN,YAAa,GACb,aAAc,GACd,QAAS,EACT,WAAY,CAChB,EAAGI,CAAG,CACV,CAEA,MAAO,CAGH,aAAc,SAASC,EAAU,CAC7B,GAAI,CAAC,OAAO,WAAY,CACfH,IACDA,EAAS,GACTF,EAAG,KAAKA,EAAG,EAAE,0BAA0B,CAAC,GAE5C,MACJ,CAEA,IAAIM,EAAaC,EAAYF,CAAQ,EAErCJ,EAAS,OAAO,WAAW,aAAaI,EAAUF,EAAQ,CAAC,EACvDK,EAASP,EAAO,kBAAkB,EAAG,gBAAgB,EACzDA,EAAO,QAAQ,KAAMK,CAAM,EAC3BL,EAAO,MAAM,CACjB,EAIA,cAAe,UAAW,CACjBA,IAELA,EAAO,KAAK,EACZA,EAAO,WAAW,EAClBA,EAAS,KACb,CACJ,CACJ",
6
6
  "names": ["GridEditor", "addClass", "node", "names", "split", "name", "split", "names", "outerHeight", "node", "GridEditor", "ge", "editor", "warned", "options", "own", "textarea", "height", "outerHeight", "addClass"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/js/register.js", "../../src/js/dom.js", "../../src/js/plugins/grideditor.elements.js"],
4
- "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * The DOM, the way grid-editor uses it.\n *\n * Small helpers over the browser's own API, for the core and the shipped\n * plugins. Not a public API: a plugin of a host's own is free to write its\n * DOM code however it likes, and this file makes no promise to it.\n *\n * Stateless on purpose. The build puts a copy of this file in each plugin's\n * classic script, so anything kept here would be kept once per copy; a\n * module that needs to remember something about a node keeps its own\n * WeakMap.\n */\n\n/** Every element under `root` matching `selector`, as an array. */\nexport function all(root, selector) {\n return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];\n}\n\n/** The first element under `root` matching `selector`, or null. */\nexport function one(root, selector) {\n return root ? root.querySelector(selector) : null;\n}\n\n/** `root` itself when it matches, then every element under it that does. */\nexport function selfAndAll(root, selector) {\n if (!root) { return []; }\n\n var found = all(root, selector);\n if (root.nodeType === 1 && root.matches(selector)) { found.unshift(root); }\n return found;\n}\n\n/** The element children of `node`, those matching `selector` if one is given. */\nexport function children(node, selector) {\n if (!node) { return []; }\n\n return Array.prototype.filter.call(node.children, function(each) {\n return !selector || each.matches(selector);\n });\n}\n\n/** The first element child matching `selector`, or null. */\nexport function child(node, selector) {\n return children(node, selector)[0] || null;\n}\n\n/** The nearest ancestor-or-self matching `selector` below `stopAt`, or null. */\nexport function closest(node, selector, stopAt) {\n var found = node && node.nodeType === 1 ? node.closest(selector) : null;\n\n if (found && stopAt && found !== stopAt && !stopAt.contains(found)) { return null; }\n return found;\n}\n\n/** Whether `node` is an element matching `selector`. */\nexport function is(node, selector) {\n return !!node && node.nodeType === 1 && node.matches(selector);\n}\n\n/** Whether `node` is in the document. */\nexport function attached(node) {\n return !!node && document.documentElement.contains(node);\n}\n\n/** The element siblings after `node` that match `selector`. */\nexport function nextAll(node, selector) {\n var found = [];\n\n for (var next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (!selector || next.matches(selector)) { found.push(next); }\n }\n return found;\n}\n\n/** The ancestors of `node` up to, and not including, `stop`, nearest first. */\nexport function parentsUntil(node, stop) {\n var found = [];\n\n for (var parent = node.parentElement; parent && parent !== stop; parent = parent.parentElement) {\n found.push(parent);\n }\n return found;\n}\n\n/**\n * The nodes the html parses into, detached. Parsed the way innerHTML parses,\n * so a <script> in it never runs, here or once it is in the page.\n */\nexport function parse(html) {\n var template = document.createElement('template');\n template.innerHTML = html;\n return Array.prototype.slice.call(template.content.childNodes);\n}\n\n/** The one element the html is, detached. */\nexport function create(html) {\n var nodes = parse(html.trim());\n\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i].nodeType === 1) { return nodes[i]; }\n }\n return null;\n}\n\n/** An element of `tag`, with `attributes` and `text`. */\nexport function element(tag, attributes, text) {\n var node = document.createElement(tag);\n\n Object.keys(attributes || {}).forEach(function(name) {\n var value = attributes[name];\n if (value !== null && value !== undefined && value !== false) { node.setAttribute(name, value); }\n });\n if (text !== undefined && text !== null) { node.textContent = text; }\n\n return node;\n}\n\n/** Replace what `node` holds with `html`. A <script> in it does not run. */\nexport function setHtml(node, html) {\n node.innerHTML = html === undefined || html === null ? '' : String(html);\n return node;\n}\n\n/** Add one or several space separated classes. */\nexport function addClass(node, names) {\n split(names).forEach(function(name) { node.classList.add(name); });\n return node;\n}\n\nexport function removeClass(node, names) {\n split(names).forEach(function(name) { node.classList.remove(name); });\n return node;\n}\n\n/** Each class on, or off, or flipped when `on` is not given. */\nexport function toggleClass(node, names, state) {\n split(names).forEach(function(name) {\n if (state === undefined) {\n node.classList.toggle(name);\n } else {\n node.classList.toggle(name, !!state);\n }\n });\n return node;\n}\n\nexport function hasClass(node, name) {\n return !!node && node.nodeType === 1 && node.classList.contains(name);\n}\n\nfunction split(names) {\n return String(names || '').split(/\\s+/).filter(Boolean);\n}\n\n/** Take the class attribute off when there is nothing left in it. */\nexport function dropEmptyClass(node) {\n if (!node.getAttribute('class')) { node.removeAttribute('class'); }\n return node;\n}\n\n/** Take the style attribute off when there is nothing left in it. */\nexport function dropEmptyStyle(node) {\n if (!node.getAttribute('style')) { node.removeAttribute('style'); }\n return node;\n}\n\n/** Set attributes; a null or undefined value takes the attribute off. */\nexport function attr(node, attributes) {\n Object.keys(attributes).forEach(function(name) {\n var value = attributes[name];\n\n if (value === null || value === undefined) {\n node.removeAttribute(name);\n } else {\n node.setAttribute(name, value);\n }\n });\n return node;\n}\n\n/**\n * Inline styles, by css property name. A number is pixels for the properties\n * that take a length, as jQuery had it; an empty string takes one off.\n */\nexport function css(node, styles) {\n Object.keys(styles).forEach(function(property) {\n var value = styles[property];\n\n if (typeof value === 'number' && !UNITLESS[property]) { value = value + 'px'; }\n node.style.setProperty(property, value === null || value === undefined ? '' : String(value));\n });\n return node;\n}\n\nvar UNITLESS = { opacity: true, 'z-index': true, 'flex-grow': true, 'flex-shrink': true, order: true };\n\n/** What an element of this tag shows as when nothing hides it. */\nvar defaultDisplays = {};\n\nfunction defaultDisplay(node) {\n var tag = node.nodeName;\n\n if (!defaultDisplays[tag]) {\n var probe = document.body.appendChild(document.createElement(tag));\n defaultDisplays[tag] = getComputedStyle(probe).display;\n probe.remove();\n if (defaultDisplays[tag] === 'none') { defaultDisplays[tag] = 'block'; }\n }\n return defaultDisplays[tag];\n}\n\n/** Show a node: its inline display:none off, and a display of its own if a stylesheet hides it. */\nexport function show(node) {\n node.style.removeProperty('display');\n if (getComputedStyle(node).display === 'none') { node.style.display = defaultDisplay(node); }\n return node;\n}\n\nexport function hide(node) {\n node.style.display = 'none';\n return node;\n}\n\n/** Show or hide; flip when `on` is not given. */\nexport function toggle(node, state) {\n if (state === undefined) { state = !visible(node); }\n return state ? show(node) : hide(node);\n}\n\n/** Whether a node takes up room: what jQuery's :visible meant. */\nexport function visible(node) {\n return !!(node.offsetWidth || node.offsetHeight || node.getClientRects().length);\n}\n\n/** The border box's width, fractions included. */\nexport function outerWidth(node) {\n return node.getBoundingClientRect().width;\n}\n\nexport function outerHeight(node) {\n return node.getBoundingClientRect().height;\n}\n\n/** The content box's height, which is what jQuery's height() gave. */\nexport function contentHeight(node) {\n var style = getComputedStyle(node);\n return node.clientHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);\n}\n\n/** Where a node is on the page, not in the window. */\nexport function offset(node) {\n var box = node.getBoundingClientRect();\n return { top: box.top + window.pageYOffset, left: box.left + window.pageXOffset };\n}\n\n/** Its index among its parent's element children, those matching `selector` if given. */\nexport function indexIn(node, selector) {\n return children(node.parentElement, selector).indexOf(node);\n}\n\n/** Put `node` right after `reference`. */\nexport function insertAfter(node, reference) {\n reference.parentNode.insertBefore(node, reference.nextSibling);\n return node;\n}\n\n/** Replace `node` with what it holds. */\nexport function unwrap(node) {\n var parent = node.parentNode;\n\n while (node.firstChild) { parent.insertBefore(node.firstChild, node); }\n node.remove();\n}\n\n/** Put `node` inside `wrapper`, where `node` was. */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Listen on `root` for `types` (space separated) on descendants that match\n * `selector`, with `this` the matched element, as jQuery's delegated\n * handlers had it. Hands back the listener, for removeEventListener; a\n * signal in `options` removes it too.\n */\nexport function delegate(root, types, selector, handler, options) {\n var listener = function(event) {\n var match = closest(event.target, selector, root);\n if (match && root.contains(match)) { return handler.call(match, event); }\n return undefined;\n };\n\n split(types).forEach(function(type) { root.addEventListener(type, listener, options); });\n return listener;\n}\n\n/** Listen for several space separated event types with one handler. */\nexport function on(target, types, handler, options) {\n split(types).forEach(function(type) { target.addEventListener(type, handler, options); });\n return handler;\n}\n\nexport function off(target, types, handler, options) {\n split(types).forEach(function(type) { target.removeEventListener(type, handler, options); });\n}\n\n/** A mouse event of `type` sent to `node`, the way a pointer would. */\nexport function fire(node, type) {\n node.dispatchEvent(new MouseEvent(type, { bubbles: type !== 'mouseenter' && type !== 'mouseleave' }));\n}\n\n/* ------------------------------------------------------------------\n * Taking a node away, visibly.\n *\n * The durations are the ones 6.x had through jQuery: 400 ms unless the\n * caller says otherwise. `done` runs once the node is out of sight, which is\n * when the caller removes it; a node that is already out of sight is done at\n * once, on the next task, as jQuery had it.\n * ------------------------------------------------------------------ */\n\nvar DEFAULT_DURATION = 400;\n\nfunction animateAway(node, frames, duration, done) {\n duration = duration === undefined ? DEFAULT_DURATION : duration;\n\n var finish = function() {\n hide(node);\n if (done) { done(); }\n };\n\n if (!visible(node) || !node.animate || duration <= 0) {\n window.setTimeout(finish, 0);\n return;\n }\n\n var animation = node.animate(frames(getComputedStyle(node)), {\n duration: duration,\n easing: 'ease-in-out',\n });\n var called = false;\n var once = function() {\n if (called) { return; }\n called = true;\n finish();\n };\n\n animation.onfinish = once;\n animation.oncancel = once;\n}\n\n/** Fold a node up to nothing, then hide it. */\nexport function slideUp(node, duration, done) {\n if (typeof duration === 'function') {\n done = duration;\n duration = undefined;\n }\n\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n return [\n {\n height: style.height,\n paddingTop: style.paddingTop,\n paddingBottom: style.paddingBottom,\n marginTop: style.marginTop,\n marginBottom: style.marginBottom,\n },\n { height: '0px', paddingTop: '0px', paddingBottom: '0px', marginTop: '0px', marginBottom: '0px' },\n ];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n\n/** Fade a node out, then hide it. */\nexport function fadeOut(node, duration, done) {\n animateAway(node, function(style) {\n return [{ opacity: style.opacity }, { opacity: 0 }];\n }, duration, done);\n}\n\n/** Fade and fold a node, in height and, with `width`, sideways too, then hide it. */\nexport function shrinkAway(node, duration, done, width) {\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n var from = { opacity: style.opacity, height: style.height };\n var to = { opacity: 0, height: '0px' };\n\n if (width) {\n from.width = style.width;\n to.width = '0px';\n }\n return [from, to];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n", "/**\n * Element level controls for grid-editor.\n *\n * A feature plugin: load this file after the editor and the nodes a host\n * marked become elements - one movable, deletable block each, in the column\n * beside the texts, instead of rich text. What it can ask the editor for is\n * the handle its factory is called with, described in docs/plugins.md.\n *\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.elements.min.js\"></script>\n *\n * Up to 5.x an element lived inside a content area, among the text. Markup\n * saved that way still loads: the editor takes each element out of the text\n * it sits in, which is what `cuts` is for.\n */\nimport { GridEditor } from '../grideditor.js';\nimport * as dom from '../dom.js';\n\nObject.assign(GridEditor.locales.en, {\n 'tool.delete_element': 'Remove element',\n 'tool.element_info': 'Element: {name}',\n 'confirm.delete_element': 'Delete element?',\n});\n\n/** A column's children that are something else than an element, whatever elements.auto says. */\nvar NOT_ELEMENTS = '.row, .ge-content, .ge-text-block, [data-ge-container], .ge-tools-drawer, .ge-resize-handle';\n\nGridEditor.features.elements = function(ge) {\n\n var warnedIntoText = false;\n\n function elementsEnabled() {\n if (ge.settings.elements.enabled !== 'auto') { return !!ge.settings.elements.enabled; }\n\n return ge.settings.elements.auto || !!ge.canvas.querySelector(ge.settings.elements.selector);\n }\n\n /** Whether a child of a column is an element. */\n function isElement(node) {\n return ge.settings.elements.auto\n ? !node.matches(NOT_ELEMENTS)\n : node.matches(ge.settings.elements.selector);\n }\n\n function markElements() {\n if (!elementsEnabled()) { return; }\n\n dom.all(ge.canvas, '.column').forEach(function(column) {\n dom.children(column).forEach(function(element) {\n if (!dom.hasClass(element, 'ge-element') && !isElement(element)) { return; }\n\n dom.addClass(element, 'ge-element');\n if (!dom.child(element, '.ge-tools-drawer')) { createElementControls(element); }\n });\n });\n }\n\n function unmarkElements() {\n dom.all(ge.canvas, '.ge-element').forEach(function(element) {\n dom.removeClass(element, 'ge-element');\n\n // A host element that had no class of its own should not come\n // back from getHtml carrying an empty one\n dom.dropEmptyClass(element);\n });\n }\n\n function createElementControls(element) {\n var drawer = dom.element('div', { 'class': 'ge-tools-drawer ge-element-drawer' });\n element.insertBefore(drawer, element.firstChild);\n\n ge.createMoveTool(drawer);\n ge.createTool(drawer, ge.t('tool.element_info', { name: elementName(element) }),\n 'ge-element-info', 'bi bi-info-circle');\n ge.addSettingsTool(drawer, element, ge.settings.element_classes);\n\n ge.settings.element_tools.forEach(function(hostTool) {\n ge.createTool(drawer, hostTool.title || '', hostTool.className || '',\n hostTool.iconClass || 'bi bi-wrench', hostTool.on);\n });\n\n ge.createTool(drawer, ge.t('tool.delete_element'), 'ge-delete-element', 'bi bi-trash', function() {\n ge.deleteNode('element', element, ge.t('confirm.delete_element'), function(removed) {\n dom.shrinkAway(element, 300, removed);\n });\n });\n }\n\n function elementName(element) {\n var type = element.getAttribute('data-ge-element');\n var label = element.getAttribute('data-ge-label');\n\n if (label && type) { return label + ' (' + type + ')'; }\n\n return label || type || element.tagName.toLowerCase();\n }\n\n /**\n * Placed into a content area, as 5.x did, an element would be text\n * again, and the next init would cut it out. So it goes beside that\n * content area instead - after it for appendTo, before it for\n * prependTo - with a word to the host.\n */\n function placementBesideText(options) {\n var placed = Object.assign({}, options);\n\n [['appendTo', 'insertAfter'], ['prependTo', 'insertBefore']].forEach(function(pair) {\n var target = options[pair[0]] !== undefined ? nodeFrom(options[pair[0]]) : null;\n if (!target || !target.matches('.ge-content')) { return; }\n\n if (!warnedIntoText) {\n warnedIntoText = true;\n ge.warn('createElement: an element is a block of the column since 6.0, not part of a ' +\n 'content area\\'s text; it goes beside the content area. Place it in a column instead.');\n }\n\n delete placed[pair[0]];\n placed[pair[1]] = dom.hasClass(target.parentElement, 'ge-text-block') ? target.parentElement : target;\n });\n\n return placed;\n }\n\n /** A place a caller named: an element, or the first one a selector matches. */\n function nodeFrom(node) {\n if (typeof node === 'string') { return document.querySelector(node); }\n return node && node.nodeType === 1 ? node : null;\n }\n\n /**\n * What the element holds: html, which is parsed as innerHTML parses so\n * no <script> in it runs, or a node, or a list of nodes.\n */\n function fill(element, content) {\n if (content === undefined || content === null) { return; }\n\n if (typeof content === 'string') {\n dom.parse(content).forEach(function(node) { element.appendChild(node); });\n } else if (content.nodeType) {\n element.appendChild(content);\n } else if (typeof content.length === 'number') {\n Array.prototype.slice.call(content).forEach(function(node) { element.appendChild(node); });\n }\n }\n\n function apiCreateElement(content, options) {\n options = options || {};\n\n var element = dom.element('div', {\n 'class': 'ge-element',\n 'data-ge-element': options.type || 'element',\n });\n fill(element, content);\n if (options.label !== undefined) {\n element.setAttribute('data-ge-label', options.label);\n }\n\n return ge.place(element, 'element', placementBesideText(options));\n }\n\n return {\n methods: {\n createElement: apiCreateElement,\n },\n\n /** A node this plugin marked is an element, whatever else it is. */\n kindOf: function(node) {\n return dom.hasClass(node, 'ge-element') ? 'element' : null;\n },\n\n /**\n * An element cuts the text it sits in: 5.x's markup, or markup a host\n * wrote the same way, has it inside a content area, and it comes out.\n */\n cuts: function() {\n if (!elementsEnabled()) { return null; }\n\n return ge.settings.elements.auto ? '*' : ge.settings.elements.selector;\n },\n\n // A block the columns move, beside the texts, the rows and the\n // containers - and only the columns\n blocks: '.ge-element',\n accepts: function(region, node) {\n if (dom.hasClass(node, 'ge-element')) { return dom.is(region, '.column'); }\n\n return true;\n },\n\n onInit: markElements,\n onDeinit: unmarkElements,\n };\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * The DOM, the way grid-editor uses it.\n *\n * Small helpers over the browser's own API, for the core and the shipped\n * plugins. Not a public API: a plugin of a host's own is free to write its\n * DOM code however it likes, and this file makes no promise to it.\n *\n * Stateless on purpose. The build puts a copy of this file in each plugin's\n * classic script, so anything kept here would be kept once per copy; a\n * module that needs to remember something about a node keeps its own\n * WeakMap.\n */\n\n/** Every element under `root` matching `selector`, as an array. */\nexport function all(root, selector) {\n return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];\n}\n\n/** The first element under `root` matching `selector`, or null. */\nexport function one(root, selector) {\n return root ? root.querySelector(selector) : null;\n}\n\n/** `root` itself when it matches, then every element under it that does. */\nexport function selfAndAll(root, selector) {\n if (!root) { return []; }\n\n var found = all(root, selector);\n if (root.nodeType === 1 && root.matches(selector)) { found.unshift(root); }\n return found;\n}\n\n/** The element children of `node`, those matching `selector` if one is given. */\nexport function children(node, selector) {\n if (!node) { return []; }\n\n return Array.prototype.filter.call(node.children, function(each) {\n return !selector || each.matches(selector);\n });\n}\n\n/** The first element child matching `selector`, or null. */\nexport function child(node, selector) {\n return children(node, selector)[0] || null;\n}\n\n/** The nearest ancestor-or-self matching `selector` below `stopAt`, or null. */\nexport function closest(node, selector, stopAt) {\n var found = node && node.nodeType === 1 ? node.closest(selector) : null;\n\n if (found && stopAt && found !== stopAt && !stopAt.contains(found)) { return null; }\n return found;\n}\n\n/** Whether `node` is an element matching `selector`. */\nexport function is(node, selector) {\n return !!node && node.nodeType === 1 && node.matches(selector);\n}\n\n/** Whether `node` is in the document. */\nexport function attached(node) {\n return !!node && document.documentElement.contains(node);\n}\n\n/** The element siblings after `node` that match `selector`. */\nexport function nextAll(node, selector) {\n var found = [];\n\n for (var next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (!selector || next.matches(selector)) { found.push(next); }\n }\n return found;\n}\n\n/** The ancestors of `node` up to, and not including, `stop`, nearest first. */\nexport function parentsUntil(node, stop) {\n var found = [];\n\n for (var parent = node.parentElement; parent && parent !== stop; parent = parent.parentElement) {\n found.push(parent);\n }\n return found;\n}\n\n/**\n * The nodes the html parses into, detached. Parsed the way innerHTML parses,\n * so a <script> in it never runs, here or once it is in the page.\n */\nexport function parse(html) {\n var template = document.createElement('template');\n template.innerHTML = html;\n return Array.prototype.slice.call(template.content.childNodes);\n}\n\n/** The one element the html is, detached. */\nexport function create(html) {\n var nodes = parse(html.trim());\n\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i].nodeType === 1) { return nodes[i]; }\n }\n return null;\n}\n\n/** An element of `tag`, with `attributes` and `text`. */\nexport function element(tag, attributes, text) {\n var node = document.createElement(tag);\n\n Object.keys(attributes || {}).forEach(function(name) {\n var value = attributes[name];\n if (value !== null && value !== undefined && value !== false) { node.setAttribute(name, value); }\n });\n if (text !== undefined && text !== null) { node.textContent = text; }\n\n return node;\n}\n\n/** Replace what `node` holds with `html`. A <script> in it does not run. */\nexport function setHtml(node, html) {\n node.innerHTML = html === undefined || html === null ? '' : String(html);\n return node;\n}\n\n/** Add one or several space separated classes. */\nexport function addClass(node, names) {\n split(names).forEach(function(name) { node.classList.add(name); });\n return node;\n}\n\nexport function removeClass(node, names) {\n split(names).forEach(function(name) { node.classList.remove(name); });\n return node;\n}\n\n/** Each class on, or off, or flipped when `on` is not given. */\nexport function toggleClass(node, names, state) {\n split(names).forEach(function(name) {\n if (state === undefined) {\n node.classList.toggle(name);\n } else {\n node.classList.toggle(name, !!state);\n }\n });\n return node;\n}\n\nexport function hasClass(node, name) {\n return !!node && node.nodeType === 1 && node.classList.contains(name);\n}\n\nfunction split(names) {\n return String(names || '').split(/\\s+/).filter(Boolean);\n}\n\n/** Take the class attribute off when there is nothing left in it. */\nexport function dropEmptyClass(node) {\n if (!node.getAttribute('class')) { node.removeAttribute('class'); }\n return node;\n}\n\n/** Take the style attribute off when there is nothing left in it. */\nexport function dropEmptyStyle(node) {\n if (!node.getAttribute('style')) { node.removeAttribute('style'); }\n return node;\n}\n\n/** Set attributes; a null or undefined value takes the attribute off. */\nexport function attr(node, attributes) {\n Object.keys(attributes).forEach(function(name) {\n var value = attributes[name];\n\n if (value === null || value === undefined) {\n node.removeAttribute(name);\n } else {\n node.setAttribute(name, value);\n }\n });\n return node;\n}\n\n/**\n * Inline styles, by css property name. A number is pixels for the properties\n * that take a length, as jQuery had it; an empty string takes one off.\n */\nexport function css(node, styles) {\n Object.keys(styles).forEach(function(property) {\n var value = styles[property];\n\n if (typeof value === 'number' && !UNITLESS[property]) { value = value + 'px'; }\n node.style.setProperty(property, value === null || value === undefined ? '' : String(value));\n });\n return node;\n}\n\nvar UNITLESS = { opacity: true, 'z-index': true, 'flex-grow': true, 'flex-shrink': true, order: true };\n\n/** What an element of this tag shows as when nothing hides it. */\nvar defaultDisplays = {};\n\nfunction defaultDisplay(node) {\n var tag = node.nodeName;\n\n if (!defaultDisplays[tag]) {\n var probe = document.body.appendChild(document.createElement(tag));\n defaultDisplays[tag] = getComputedStyle(probe).display;\n probe.remove();\n if (defaultDisplays[tag] === 'none') { defaultDisplays[tag] = 'block'; }\n }\n return defaultDisplays[tag];\n}\n\n/** Show a node: its inline display:none off, and a display of its own if a stylesheet hides it. */\nexport function show(node) {\n node.style.removeProperty('display');\n if (getComputedStyle(node).display === 'none') { node.style.display = defaultDisplay(node); }\n return node;\n}\n\nexport function hide(node) {\n node.style.display = 'none';\n return node;\n}\n\n/** Show or hide; flip when `on` is not given. */\nexport function toggle(node, state) {\n if (state === undefined) { state = !visible(node); }\n return state ? show(node) : hide(node);\n}\n\n/** Whether a node takes up room: what jQuery's :visible meant. */\nexport function visible(node) {\n return !!(node.offsetWidth || node.offsetHeight || node.getClientRects().length);\n}\n\n/** The border box's width, fractions included. */\nexport function outerWidth(node) {\n return node.getBoundingClientRect().width;\n}\n\nexport function outerHeight(node) {\n return node.getBoundingClientRect().height;\n}\n\n/** The content box's height, which is what jQuery's height() gave. */\nexport function contentHeight(node) {\n var style = getComputedStyle(node);\n return node.clientHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);\n}\n\n/** Where a node is on the page, not in the window. */\nexport function offset(node) {\n var box = node.getBoundingClientRect();\n return { top: box.top + window.pageYOffset, left: box.left + window.pageXOffset };\n}\n\n/** Its index among its parent's element children, those matching `selector` if given. */\nexport function indexIn(node, selector) {\n return children(node.parentElement, selector).indexOf(node);\n}\n\n/** Put `node` right after `reference`. */\nexport function insertAfter(node, reference) {\n reference.parentNode.insertBefore(node, reference.nextSibling);\n return node;\n}\n\n/** Replace `node` with what it holds. */\nexport function unwrap(node) {\n var parent = node.parentNode;\n\n while (node.firstChild) { parent.insertBefore(node.firstChild, node); }\n node.remove();\n}\n\n/** Put `node` inside `wrapper`, where `node` was. */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Listen on `root` for `types` (space separated) on descendants that match\n * `selector`, with `this` the matched element, as jQuery's delegated\n * handlers had it. Hands back the listener, for removeEventListener; a\n * signal in `options` removes it too.\n */\nexport function delegate(root, types, selector, handler, options) {\n var listener = function(event) {\n var match = closest(event.target, selector, root);\n if (match && root.contains(match)) { return handler.call(match, event); }\n return undefined;\n };\n\n split(types).forEach(function(type) { root.addEventListener(type, listener, options); });\n return listener;\n}\n\n/** Listen for several space separated event types with one handler. */\nexport function on(target, types, handler, options) {\n split(types).forEach(function(type) { target.addEventListener(type, handler, options); });\n return handler;\n}\n\nexport function off(target, types, handler, options) {\n split(types).forEach(function(type) { target.removeEventListener(type, handler, options); });\n}\n\n/** A mouse event of `type` sent to `node`, the way a pointer would. */\nexport function fire(node, type) {\n node.dispatchEvent(new MouseEvent(type, { bubbles: type !== 'mouseenter' && type !== 'mouseleave' }));\n}\n\n/* ------------------------------------------------------------------\n * Taking a node away, visibly.\n *\n * The durations are jQuery's: 400 ms unless the caller says otherwise. `done` runs once the node is out of sight, which is\n * when the caller removes it; a node that is already out of sight is done at\n * once, on the next task, as jQuery had it.\n * ------------------------------------------------------------------ */\n\nvar DEFAULT_DURATION = 400;\n\nfunction animateAway(node, frames, duration, done) {\n duration = duration === undefined ? DEFAULT_DURATION : duration;\n\n var finish = function() {\n hide(node);\n if (done) { done(); }\n };\n\n if (!visible(node) || !node.animate || duration <= 0) {\n window.setTimeout(finish, 0);\n return;\n }\n\n var animation = node.animate(frames(getComputedStyle(node)), {\n duration: duration,\n easing: 'ease-in-out',\n });\n var called = false;\n var once = function() {\n if (called) { return; }\n called = true;\n finish();\n };\n\n animation.onfinish = once;\n animation.oncancel = once;\n}\n\n/** Fold a node up to nothing, then hide it. */\nexport function slideUp(node, duration, done) {\n if (typeof duration === 'function') {\n done = duration;\n duration = undefined;\n }\n\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n return [\n {\n height: style.height,\n paddingTop: style.paddingTop,\n paddingBottom: style.paddingBottom,\n marginTop: style.marginTop,\n marginBottom: style.marginBottom,\n },\n { height: '0px', paddingTop: '0px', paddingBottom: '0px', marginTop: '0px', marginBottom: '0px' },\n ];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n\n/** Fade a node out, then hide it. */\nexport function fadeOut(node, duration, done) {\n animateAway(node, function(style) {\n return [{ opacity: style.opacity }, { opacity: 0 }];\n }, duration, done);\n}\n\n/** Fade and fold a node, in height and, with `width`, sideways too, then hide it. */\nexport function shrinkAway(node, duration, done, width) {\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n var from = { opacity: style.opacity, height: style.height };\n var to = { opacity: 0, height: '0px' };\n\n if (width) {\n from.width = style.width;\n to.width = '0px';\n }\n return [from, to];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n", "/**\n * Element level controls for grid-editor.\n *\n * A feature plugin: load this file after the editor and the nodes a host\n * marked become elements - one movable, deletable block each, in the column\n * beside the texts, instead of rich text. What it can ask the editor for is\n * the handle its factory is called with, described in docs/plugins.md.\n *\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.elements.min.js\"></script>\n *\n * Up to 5.x an element lived inside a content area, among the text. Markup\n * saved that way still loads: the editor takes each element out of the text\n * it sits in, which is what `cuts` is for.\n */\nimport { GridEditor } from '../grideditor.js';\nimport * as dom from '../dom.js';\n\nObject.assign(GridEditor.locales.en, {\n 'tool.delete_element': 'Remove element',\n 'tool.element_info': 'Element: {name}',\n 'confirm.delete_element': 'Delete element?',\n});\n\n/** A column's children that are something else than an element, whatever elements.auto says. */\nvar NOT_ELEMENTS = '.row, .ge-content, .ge-text-block, [data-ge-container], .ge-tools-drawer, .ge-resize-handle';\n\nGridEditor.features.elements = function(ge) {\n\n var warnedIntoText = false;\n\n function elementsEnabled() {\n if (ge.settings.elements.enabled !== 'auto') { return !!ge.settings.elements.enabled; }\n\n return ge.settings.elements.auto || !!ge.canvas.querySelector(ge.settings.elements.selector);\n }\n\n /** Whether a child of a column is an element. */\n function isElement(node) {\n return ge.settings.elements.auto\n ? !node.matches(NOT_ELEMENTS)\n : node.matches(ge.settings.elements.selector);\n }\n\n function markElements() {\n if (!elementsEnabled()) { return; }\n\n dom.all(ge.canvas, '.column').forEach(function(column) {\n dom.children(column).forEach(function(element) {\n if (!dom.hasClass(element, 'ge-element') && !isElement(element)) { return; }\n\n dom.addClass(element, 'ge-element');\n if (!dom.child(element, '.ge-tools-drawer')) { createElementControls(element); }\n });\n });\n }\n\n function unmarkElements() {\n dom.all(ge.canvas, '.ge-element').forEach(function(element) {\n dom.removeClass(element, 'ge-element');\n\n // A host element that had no class of its own should not come\n // back from getHtml carrying an empty one\n dom.dropEmptyClass(element);\n });\n }\n\n function createElementControls(element) {\n var drawer = dom.element('div', { 'class': 'ge-tools-drawer ge-element-drawer' });\n element.insertBefore(drawer, element.firstChild);\n\n ge.createMoveTool(drawer);\n ge.createTool(drawer, ge.t('tool.element_info', { name: elementName(element) }),\n 'ge-element-info', 'bi bi-info-circle');\n ge.addSettingsTool(drawer, element, ge.settings.element_classes);\n\n ge.settings.element_tools.forEach(function(hostTool) {\n ge.createTool(drawer, hostTool.title || '', hostTool.className || '',\n hostTool.iconClass || 'bi bi-wrench', hostTool.on);\n });\n\n ge.createTool(drawer, ge.t('tool.delete_element'), 'ge-delete-element', 'bi bi-trash', function() {\n ge.deleteNode('element', element, ge.t('confirm.delete_element'), function(removed) {\n dom.shrinkAway(element, 300, removed);\n });\n });\n }\n\n function elementName(element) {\n var type = element.getAttribute('data-ge-element');\n var label = element.getAttribute('data-ge-label');\n\n if (label && type) { return label + ' (' + type + ')'; }\n\n return label || type || element.tagName.toLowerCase();\n }\n\n /**\n * Placed into a content area, as 5.x did, an element would be text\n * again, and the next init would cut it out. So it goes beside that\n * content area instead - after it for appendTo, before it for\n * prependTo - with a word to the host.\n */\n function placementBesideText(options) {\n var placed = Object.assign({}, options);\n\n [['appendTo', 'insertAfter'], ['prependTo', 'insertBefore']].forEach(function(pair) {\n var target = options[pair[0]] !== undefined ? nodeFrom(options[pair[0]]) : null;\n if (!target || !target.matches('.ge-content')) { return; }\n\n if (!warnedIntoText) {\n warnedIntoText = true;\n ge.warn('createElement: an element is a block of the column since 6.0, not part of a ' +\n 'content area\\'s text; it goes beside the content area. Place it in a column instead.');\n }\n\n delete placed[pair[0]];\n placed[pair[1]] = dom.hasClass(target.parentElement, 'ge-text-block') ? target.parentElement : target;\n });\n\n return placed;\n }\n\n /** A place a caller named: an element, or the first one a selector matches. */\n function nodeFrom(node) {\n if (typeof node === 'string') { return document.querySelector(node); }\n return node && node.nodeType === 1 ? node : null;\n }\n\n /**\n * What the element holds: html, which is parsed as innerHTML parses so\n * no <script> in it runs, or a node, or a list of nodes.\n */\n function fill(element, content) {\n if (content === undefined || content === null) { return; }\n\n if (typeof content === 'string') {\n dom.parse(content).forEach(function(node) { element.appendChild(node); });\n } else if (content.nodeType) {\n element.appendChild(content);\n } else if (typeof content.length === 'number') {\n Array.prototype.slice.call(content).forEach(function(node) { element.appendChild(node); });\n }\n }\n\n function apiCreateElement(content, options) {\n options = options || {};\n\n var element = dom.element('div', {\n 'class': 'ge-element',\n 'data-ge-element': options.type || 'element',\n });\n fill(element, content);\n if (options.label !== undefined) {\n element.setAttribute('data-ge-label', options.label);\n }\n\n return ge.place(element, 'element', placementBesideText(options));\n }\n\n return {\n methods: {\n createElement: apiCreateElement,\n },\n\n /** A node this plugin marked is an element, whatever else it is. */\n kindOf: function(node) {\n return dom.hasClass(node, 'ge-element') ? 'element' : null;\n },\n\n /**\n * An element cuts the text it sits in: 5.x's markup, or markup a host\n * wrote the same way, has it inside a content area, and it comes out.\n */\n cuts: function() {\n if (!elementsEnabled()) { return null; }\n\n return ge.settings.elements.auto ? '*' : ge.settings.elements.selector;\n },\n\n // A block the columns move, beside the texts, the rows and the\n // containers - and only the columns\n blocks: '.ge-element',\n accepts: function(region, node) {\n if (dom.hasClass(node, 'ge-element')) { return dom.is(region, '.column'); }\n\n return true;\n },\n\n onInit: markElements,\n onDeinit: unmarkElements,\n };\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["GridEditor", "all", "root", "selector", "children", "node", "selector", "each", "child", "is", "node", "selector", "parse", "html", "template", "element", "tag", "attributes", "text", "node", "name", "value", "addClass", "node", "names", "split", "name", "removeClass", "hasClass", "node", "name", "split", "names", "dropEmptyClass", "hide", "node", "visible", "node", "DEFAULT_DURATION", "animateAway", "node", "frames", "duration", "done", "finish", "hide", "visible", "animation", "called", "once", "shrinkAway", "node", "duration", "done", "width", "animateAway", "style", "from", "to", "GridEditor", "NOT_ELEMENTS", "ge", "warnedIntoText", "elementsEnabled", "isElement", "node", "markElements", "all", "column", "children", "element", "hasClass", "addClass", "child", "createElementControls", "unmarkElements", "removeClass", "dropEmptyClass", "drawer", "elementName", "hostTool", "removed", "shrinkAway", "type", "label", "placementBesideText", "options", "placed", "pair", "target", "nodeFrom", "fill", "content", "parse", "apiCreateElement", "region", "is"]
7
7
  }