evwt
Version:
1,201 lines (1,039 loc) • 79.1 kB
JavaScript
const numeric = (value, unit) => Number(value.slice(0, -1 * unit.length));
const parseValue = value => {
if (value.endsWith('px')) { return { value, type: 'px', numeric: numeric(value, 'px') }; }
if (value.endsWith('fr')) { return { value, type: 'fr', numeric: numeric(value, 'fr') }; }
if (value.endsWith('%')) { return { value, type: '%', numeric: numeric(value, '%') }; }
if (value === 'auto') return { value, type: 'auto' };
return null;
};
const parse = rule => rule.split(' ').map(parseValue);
const getSizeAtTrack = (index, tracks, gap = 0, end = false) => {
const newIndex = end ? index + 1 : index;
const trackSum = tracks
.slice(0, newIndex)
.reduce((accum, value) => accum + value.numeric, 0);
const gapSum = gap ? index * gap : 0;
return trackSum + gapSum;
};
const getStyles = (rule, ownRules, matchedRules) =>
[...ownRules, ...matchedRules]
.map(r => r.style[rule])
.filter(style => style !== undefined && style !== '');
const getGapValue = (unit, size) => {
if (size.endsWith(unit)) {
return Number(size.slice(0, -1 * unit.length))
}
return null
};
const firstNonZero = tracks => {
// eslint-disable-next-line no-plusplus
for (let i = 0; i < tracks.length; i++) {
if (tracks[i].numeric > 0) {
return i
}
}
return null
};
const NOOP = () => false;
const defaultWriteStyle = (element, gridTemplateProp, style) => {
// eslint-disable-next-line no-param-reassign
element.style[gridTemplateProp] = style;
};
const getOption = (options, propName, def) => {
const value = options[propName];
if (value !== undefined) {
return value
}
return def
};
var getMatchedCSSRules = el =>
[]
.concat(
...Array.from(el.ownerDocument.styleSheets).map(s => {
let rules = [];
try {
rules = Array.from(s.cssRules || []);
} catch (e) {
// Ignore results on security error
}
return rules
}),
)
.filter(r => {
let matches = false;
try {
matches = el.matches(r.selectorText);
} catch (e) {
// Ignore matching erros
}
return matches
});
const gridTemplatePropColumns = 'grid-template-columns';
const gridTemplatePropRows = 'grid-template-rows';
class Gutter {
constructor(direction, options, parentOptions) {
this.direction = direction;
this.element = options.element;
this.track = options.track;
if (direction === 'column') {
this.gridTemplateProp = gridTemplatePropColumns;
this.gridGapProp = 'grid-column-gap';
this.cursor = getOption(
parentOptions,
'columnCursor',
getOption(parentOptions, 'cursor', 'col-resize'),
);
this.snapOffset = getOption(
parentOptions,
'columnSnapOffset',
getOption(parentOptions, 'snapOffset', 30),
);
this.dragInterval = getOption(
parentOptions,
'columnDragInterval',
getOption(parentOptions, 'dragInterval', 1),
);
this.clientAxis = 'clientX';
this.optionStyle = getOption(parentOptions, 'gridTemplateColumns');
} else if (direction === 'row') {
this.gridTemplateProp = gridTemplatePropRows;
this.gridGapProp = 'grid-row-gap';
this.cursor = getOption(
parentOptions,
'rowCursor',
getOption(parentOptions, 'cursor', 'row-resize'),
);
this.snapOffset = getOption(
parentOptions,
'rowSnapOffset',
getOption(parentOptions, 'snapOffset', 30),
);
this.dragInterval = getOption(
parentOptions,
'rowDragInterval',
getOption(parentOptions, 'dragInterval', 1),
);
this.clientAxis = 'clientY';
this.optionStyle = getOption(parentOptions, 'gridTemplateRows');
}
this.onDragStart = getOption(parentOptions, 'onDragStart', NOOP);
this.onDragEnd = getOption(parentOptions, 'onDragEnd', NOOP);
this.onDrag = getOption(parentOptions, 'onDrag', NOOP);
this.writeStyle = getOption(
parentOptions,
'writeStyle',
defaultWriteStyle,
);
this.startDragging = this.startDragging.bind(this);
this.stopDragging = this.stopDragging.bind(this);
this.drag = this.drag.bind(this);
this.dblClick = this.dblClick.bind(this);
this.minSizeStart = options.minSizeStart;
this.minSizeEnd = options.minSizeEnd;
if (options.element) {
this.element.addEventListener('dblclick', this.dblClick);
this.element.addEventListener('mousedown', this.startDragging);
this.element.addEventListener('touchstart', this.startDragging);
}
}
getDimensions() {
const {
width,
height,
top,
bottom,
left,
right
} = this.grid.getBoundingClientRect();
if (this.direction === 'column') {
this.start = top;
this.end = bottom;
this.size = height;
} else if (this.direction === 'row') {
this.start = left;
this.end = right;
this.size = width;
}
}
getSizeAtTrack(track, end) {
return getSizeAtTrack(
track,
this.computedPixels,
this.computedGapPixels,
end,
);
}
getSizeOfTrack(track) {
return this.computedPixels[track].numeric;
}
getRawTracks() {
const tracks = getStyles(
this.gridTemplateProp,
[this.grid],
getMatchedCSSRules(this.grid),
);
if (!tracks.length) {
if (this.optionStyle) return this.optionStyle;
throw Error('Unable to determine grid template tracks from styles.');
}
return tracks[0];
}
getGap() {
const gap = getStyles(
this.gridGapProp,
[this.grid],
getMatchedCSSRules(this.grid),
);
if (!gap.length) {
return null;
}
return gap[0];
}
getRawComputedTracks() {
return window.getComputedStyle(this.grid)[this.gridTemplateProp];
}
getRawComputedGap() {
return window.getComputedStyle(this.grid)[this.gridGapProp];
}
setTracks(raw) {
this.tracks = raw.split(' ');
this.trackValues = parse(raw);
}
setComputedTracks(raw) {
this.computedTracks = raw.split(' ');
this.computedPixels = parse(raw);
}
setGap(raw) {
this.gap = raw;
}
setComputedGap(raw) {
this.computedGap = raw;
this.computedGapPixels = getGapValue('px', this.computedGap) || 0;
}
getMousePosition(e) {
if ('touches' in e) return e.touches[0][this.clientAxis];
return e[this.clientAxis];
}
dblClick() {
this.element.dispatchEvent(new Event('doubleclick'));
}
startDragging(e) {
if ('button' in e && e.button !== 0) {
return;
}
// Don't actually drag the element. We emulate that in the drag function.
e.preventDefault();
if (this.element) {
this.grid = this.element.parentNode;
} else {
this.grid = e.target.parentNode;
}
this.getDimensions();
this.setTracks(this.getRawTracks());
this.setComputedTracks(this.getRawComputedTracks());
this.setGap(this.getGap());
this.setComputedGap(this.getRawComputedGap());
const trackPercentage = this.trackValues.filter(
track => track.type === '%',
);
const trackFr = this.trackValues.filter(track => track.type === 'fr');
this.totalFrs = trackFr.length;
if (this.totalFrs) {
const track = firstNonZero(trackFr);
if (track !== null) {
this.frToPixels = this.computedPixels[track].numeric / trackFr[track].numeric;
if (this.frToPixels === 0) {
this.frToPixels = Number.EPSILON;
}
}
}
if (trackPercentage.length) {
const track = firstNonZero(trackPercentage);
if (track !== null) {
this.percentageToPixels = this.computedPixels[track].numeric
/ trackPercentage[track].numeric;
}
}
// get start of gutter track
const gutterStart = this.getSizeAtTrack(this.track, false) + this.start;
this.dragStartOffset = this.getMousePosition(e) - gutterStart;
this.aTrack = this.track - 1;
if (this.track < this.tracks.length - 1) {
this.bTrack = this.track + 1;
} else {
throw Error(
`Invalid track index: ${this.track}. Track must be between two other tracks and only ${this.tracks.length} tracks were found.`,
);
}
this.aTrackStart = this.getSizeAtTrack(this.aTrack, false) + this.start;
this.bTrackEnd = this.getSizeAtTrack(this.bTrack, true) + this.start;
// Set the dragging property of the pair object.
this.dragging = true;
// All the binding. `window` gets the stop events in case we drag out of the elements.
window.addEventListener('mouseup', this.stopDragging);
window.addEventListener('touchend', this.stopDragging);
window.addEventListener('touchcancel', this.stopDragging);
window.addEventListener('mousemove', this.drag);
window.addEventListener('touchmove', this.drag);
window.addEventListener('dblclick', this.dblClick);
// Disable selection. Disable!
this.grid.addEventListener('selectstart', NOOP);
this.grid.addEventListener('dragstart', NOOP);
this.grid.style.userSelect = 'none';
this.grid.style.webkitUserSelect = 'none';
this.grid.style.MozUserSelect = 'none';
this.grid.style.pointerEvents = 'none';
// Set the cursor at multiple levels
this.grid.style.cursor = this.cursor;
window.document.body.style.cursor = this.cursor;
this.onDragStart(this.direction, this.track, this.element);
}
stopDragging() {
this.dragging = false;
// Remove the stored event listeners. This is why we store them.
this.cleanup();
this.onDragEnd(this.direction, this.track, this.element);
if (this.needsDestroy) {
if (this.element) {
this.element.removeEventListener(
'mousedown',
this.startDragging,
);
this.element.removeEventListener(
'touchstart',
this.startDragging,
);
}
this.destroyCb();
this.needsDestroy = false;
this.destroyCb = null;
}
}
drag(e) {
let mousePosition = this.getMousePosition(e);
const gutterSize = this.getSizeOfTrack(this.track);
const minMousePosition = this.aTrackStart
+ this.minSizeStart
+ this.dragStartOffset
+ this.computedGapPixels;
const maxMousePosition = this.bTrackEnd
- this.minSizeEnd
- this.computedGapPixels
- (gutterSize - this.dragStartOffset);
const minMousePositionOffset = minMousePosition + this.snapOffset;
const maxMousePositionOffset = maxMousePosition - this.snapOffset;
if (mousePosition < minMousePositionOffset) {
mousePosition = minMousePosition;
}
if (mousePosition > maxMousePositionOffset) {
mousePosition = maxMousePosition;
}
if (mousePosition < minMousePosition) {
mousePosition = minMousePosition;
} else if (mousePosition > maxMousePosition) {
mousePosition = maxMousePosition;
}
let aTrackSize = mousePosition
- this.aTrackStart
- this.dragStartOffset
- this.computedGapPixels;
let bTrackSize = this.bTrackEnd
- mousePosition
+ this.dragStartOffset
- gutterSize
- this.computedGapPixels;
if (this.dragInterval > 1) {
const aTrackSizeIntervaled = Math.round(aTrackSize / this.dragInterval) * this.dragInterval;
bTrackSize -= aTrackSizeIntervaled - aTrackSize;
aTrackSize = aTrackSizeIntervaled;
}
if (aTrackSize < this.minSizeStart) {
aTrackSize = this.minSizeStart;
}
if (bTrackSize < this.minSizeEnd) {
bTrackSize = this.minSizeEnd;
}
if (this.trackValues[this.aTrack].type === 'px') {
this.tracks[this.aTrack] = `${aTrackSize}px`;
} else if (this.trackValues[this.aTrack].type === 'fr') {
if (this.totalFrs === 1) {
this.tracks[this.aTrack] = '1fr';
} else {
const targetFr = aTrackSize / this.frToPixels;
this.tracks[this.aTrack] = `${targetFr}fr`;
}
} else if (this.trackValues[this.aTrack].type === '%') {
const targetPercentage = aTrackSize / this.percentageToPixels;
this.tracks[this.aTrack] = `${targetPercentage}%`;
}
if (this.trackValues[this.bTrack].type === 'px') {
this.tracks[this.bTrack] = `${bTrackSize}px`;
} else if (this.trackValues[this.bTrack].type === 'fr') {
if (this.totalFrs === 1) {
this.tracks[this.bTrack] = '1fr';
} else if (this.trackValues[this.aTrack].type === 'fr') {
const targetFr = bTrackSize / this.frToPixels;
this.tracks[this.bTrack] = `${targetFr}fr`;
}
} else if (this.trackValues[this.bTrack].type === '%') {
const targetPercentage = bTrackSize / this.percentageToPixels;
this.tracks[this.bTrack] = `${targetPercentage}%`;
}
const style = this.tracks.join(' ');
this.writeStyle(this.grid, this.gridTemplateProp, style);
this.onDrag(this.direction, this.track, this.element, style);
}
cleanup() {
window.removeEventListener('mouseup', this.stopDragging);
window.removeEventListener('touchend', this.stopDragging);
window.removeEventListener('touchcancel', this.stopDragging);
window.removeEventListener('mousemove', this.drag);
window.removeEventListener('touchmove', this.drag);
// Double click apparently needs to go to the end of the event loop
setTimeout(() => {
window.removeEventListener('dblclick', this.dblClick);
}, 0);
if (this.grid) {
this.grid.removeEventListener('selectstart', NOOP);
this.grid.removeEventListener('dragstart', NOOP);
this.grid.style.userSelect = '';
this.grid.style.webkitUserSelect = '';
this.grid.style.MozUserSelect = '';
this.grid.style.pointerEvents = '';
this.grid.style.cursor = '';
}
window.document.body.style.cursor = '';
}
destroy(immediate = true, cb) {
if (immediate || this.dragging === false) {
this.cleanup();
if (this.element) {
this.element.removeEventListener(
'mousedown',
this.startDragging,
);
this.element.removeEventListener(
'touchstart',
this.startDragging,
);
}
if (cb) {
cb();
}
} else {
this.needsDestroy = true;
if (cb) {
this.destroyCb = cb;
}
}
}
}
const getTrackOption = (options, track, defaultValue) => {
if (track in options) {
return options[track]
}
return defaultValue
};
const createGutter = (direction, options) => gutterOptions => {
if (gutterOptions.track < 1) {
throw Error(
`Invalid track index: ${gutterOptions.track}. Track must be between two other tracks.`,
)
}
const trackMinSizes =
direction === 'column'
? options.columnMinSizes || {}
: options.rowMinSizes || {};
const trackMinSize = direction === 'column' ? 'columnMinSize' : 'rowMinSize';
return new Gutter(
direction,
{
minSizeStart: getTrackOption(
trackMinSizes,
gutterOptions.track - 1,
getOption(
options,
trackMinSize,
getOption(options, 'minSize', 0),
),
),
minSizeEnd: getTrackOption(
trackMinSizes,
gutterOptions.track + 1,
getOption(
options,
trackMinSize,
getOption(options, 'minSize', 0),
),
),
...gutterOptions,
},
options,
)
};
class Grid {
constructor(options) {
this.columnGutters = {};
this.rowGutters = {};
this.options = {
columnGutters: options.columnGutters || [],
rowGutters: options.rowGutters || [],
columnMinSizes: options.columnMinSizes || {},
rowMinSizes: options.rowMinSizes || {},
...options,
};
this.options.columnGutters.forEach(gutterOptions => {
this.columnGutters[options.track] = createGutter(
'column',
this.options,
)(gutterOptions);
});
this.options.rowGutters.forEach(gutterOptions => {
this.rowGutters[options.track] = createGutter(
'row',
this.options,
)(gutterOptions);
});
}
addColumnGutter(element, track) {
if (this.columnGutters[track]) {
this.columnGutters[track].destroy();
}
this.columnGutters[track] = createGutter(
'column',
this.options,
)({
element,
track,
});
}
addRowGutter(element, track) {
if (this.rowGutters[track]) {
this.rowGutters[track].destroy();
}
this.rowGutters[track] = createGutter(
'row',
this.options,
)({
element,
track,
});
}
removeColumnGutter(track, immediate = true) {
if (this.columnGutters[track]) {
this.columnGutters[track].destroy(immediate, () => {
delete this.columnGutters[track];
});
}
}
removeRowGutter(track, immediate = true) {
if (this.rowGutters[track]) {
this.rowGutters[track].destroy(immediate, () => {
delete this.rowGutters[track];
});
}
}
handleDragStart(e, direction, track) {
if (direction === 'column') {
if (this.columnGutters[track]) {
this.columnGutters[track].destroy();
}
this.columnGutters[track] = createGutter(
'column',
this.options,
)({
track,
});
this.columnGutters[track].startDragging(e);
} else if (direction === 'row') {
if (this.rowGutters[track]) {
this.rowGutters[track].destroy();
}
this.rowGutters[track] = createGutter(
'row',
this.options,
)({
track,
});
this.rowGutters[track].startDragging(e);
}
}
destroy(immediate = true) {
Object.keys(this.columnGutters).forEach(track =>
this.columnGutters[track].destroy(immediate, () => {
delete this.columnGutters[track];
}),
);
Object.keys(this.rowGutters).forEach(track =>
this.rowGutters[track].destroy(immediate, () => {
delete this.rowGutters[track];
}),
);
}
}
var Split = options => new Grid(options);
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
var script = {
name: 'EvLayoutChild',
props: {
child: Object
},
computed: {
classForChild() {
if (this.child && this.child.name) {
return `ev-pane-${this.child.name}`;
}
return '';
},
childStyle() {
if (!this.child.sizes || !this.child.sizes.length || !this.child.direction) {
return;
}
let sizes = this.child.sizes.map(s => [s, '0']).flat();
sizes.pop();
return `grid-template-${this.child.direction}s: ${sizes.join(' ')}`;
}
},
methods: {
gutterClass(child, direction) {
let className = `ev-gutter ev-gutter-${child.name} ev-gutter-${direction}`;
if (child.resizable === false) {
className += ' ev-gutter-no-resize';
}
return className;
}
}
};
function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
if (typeof shadowMode !== 'boolean') {
createInjectorSSR = createInjector;
createInjector = shadowMode;
shadowMode = false;
}
// Vue.extend constructor export interop.
const options = typeof script === 'function' ? script.options : script;
// render functions
if (template && template.render) {
options.render = template.render;
options.staticRenderFns = template.staticRenderFns;
options._compiled = true;
// functional template
if (isFunctionalTemplate) {
options.functional = true;
}
}
// scopedId
if (scopeId) {
options._scopeId = scopeId;
}
let hook;
if (moduleIdentifier) {
// server build
hook = function (context) {
// 2.3 injection
context =
context || // cached call
(this.$vnode && this.$vnode.ssrContext) || // stateful
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
// 2.2 with runInNewContext: true
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
context = __VUE_SSR_CONTEXT__;
}
// inject component styles
if (style) {
style.call(this, createInjectorSSR(context));
}
// register component module identifier for async chunk inference
if (context && context._registeredComponents) {
context._registeredComponents.add(moduleIdentifier);
}
};
// used by ssr in case component is cached and beforeCreate
// never gets called
options._ssrRegister = hook;
}
else if (style) {
hook = shadowMode
? function (context) {
style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
}
: function (context) {
style.call(this, createInjector(context));
};
}
if (hook) {
if (options.functional) {
// register for functional component in vue file
const originalRender = options.render;
options.render = function renderWithStyleInjection(h, context) {
hook.call(context);
return originalRender(h, context);
};
}
else {
// inject component registration as beforeCreate hook
const existing = options.beforeCreate;
options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
}
}
return script;
}
const isOldIE = typeof navigator !== 'undefined' &&
/msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
function createInjector(context) {
return (id, style) => addStyle(id, style);
}
let HEAD;
const styles = {};
function addStyle(id, css) {
const group = isOldIE ? css.media || 'default' : id;
const style = styles[group] || (styles[group] = { ids: new Set(), styles: [] });
if (!style.ids.has(id)) {
style.ids.add(id);
let code = css.source;
if (css.map) {
// https://developer.chrome.com/devtools/docs/javascript-debugging
// this makes source maps inside style tags work properly in Chrome
code += '\n/*# sourceURL=' + css.map.sources[0] + ' */';
// http://stackoverflow.com/a/26603875
code +=
'\n/*# sourceMappingURL=data:application/json;base64,' +
btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) +
' */';
}
if (!style.element) {
style.element = document.createElement('style');
style.element.type = 'text/css';
if (css.media)
style.element.setAttribute('media', css.media);
if (HEAD === undefined) {
HEAD = document.head || document.getElementsByTagName('head')[0];
}
HEAD.appendChild(style.element);
}
if ('styleSheet' in style.element) {
style.styles.push(code);
style.element.styleSheet.cssText = style.styles
.filter(Boolean)
.join('\n');
}
else {
const index = style.ids.size - 1;
const textNode = document.createTextNode(code);
const nodes = style.element.childNodes;
if (nodes[index])
style.element.removeChild(nodes[index]);
if (nodes.length)
style.element.insertBefore(textNode, nodes[index]);
else
style.element.appendChild(textNode);
}
}
}
/* script */
const __vue_script__ = script;
/* template */
var __vue_render__ = function() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c(
"div",
{
staticClass: "d-grid overflow-hidden h-100 w-100",
class: _vm.classForChild,
style: _vm.childStyle,
attrs: {
"data-min-size": _vm.child.minSize,
"data-evlayout-name": _vm.child.name
}
},
[
!_vm.child.panes
? _c(
"div",
{ staticClass: "ev-layout-pane h-100 w-100 overflow-auto" },
[_vm._t(_vm.child.name)],
2
)
: _vm._e(),
_vm._v(" "),
_vm._l(_vm.child.panes, function(grandChild, idx) {
return [
_c(
"ev-layout-child",
{
key: grandChild.name,
attrs: { child: grandChild },
scopedSlots: _vm._u(
[
_vm._l(_vm.$scopedSlots, function(_, name) {
return {
key: name,
fn: function(slotData) {
return [_vm._t(name, null, null, slotData)]
}
}
})
],
null,
true
)
},
[
_vm._l(_vm.$slots, function(_, name) {
return _vm._t(name, null, { slot: name })
})
],
2
),
_vm._v(" "),
_vm.child.panes[idx + 1]
? _c("div", {
key: grandChild.name + "gutter",
class: _vm.gutterClass(grandChild, _vm.child.direction)
})
: _vm._e()
]
})
],
2
)
};
var __vue_staticRenderFns__ = [];
__vue_render__._withStripped = true;
/* style */
const __vue_inject_styles__ = function (inject) {
if (!inject) return
inject("data-v-748ace0d_0", { source: "*[data-v-748ace0d] {\n box-sizing: border-box;\n}\n*[data-v-748ace0d]:before,\n*[data-v-748ace0d]:after {\n box-sizing: border-box;\n}\n.h-100[data-v-748ace0d] {\n height: 100%;\n}\n.vh-100[data-v-748ace0d] {\n height: 100vh;\n}\n.w-100[data-v-748ace0d] {\n width: 100%;\n}\n.vw-100[data-v-748ace0d] {\n width: 100vw;\n}\n.pre-line[data-v-748ace0d] {\n white-space: pre-line;\n}\n.pre-wrap[data-v-748ace0d] {\n white-space: pre-wrap;\n}\n.no-wrap[data-v-748ace0d] {\n white-space: nowrap;\n}\n.d-block[data-v-748ace0d] {\n display: block;\n}\n.d-inline-block[data-v-748ace0d] {\n display: inline-block;\n}\n.d-flex[data-v-748ace0d] {\n display: flex;\n}\n.d-inline-flex[data-v-748ace0d] {\n display: inline-flex;\n}\n.d-grid[data-v-748ace0d] {\n display: grid;\n}\n.d-none[data-v-748ace0d] {\n display: none;\n}\n.hide[data-v-748ace0d] {\n visibility: hidden;\n}\n.overflow-hidden[data-v-748ace0d] {\n overflow: hidden;\n}\n.overflow-auto[data-v-748ace0d] {\n overflow: auto;\n}\n.flex-center[data-v-748ace0d] {\n justify-content: center;\n}\n.flex-middle[data-v-748ace0d] {\n align-items: center;\n}\n.flex-grow[data-v-748ace0d] {\n flex-grow: 1;\n}\n.flex-shrink[data-v-748ace0d] {\n flex-shrink: 1;\n}\n.flex-vertical[data-v-748ace0d] {\n flex-direction: column;\n}\n.flex-space[data-v-748ace0d] {\n justify-content: space-between;\n}\n.flex-end[data-v-748ace0d] {\n justify-content: flex-end;\n}\n.flex-start[data-v-748ace0d] {\n justify-content: flex-start;\n}\n.text-center[data-v-748ace0d] {\n text-align: center;\n}\n.m-z[data-v-748ace0d] {\n margin: 0 !important;\n}\n.m-n-z[data-v-748ace0d] {\n margin-top: 0 !important;\n}\n.m-e-z[data-v-748ace0d] {\n margin-right: 0 !important;\n}\n.m-s-z[data-v-748ace0d] {\n margin-bottom: 0 !important;\n}\n.m-w-z[data-v-748ace0d] {\n margin-left: 0 !important;\n}\n.m-n-xl[data-v-748ace0d] {\n margin-top: 25px;\n}\n.m-e-xl[data-v-748ace0d] {\n margin-right: 25px;\n}\n.m-s-xl[data-v-748ace0d] {\n margin-bottom: 25px;\n}\n.m-w-xl[data-v-748ace0d] {\n margin-left: 25px;\n}\n.m-n-lg[data-v-748ace0d] {\n margin-top: 20px;\n}\n.m-e-lg[data-v-748ace0d] {\n margin-right: 20px;\n}\n.m-s-lg[data-v-748ace0d] {\n margin-bottom: 20px;\n}\n.m-w-lg[data-v-748ace0d] {\n margin-left: 20px;\n}\n.m-n-med[data-v-748ace0d] {\n margin-top: 15px;\n}\n.m-e-med[data-v-748ace0d] {\n margin-right: 15px;\n}\n.m-s-med[data-v-748ace0d] {\n margin-bottom: 15px;\n}\n.m-w-med[data-v-748ace0d] {\n margin-left: 15px;\n}\n.m-n-sm[data-v-748ace0d] {\n margin-top: 10px;\n}\n.m-e-sm[data-v-748ace0d] {\n margin-right: 10px;\n}\n.m-s-sm[data-v-748ace0d] {\n margin-bottom: 10px;\n}\n.m-w-sm[data-v-748ace0d] {\n margin-left: 10px;\n}\n.m-n-xs[data-v-748ace0d] {\n margin-top: 5px;\n}\n.m-e-xs[data-v-748ace0d] {\n margin-right: 5px;\n}\n.m-s-xs[data-v-748ace0d] {\n margin-bottom: 5px;\n}\n.m-w-xs[data-v-748ace0d] {\n margin-left: 5px;\n}\n.m-n-xxs[data-v-748ace0d] {\n margin-top: 2px;\n}\n.m-e-xxs[data-v-748ace0d] {\n margin-right: 2px;\n}\n.m-s-xxs[data-v-748ace0d] {\n margin-bottom: 2px;\n}\n.m-w-xxs[data-v-748ace0d] {\n margin-left: 2px;\n}\n.p-z[data-v-748ace0d] {\n padding: 0 !important;\n}\n.p-n-z[data-v-748ace0d] {\n padding-top: 0 !important;\n}\n.p-e-z[data-v-748ace0d] {\n padding-right: 0 !important;\n}\n.p-s-z[data-v-748ace0d] {\n padding-bottom: 0 !important;\n}\n.p-w-z[data-v-748ace0d] {\n padding-left: 0 !important;\n}\n.p-n-xl[data-v-748ace0d] {\n padding-top: 25px;\n}\n.p-e-xl[data-v-748ace0d] {\n padding-right: 25px;\n}\n.p-s-xl[data-v-748ace0d] {\n padding-bottom: 25px;\n}\n.p-w-xl[data-v-748ace0d] {\n padding-left: 25px;\n}\n.p-n-lg[data-v-748ace0d] {\n padding-top: 20px;\n}\n.p-e-lg[data-v-748ace0d] {\n padding-right: 20px;\n}\n.p-s-lg[data-v-748ace0d] {\n padding-bottom: 20px;\n}\n.p-w-lg[data-v-748ace0d] {\n padding-left: 20px;\n}\n.p-n-med[data-v-748ace0d] {\n padding-top: 15px;\n}\n.p-e-med[data-v-748ace0d] {\n padding-right: 15px;\n}\n.p-s-med[data-v-748ace0d] {\n padding-bottom: 15px;\n}\n.p-w-med[data-v-748ace0d] {\n padding-left: 15px;\n}\n.p-n-sm[data-v-748ace0d] {\n padding-top: 10px;\n}\n.p-e-sm[data-v-748ace0d] {\n padding-right: 10px;\n}\n.p-s-sm[data-v-748ace0d] {\n padding-bottom: 10px;\n}\n.p-w-sm[data-v-748ace0d] {\n padding-left: 10px;\n}\n.p-n-xs[data-v-748ace0d] {\n padding-top: 5px;\n}\n.p-e-xs[data-v-748ace0d] {\n padding-right: 5px;\n}\n.p-s-xs[data-v-748ace0d] {\n padding-bottom: 5px;\n}\n.p-w-xs[data-v-748ace0d] {\n padding-left: 5px;\n}\n.p-xs[data-v-748ace0d] {\n padding: 5px;\n}\n.p-n-xxs[data-v-748ace0d] {\n padding-top: 2px;\n}\n.p-e-xxs[data-v-748ace0d] {\n padding-right: 2px;\n}\n.p-s-xxs[data-v-748ace0d] {\n padding-bottom: 2px;\n}\n.p-w-xxs[data-v-748ace0d] {\n padding-left: 2px;\n}\n.p-xxs[data-v-748ace0d] {\n padding: 2px;\n}\n.p-xs[data-v-748ace0d] {\n padding: 5px;\n}\n.p-sm[data-v-748ace0d] {\n padding: 10px;\n}\n.p-med[data-v-748ace0d] {\n padding: 15px;\n}\n.p-lg[data-v-748ace0d] {\n padding: 20px;\n}\n.p-xl[data-v-748ace0d] {\n padding: 25px;\n}\n.m-xxs[data-v-748ace0d] {\n margin: 2px;\n}\n.m-xs[data-v-748ace0d] {\n margin: 5px;\n}\n.m-sm[data-v-748ace0d] {\n margin: 10px;\n}\n.m-med[data-v-748ace0d] {\n margin: 15px;\n}\n.m-lg[data-v-748ace0d] {\n margin: 20px;\n}\n.m-xl[data-v-748ace0d] {\n margin: 25px;\n}\n.ev-gutter-column[data-v-748ace0d] {\n cursor: col-resize;\n}\n.ev-gutter-row[data-v-748ace0d] {\n cursor: row-resize;\n}\n.ev-gutter[data-v-748ace0d]:not(.ev-gutter-no-resize)::after {\n display: block;\n position: relative;\n content: \"\";\n}\n.ev-gutter:not(.ev-gutter-no-resize).ev-gutter-column[data-v-748ace0d]::after {\n width: 8px;\n height: 100%;\n margin-left: -4px;\n}\n.ev-gutter:not(.ev-gutter-no-resize).ev-gutter-row[data-v-748ace0d]::after {\n width: 100%;\n height: 8px;\n margin-top: -4px;\n}\n.ev-layout-pane-maximized[data-v-748ace0d] {\n border: 0;\n}\n\n/*# sourceMappingURL=EvLayoutChild.vue.map */", map: {"version":3,"sources":["EvLayoutChild.vue","/Users/john/Code/evwt/components/src/EvLayoutChild.vue"],"names":[],"mappings":"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","file":"EvLayoutChild.vue","sourcesContent":["* {\n box-sizing: border-box;\n}\n\n*:before,\n*:after {\n box-sizing: border-box;\n}\n\n.h-100 {\n height: 100%;\n}\n\n.vh-100 {\n height: 100vh;\n}\n\n.w-100 {\n width: 100%;\n}\n\n.vw-100 {\n width: 100vw;\n}\n\n.pre-line {\n white-space: pre-line;\n}\n\n.pre-wrap {\n white-space: pre-wrap;\n}\n\n.no-wrap {\n white-space: nowrap;\n}\n\n.d-block {\n display: block;\n}\n\n.d-inline-block {\n display: inline-block;\n}\n\n.d-flex {\n display: flex;\n}\n\n.d-inline-flex {\n display: inline-flex;\n}\n\n.d-grid {\n display: grid;\n}\n\n.d-none {\n display: none;\n}\n\n.hide {\n visibility: hidden;\n}\n\n.overflow-hidden {\n overflow: hidden;\n}\n\n.overflow-auto {\n overflow: auto;\n}\n\n.flex-center {\n justify-content: center;\n}\n\n.flex-middle {\n align-items: center;\n}\n\n.flex-grow {\n flex-grow: 1;\n}\n\n.flex-shrink {\n flex-shrink: 1;\n}\n\n.flex-vertical {\n flex-direction: column;\n}\n\n.flex-space {\n justify-content: space-between;\n}\n\n.flex-end {\n justify-content: flex-end;\n}\n\n.flex-start {\n justify-content: flex-start;\n}\n\n.text-center {\n text-align: center;\n}\n\n.m-z {\n margin: 0 !important;\n}\n\n.m-n-z {\n margin-top: 0 !important;\n}\n\n.m-e-z {\n margin-right: 0 !important;\n}\n\n.m-s-z {\n margin-bottom: 0 !important;\n}\n\n.m-w-z {\n margin-left: 0 !important;\n}\n\n.m-n-xl {\n margin-top: 25px;\n}\n\n.m-e-xl {\n margin-right: 25px;\n}\n\n.m-s-xl {\n margin-bottom: 25px;\n}\n\n.m-w-xl {\n margin-left: 25px;\n}\n\n.m-n-lg {\n margin-top: 20px;\n}\n\n.m-e-lg {\n margin-right: 20px;\n}\n\n.m-s-lg {\n margin-bottom: 20px;\n}\n\n.m-w-lg {\n margin-left: 20px;\n}\n\n.m-n-med {\n margin-top: 15px;\n}\n\n.m-e-med {\n margin-right: 15px;\n}\n\n.m-s-med {\n margin-bottom: 15px;\n}\n\n.m-w-med {\n margin-left: 15px;\n}\n\n.m-n-sm {\n margin-top: 10px;\n}\n\n.m-e-sm {\n margin-right: 10px;\n}\n\n.m-s-sm {\n margin-bottom: 10px;\n}\n\n.m-w-sm {\n margin-left: 10px;\n}\n\n.m-n-xs {\n margin-top: 5px;\n}\n\n.m-e-xs {\n margin-right: 5px;\n}\n\n.m-s-xs {\n margin-bottom: 5px;\n}\n\n.m-w-xs {\n margin-left: 5px;\n}\n\n.m-n-xxs {\n margin-top: 2px;\n}\n\n.m-e-xxs {\n margin-right: 2px;\n}\n\n.m-s-xxs {\n margin-bottom: 2px;\n}\n\n.m-w-xxs {\n margin-left: 2px;\n}\n\n.p-z {\n padding: 0 !important;\n}\n\n.p-n-z {\n padding-top: 0 !important;\n}\n\n.p-e-z {\n padding-right: 0 !important;\n}\n\n.p-s-z {\n padding-bottom: 0 !important;\n}\n\n.p-w-z {\n padding-left: 0 !important;\n}\n\n.p-n-xl {\n padding-top: 25px;\n}\n\n.p-e-xl {\n padding-right: 25px;\n}\n\n.p-s-xl {\n padding-bottom: 25px;\n}\n\n.p-w-xl {\n padding-left: 25px;\n}\n\n.p-n-lg {\n padding-top: 20px;\n}\n\n.p-e-lg {\n padding-right: 20px;\n}\n\n.p-s-lg {\n padding-bottom: 20px;\n}\n\n.p-w-lg {\n padding-left: 20px;\n}\n\n.p-n-med {\n padding-top: 15px;\n}\n\n.p-e-med {\n padding-right: 15px;\n}\n\n.p-s-med {\n padding-bottom: 15px;\n}\n\n.p-w-med {\n padding-left: 15px;\n}\n\n.p-n-sm {\n padding-top: 10px;\n}\n\n.p-e-sm {\n padding-right: 10px;\n}\n\n.p-s-sm {\n padding-bottom: 10px;\n}\n\n.p-w-sm {\n padding-left: 10px;\n}\n\n.p-n-xs {\n padding-top: 5px;\n}\n\n.p-e-xs {\n padding-right: 5px;\n}\n\n.p-s-xs {\n padding-bottom: 5px;\n}\n\n.p-w-xs {\n padding-left: 5px;\n}\n\n.p-xs {\n padding: 5px;\n}\n\n.p-n-xxs {\n padding-top: 2px;\n}\n\n.p-e-xxs {\n padding-right: 2px;\n}\n\n.p-s-xxs {\n padding-bottom: 2px;\n}\n\n.p-w-xxs {\n padding-left: 2px;\n}\n\n.p-xxs {\n padding: 2px;\n}\n\n.p-xs {\n padding: 5px;\n}\n\n.p-sm {\n padding: 10px;\n}\n\n.p-med {\n padding: 15px;\n}\n\n.p-lg {\n padding: 20px;\n}\n\n.p-xl {\n padding: 25px;\n}\n\n.m-xxs {\n margin: 2px;\n}\n\n.m-xs {\n margin: 5px;\n}\n\n.m-sm {\n margin: 10px;\n}\n\n.m-med {\n margin: 15px;\n}\n\n.m-lg {\n margin: 20px;\n}\n\n.m-xl {\n margin: 25px;\n}\n\n.ev-gutter-column {\n cursor: col-resize;\n}\n\n.ev-gutter-row {\n cursor: row-resize;\n}\n\n.ev-gutter:not(.ev-gutter-no-resize)::after {\n display: block;\n position: relative;\n content: \"\";\n}\n.ev-gutter:not(.ev-gutter-no-resize).ev-gutter-column::after {\n width: 8px;\n height: 100%;\n margin-left: -4px;\n}\n.ev-gutter:not(.ev-gutter-no-resize).ev-gutter-row::after {\n width: 100%;\n height: 8px;\n margin-top: -4px;\n}\n\n.ev-layout-pane-maximized {\n border: 0;\n}\n\n/*# sourceMappingURL=EvLayoutChild.vue.map */","<template>\n <div\n :style=\"childStyle\"\n :data-min-size=\"child.minSize\"\n :data-evlayout-name=\"child.name\"\n class=\"d-grid overflow-hidden h-100 w-100\"\n :class=\"classForChild\">\n <div v-if=\"!child.panes\" class=\"ev-layout-pane h-100 w-100 overflow-auto\">\n <slot :name=\"child.name\" class=\"overflow-auto\" />\n </div>\n\n <template v-for=\"(grandChild, idx) in child.panes\">\n <ev-layout-child\n :key=\"grandChild.name\"\n :child=\"grandChild\">\n <slot v-for=\"(_, name) in $slots\" :slot=\"name\" :name=\"name\" />\n <template v-for=\"(_, name) in $scopedSlots\" :slot=\"name\" slot-scope=\"slotData\">\n <slot :name=\"name\" v-bind=\"slotData\" />\n </template>\n </ev-layout-child>\n\n <div\n v-if=\"child.panes[idx + 1]\"\n :key=\"grandChild.name + 'gutter'\"\n :class=\"gutterClass(grandChild, child.direction)\" />\n </template>\n </div>\n</template>\n\n<script>\nexport default {\n name: 'EvLayoutChild',\n\n props: {\n child: Object\n },\n\n computed: {\n classForChild() {\n if (this.child && this.child.name) {\n return `ev-pane-${this.child.name}`;\n }\n\n return '';\n },\n\n childStyle() {\n if (!this.child.sizes || !this.child.sizes.length || !this.child.direction) {\n return;\n }\n\n let sizes = this.child.sizes.map(s => [s, '0']).flat();\n sizes.pop();\n\n return `grid-template-${this.child.direction}s: ${sizes.join(' ')}`;\n }\n },\n\n methods: {\n gutterClass(child, direction) {\n let className = `ev-gutter ev-gutter-${child.name} ev-gutter-${direction}`;\n\n if (child.resizable === false) {\n className += ' ev-gutter-no-resize';\n }\n\n return className;\n }\n }\n};\n</script>\n\n<style lang=\"scss\" scoped>\n@import '../../style/reset.scss';\n@import '../../style/utilities.scss';\n@import '../../style/split-grid.scss';\n</style>\n"]}, media: undefined });
};
/* scoped */
const __vue_scope_id__ = "data-v-748ace0d";
/* module identifier */
const __vue_module_identifier__ = undefined;
/* functional template */
const __vue_is_functional_template__ = false;
/* style inject SSR */
/* style inject shadow dom */
const __vue_component__ = /*#__PURE__*/normalizeComponent(
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
__vue_inject_styles__,
__vue_script__,
__vue_scope_id__,
__vue_is_functional_template__,
__vue_module_identifier__,
false,
createInjector,
undefined,
undefined
);
//
let cloneDeep = require('lodash.clonedeep');
var script$1 = {
name: 'EvLayout',
components: {
EvLayoutChild: __vue_component__
},
props: {
// The top-level Pane
layout: {
type: Object,
required: true
}
},
data() {
return {
layoutData: null
};
},
async created() {
this.layoutData = cloneDeep(this.layout);
this.loadUiState();
},
async mounted() {
let rowGutters = [...this.$el.querySelectorAll('.ev-gutter-row')].map((gutter) => ({
track: Array.prototype.indexOf.call(gutter.parentNode.children, gutter),
element: gutter
}));
let columnGutters = [...this.$el.querySelectorAll('.ev-gutter-column')].map((gutter) => ({
track: Array.prototype.indexOf.call(gutter.parentNode.children, gutter),
element: gutter
}));
// Return the panes before and after this gutter to their default sizes
for (const gutter of [...this.$el.querySelectorAll('.ev-gutter')]) {
gutter.addEventListener('doubleclick', (e) => {
let parent = e.target.parentElement;
let parentName = parent.dataset.evlayoutName;
let track = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
let leadingIndex = Math.floor(track / 2);
let trailingIndex = Math.ceil(track / 2);
let gridTemplate = parent.style.gridTemplateColumns || parent.style.gridTemplateRows;
let sizes = gridTemplate.split(' ').filter(s => s !== '0px');
let defaultSizes = this.defaultSizeForTrack(parentName, this.layout);
sizes[leadingIndex] = defaultSizes[leadingIndex];
sizes[trailingIndex] = defaultSizes[trailingIndex];
if (gutter.classList.contains('ev-gutter-row')) {
parent.style.gridTemplateRows = sizes.join(' 0px ');
} else {
parent.style.gridTemplateColumns = sizes.join(' 0px ');
}
if (this.$evstore && this.$evstore.$ui) {
this.syncLayoutDataForPane(parentName, this.layoutData, sizes);
this.saveUiState();
}
});
}
let minSizeReducer = (acc, gutter) => {
let prevPane = gutter.previousElementSibling;
if (prevPane) {
let minSize = parseInt(prevPane.dataset.minSize || 0);
let index = Array.prototype.indexOf.call(prevPane.parentNode.children, prevPane);
acc[index] = minSize;
}
let nextPane = gutter.nextElementSibling;
if (nextPane) {
let minSizeNext = parseInt(nextPane.dataset.minSize || 0);
let indexNext = Array.prototype.indexOf.call(nextPane.parentNode.children, nextPane);
acc[indexNext] = minSizeNext;
}
return acc;
};
let columnMinSizes = [...this.$el.querySelectorAll('.ev-gutter-column')].reduce(minSizeReducer, {});
let rowMinSizes = [...this.$el.querySelectorAll('.ev-gutter-row')].reduce(minSizeReducer, {});
let onDragStart = (direction, track, element) => {
// Fired when any pane starts dragging
// @arg direction, track, gutter element
this.$emit('dragStart', { direction, track, element });
};
let onDrag = (direction, track, element, gridTemplateStyle) => {
addMinimizedMaximizedClasses(direction, track, element);
// Fired when any pane is dragging
// @arg direction, track, gutter element, gridTemplateStyle
this.$emit('drag', {
direction, track, element, gridTemplateStyle
});
};
let addMinimizedMaximizedClasses = (direction, track, element) => {
let maximizedClassName = 'ev-layout-pane-maximized';
let minimizedClassName = 'ev-layout-pane-minimized';
let offsetKey = direction === 'column' ? 'offsetWidth' : 'offsetHeight';
let parent = element.parentElement;
let previousPane = element.previousElementSibling;
let nextPane = element.nextElementSibling;
if (previousPane && previousPane[offsetKey] === parent[offsetKey]) {
previousPane.classList.add(maximizedClassName);
} else if (previousPane.classList.contains(maximizedClassName)) {
previousPane.classList.remove(maximizedClassName);
}
if (previousPane && previousPane[offsetKey] === 0) {
previousPane.classList.add(minimizedClassName);
} else if (previousPane.classList.contains(minimizedClassName)) {
previousPane.classList.remove(minimizedClassName);
}
if (nextPane && nextPane[offsetKey] === parent[offsetKey]) {
nextPane.classList.add(maximizedClassName);
} else if (nextPane.classList.contains(maximizedClassName)) {
nextPane.classList.remove(maximizedClassName);
}
if (nextPane && nextPane[offsetKey] === 0) {
nextPane.classList.add(minimizedClassName);
} else if (nextPane.classList.contains(minimizedClassName)) {
nextPane.classList.remove(minimizedClassName);
}
};
for (const gutter of rowGutters) {
addMinimizedMaximizedClasses('row', gutter.track, gutter.element);
}
for (const gutter of columnGutters) {
addMinimizedMaximizedClasses('column', gutter.track, gutter.element);
}
let onDragEnd = async (direction, track, element) => {
// Fired when any pane ends dragging
// @arg direction, track, gutter element
this.$emit('dragEnd', { direction, track, element });
if (this.$evstore && this.$evstore.$ui) {
let { gridTemplateColumns, gridTemplateRows } = element.parentElement.style;
let gridTemplate = gridTemplateColumns || gridTemplateRows;
let sizes = gridTemplate.split(' 0px ');
let name = element.parentElement.dataset.evlayoutName;
this.syncLayoutDataForPane(name, this.layoutData, sizes);
this.saveUiState();
}
};
Split({
columnGutters, rowGutters, columnMinSizes, rowMinSizes, onDragStart, onDrag, onDragEnd
});
},
methods: {
loadUiState() {
if (!this.$evstore || !this.$evstore.$ui) return;
if (typeof this.$evstore.$ui.store.layout === 'object') {
for (const [paneName, paneSizes] of Object.entries(this.$evstore.$ui.store.layout)) {
this.syncLayoutDataForPane(paneName, this.layoutData, paneSizes);
}
}
},
saveUiState() {
this.$set(this.$evstore.$ui.store, 'layout', this.getSizesForPanes(this.layoutData));
},
syncLayoutDataForPane(name, layoutData, sizes) {
if (layoutData.name === name) {
layoutData.sizes = sizes;
return;
}
for (let idx = 0; idx < layoutData.panes.length; idx++) {
let pane = layoutData.panes[idx];
if (!pane) continue;
if (pane.name === name) {
pane.sizes = sizes;
}
if (pane.panes) {
this.syncLayoutDataForPane(name, pane, sizes);
}
}
},
defaultSizeForTrack(name, layoutData) {
if (layoutData.name === name) {
return layoutData.sizes;
}
for (let idx = 0; idx < layoutData.panes.length; idx++) {
let pane = layoutData.panes[idx];
if (!pane) continue;
if (pane.name === name) {
return pane.sizes;
}
if (pane.panes) {
this.defaultSizeForTrack(name, pane);
}
}
},
getSizesForPanes(layoutData, sizes = {}) {
sizes[la