(function () {
'use strict';
function optionsAttributes(attributes, options) {
const attrs = Object.assign({}, attributes['']);
options.forEach((opt) => {
Object.assign(attrs, attributes[opt] || {});
});
return attrs;
}
class WavePattern {
constructor(width, height) {
if(Array.isArray(height)) {
this.deltas = height;
} else {
this.deltas = [
0,
-height * 2 / 3,
-height,
-height * 2 / 3,
0,
height * 2 / 3,
height,
height * 2 / 3,
];
}
this.partWidth = width / this.deltas.length;
}
getDelta(p) {
return this.deltas[p % this.deltas.length];
}
}
class BaseTheme {
constructor(svg, baseFontAttrs) {
this.svg = svg;
this.baseFontAttrs = baseFontAttrs;
this.fontSize = this.baseFontAttrs['font-size'];
this.connectLines = new Map();
}
addConnectLine(type, {
attrs = {},
pattern = null,
} = {}) {
const base = this.connectLines.get('solid') || {attrs: {}};
const fullAttrs = Object.assign({'fill': 'none'}, base.attrs, attrs);
this.connectLines.set(type, {
attrs: fullAttrs,
renderFlat: this.renderFlatConnect.bind(this, pattern, fullAttrs),
renderRev: this.renderRevConnect.bind(this, pattern, fullAttrs),
});
}
// PUBLIC API
reset() {
// No-op
}
addDefs(builder, textBuilder) {
// Thanks, https://stackoverflow.com/a/12263962/1180785
// https://bugs.chromium.org/p/chromium/issues/detail?id=603157
// https://bugzilla.mozilla.org/show_bug.cgi?id=917766
textBuilder('highlight', () => this.svg.el('filter')
.add(
// Morph makes characters consistent
this.svg.el('feMorphology').attrs({
'in': 'SourceAlpha',
'operator': 'dilate',
'radius': '4',
}),
// Blur+thresh makes edges smooth
this.svg.el('feGaussianBlur').attrs({
'edgeMode': 'none',
'stdDeviation': '3, 1.5',
}),
this.svg.el('feComponentTransfer').add(
this.svg.el('feFuncA').attrs({
'intercept': -70,
'slope': 100,
'type': 'linear',
})
),
// Add colour
this.svg.el('feComponentTransfer').add(
this.svg.el('feFuncR').attrs({
'intercept': 1,
'slope': 0,
'type': 'linear',
}),
this.svg.el('feFuncG').attrs({
'intercept': 0.9375,
'slope': 0,
'type': 'linear',
}),
this.svg.el('feFuncB').attrs({
'intercept': 0.09375,
'slope': 0,
'type': 'linear',
}),
this.svg.el('feFuncA').attrs({
'slope': 0.7,
'type': 'linear',
})
),
// Draw text on top
this.svg.el('feMerge').add(
this.svg.el('feMergeNode'),
this.svg.el('feMergeNode').attr('in', 'SourceGraphic')
)
));
}
getTitleAttrs() {
return Object.assign({}, this.baseFontAttrs, {
'font-size': this.fontSize * 2.5,
'text-anchor': 'middle',
});
}
getConnectLine(type) {
const lines = this.connectLines;
return lines.get(type) || lines.get('solid');
}
getBlock(type) {
return this.blocks[type] || this.blocks[''];
}
getNote(type) {
return this.notes[type] || this.notes[''];
}
getDivider(type) {
return this.dividers[type] || this.dividers[''];
}
optionsAttributes(attributes, options) {
return optionsAttributes(attributes, options);
}
renderAgentLine({className, options, width, x, y0, y1}) {
const attrs = this.optionsAttributes(this.agentLineAttrs, options);
if(width > 0) {
return this.svg.box(attrs, {
height: y1 - y0,
width,
x: x - width / 2,
y: y0,
}).addClass(className);
} else {
return this.svg.line(attrs, {
'x1': x,
'x2': x,
'y1': y0,
'y2': y1,
}).addClass(className);
}
}
// INTERNAL HELPERS
renderArrowHead(attrs, {dir, height, width, x, y}) {
const wx = width * dir.dx;
const wy = width * dir.dy;
const hy = height * 0.5 * dir.dx;
const hx = -height * 0.5 * dir.dy;
return this.svg.el(attrs.fill === 'none' ? 'polyline' : 'polygon')
.attr('points', (
(x + wx - hx) + ' ' + (y + wy - hy) + ' ' +
x + ' ' + y + ' ' +
(x + wx + hx) + ' ' + (y + wy + hy)
))
.attrs(attrs);
}
renderTag(attrs, {height, width, x, y}) {
const {rx, ry} = attrs;
const x2 = x + width;
const y2 = y + height;
const line = (
'M' + x2 + ' ' + y +
'L' + x2 + ' ' + (y2 - ry) +
'L' + (x2 - rx) + ' ' + y2 +
'L' + x + ' ' + y2
);
const g = this.svg.el('g');
if(attrs.fill !== 'none') {
g.add(this.svg.el('path')
.attr('d', line + 'L' + x + ' ' + y)
.attrs(attrs)
.attr('stroke', 'none'));
}
if(attrs.stroke !== 'none') {
g.add(this.svg.el('path')
.attr('d', line)
.attrs(attrs)
.attr('fill', 'none'));
}
return g;
}
renderDB(attrs, position) {
const z = attrs['db-z'];
return this.svg.el('g').add(
this.svg.box({
'rx': position.width / 2,
'ry': z,
}, position).attrs(attrs),
this.svg.el('path')
.attr('d', (
'M' + position.x + ' ' + (position.y + z) +
'a' + (position.width / 2) + ' ' + z +
' 0 0 0 ' + position.width + ' 0'
))
.attrs(attrs)
.attr('fill', 'none')
);
}
renderRef(options, position) {
return {
fill: this.svg.box(options, position).attrs({'stroke': 'none'}),
mask: this.svg.box(options, position).attrs({
'fill': '#000000',
'stroke': 'none',
}),
shape: this.svg.box(options, position).attrs({'fill': 'none'}),
};
}
renderFlatConnect(
pattern,
attrs,
{x1, y1, x2, y2}
) {
return {
p1: {x: x1, y: y1},
p2: {x: x2, y: y2},
shape: this.svg.el('path')
.attr('d', this.svg.patternedLine(pattern)
.move(x1, y1)
.line(x2, y2)
.cap()
.asPath())
.attrs(attrs),
};
}
renderRevConnect(
pattern,
attrs,
{rad, x1, x2, xR, y1, y2}
) {
const maxRad = (y2 - y1) / 2;
const line = this.svg.patternedLine(pattern)
.move(x1, y1)
.line(xR, y1);
if(rad < maxRad) {
line
.arc(xR, y1 + rad, Math.PI / 2)
.line(xR + rad, y2 - rad)
.arc(xR, y2 - rad, Math.PI / 2);
} else {
line.arc(xR, (y1 + y2) / 2, Math.PI);
}
return {
p1: {x: x1, y: y1},
p2: {x: x2, y: y2},
shape: this.svg.el('path')
.attr('d', line
.line(x2, y2)
.cap()
.asPath())
.attrs(attrs),
};
}
renderLineDivider(
{lineAttrs},
{height, labelWidth, width, x, y}
) {
let shape = null;
const yPos = y + height / 2;
if(labelWidth > 0) {
shape = this.svg.el('g').add(
this.svg.line({'fill': 'none'}, {
'x1': x,
'x2': x + (width - labelWidth) / 2,
'y1': yPos,
'y2': yPos,
}).attrs(lineAttrs),
this.svg.line({'fill': 'none'}, {
'x1': x + (width + labelWidth) / 2,
'x2': x + width,
'y1': yPos,
'y2': yPos,
}).attrs(lineAttrs)
);
} else {
shape = this.svg.line({'fill': 'none'}, {
'x1': x,
'x2': x + width,
'y1': yPos,
'y2': yPos,
}).attrs(lineAttrs);
}
return {shape};
}
renderDelayDivider(
{dotSize, gapSize},
{height, width, x, y}
) {
const mask = this.svg.el('g');
for(let i = 0; i + gapSize <= height; i += dotSize + gapSize) {
mask.add(this.svg.box({
'fill': '#000000',
}, {
height: gapSize,
width,
x,
y: y + i,
}));
}
return {mask};
}
renderTearDivider(
{fadeBegin, fadeSize, lineAttrs, pattern, zigHeight, zigWidth},
{env, height, labelHeight, labelWidth, width, x, y}
) {
const maskGradID = env.addDef('tear-grad', () => {
const px = 100 / width;
return this.svg.linearGradient({}, [
{
'offset': (fadeBegin * px) + '%',
'stop-color': '#000000',
},
{
'offset': ((fadeBegin + fadeSize) * px) + '%',
'stop-color': '#FFFFFF',
},
{
'offset': (100 - (fadeBegin + fadeSize) * px) + '%',
'stop-color': '#FFFFFF',
},
{
'offset': (100 - fadeBegin * px) + '%',
'stop-color': '#000000',
},
]);
});
const shapeMask = this.svg.el('mask')
.attr('maskUnits', 'userSpaceOnUse')
.add(
this.svg.box({
'fill': 'url(#' + maskGradID + ')',
}, {
height: height + 10,
width,
x,
y: y - 5,
})
);
const shapeMaskID = env.addDef(shapeMask);
if(labelWidth > 0) {
shapeMask.add(this.svg.box({
'fill': '#000000',
'rx': 2,
'ry': 2,
}, {
'height': labelHeight + 2,
'width': labelWidth,
'x': x + (width - labelWidth) / 2,
'y': y + (height - labelHeight) / 2 - 1,
}));
}
const p = pattern || new WavePattern(zigWidth, [zigHeight, -zigHeight]);
let mask = null;
const pathTop = this.svg.patternedLine(p)
.move(x, y)
.line(x + width, y);
const shape = this.svg.el('g')
.attr('mask', 'url(#' + shapeMaskID + ')')
.add(
this.svg.el('path')
.attrs({
'd': pathTop.asPath(),
'fill': 'none',
})
.attrs(lineAttrs)
);
if(height > 0) {
const pathBase = this.svg.patternedLine(p)
.move(x, y + height)
.line(x + width, y + height);
shape.add(
this.svg.el('path')
.attrs({
'd': pathBase.asPath(),
'fill': 'none',
})
.attrs(lineAttrs)
);
pathTop
.line(pathBase.x, pathBase.y, {patterned: false})
.cap();
pathTop.points.push(...pathBase.points.reverse());
mask = this.svg.el('path').attrs({
'd': pathTop.asPath(),
'fill': '#000000',
});
}
return {mask, shape};
}
}
/* eslint-disable sort-keys */ // Maybe later
const FONT = 'Helvetica,Arial,Liberation Sans,sans-serif';
const LINE_HEIGHT = 1.3;
const NOTE_ATTRS = {
'font-family': FONT,
'font-size': 8,
'line-height': LINE_HEIGHT,
};
const DIVIDER_LABEL_ATTRS = {
'font-family': FONT,
'font-size': 8,
'line-height': LINE_HEIGHT,
'text-anchor': 'middle',
};
class BasicTheme extends BaseTheme {
constructor(svg) {
super(svg, {
'font-family': FONT,
'font-size': 8,
'line-height': LINE_HEIGHT,
});
const sharedBlockSection = {
padding: {
top: 3,
bottom: 2,
},
tag: {
padding: {
top: 1,
left: 3,
right: 3,
bottom: 0,
},
boxRenderer: this.renderTag.bind(this, {
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 1,
'rx': 2,
'ry': 2,
}),
labelAttrs: {
'font-family': FONT,
'font-weight': 'bold',
'font-size': 9,
'line-height': LINE_HEIGHT,
'text-anchor': 'left',
},
},
label: {
minHeight: 4,
padding: {
top: 1,
left: 5,
right: 3,
bottom: 1,
},
labelAttrs: {
'font-family': FONT,
'font-size': 8,
'line-height': LINE_HEIGHT,
'text-anchor': 'left',
},
},
};
Object.assign(this, {
titleMargin: 10,
outerMargin: 5,
agentMargin: 10,
actionMargin: 10,
minActionMargin: 3,
agentLineHighlightRadius: 4,
agentCap: {
box: {
padding: {
top: 5,
left: 10,
right: 10,
bottom: 5,
},
arrowBottom: 5 + 12 * 1.3 / 2,
boxAttrs: {
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 1,
},
labelAttrs: {
'font-family': FONT,
'font-size': 12,
'line-height': LINE_HEIGHT,
'text-anchor': 'middle',
},
},
database: {
padding: {
top: 12,
left: 10,
right: 10,
bottom: 3,
},
arrowBottom: 5 + 12 * 1.3 / 2,
boxRenderer: this.renderDB.bind(this, {
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 1,
'db-z': 5,
}),
labelAttrs: {
'font-family': FONT,
'font-size': 12,
'line-height': LINE_HEIGHT,
'text-anchor': 'middle',
},
},
cross: {
size: 20,
render: svg.crossFactory({
'fill': 'none',
'stroke': '#000000',
'stroke-width': 1,
}),
},
bar: {
height: 4,
render: svg.boxFactory({
'fill': '#000000',
'stroke': '#000000',
'stroke-width': 1,
}),
},
fade: {
width: 5,
height: 6,
extend: 1,
},
none: {
height: 10,
},
},
connect: {
loopbackRadius: 6,
arrow: {
'single': {
width: 5,
height: 10,
render: this.renderArrowHead.bind(this),
attrs: {
'fill': '#000000',
'stroke-width': 0,
'stroke-linejoin': 'miter',
},
},
'double': {
width: 4,
height: 6,
render: this.renderArrowHead.bind(this),
attrs: {
'fill': 'none',
'stroke': '#000000',
'stroke-width': 1,
'stroke-linejoin': 'miter',
},
},
'cross': {
short: 7,
radius: 3,
render: svg.crossFactory({
'fill': 'none',
'stroke': '#000000',
'stroke-width': 1,
}),
},
},
label: {
padding: 6,
margin: {top: 2, bottom: 1},
attrs: {
'font-family': FONT,
'font-size': 8,
'line-height': LINE_HEIGHT,
'text-anchor': 'middle',
},
loopbackAttrs: {
'font-family': FONT,
'font-size': 8,
'line-height': LINE_HEIGHT,
},
},
source: {
radius: 2,
render: svg.circleFactory({
'fill': '#000000',
'stroke': '#000000',
'stroke-width': 1,
}),
},
mask: {
padding: {
top: 0,
left: 3,
right: 3,
bottom: 1,
},
},
},
agentLineAttrs: {
'': {
'fill': 'none',
'stroke': '#000000',
'stroke-width': 1,
},
'red': {
'stroke': '#CC0000',
},
},
blocks: {
'ref': {
margin: {
top: 0,
bottom: 0,
},
boxRenderer: this.renderRef.bind(this, {
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 1.5,
'rx': 2,
'ry': 2,
}),
section: sharedBlockSection,
},
'': {
margin: {
top: 0,
bottom: 0,
},
boxRenderer: svg.boxFactory({
'fill': 'none',
'stroke': '#000000',
'stroke-width': 1.5,
'rx': 2,
'ry': 2,
}),
collapsedBoxRenderer: this.renderRef.bind(this, {
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 1.5,
'rx': 2,
'ry': 2,
}),
section: sharedBlockSection,
sepRenderer: svg.lineFactory({
'stroke': '#000000',
'stroke-width': 1.5,
'stroke-dasharray': '4, 2',
}),
},
},
notes: {
'text': {
margin: {top: 0, left: 2, right: 2, bottom: 0},
padding: {top: 2, left: 2, right: 2, bottom: 2},
overlap: {left: 10, right: 10},
boxRenderer: svg.boxFactory({
'fill': '#FFFFFF',
}),
labelAttrs: NOTE_ATTRS,
},
'note': {
margin: {top: 0, left: 5, right: 5, bottom: 0},
padding: {top: 5, left: 5, right: 10, bottom: 5},
overlap: {left: 10, right: 10},
boxRenderer: svg.noteFactory({
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 1,
}, {
'fill': 'none',
'stroke': '#000000',
'stroke-width': 1,
}),
labelAttrs: NOTE_ATTRS,
},
'state': {
margin: {top: 0, left: 5, right: 5, bottom: 0},
padding: {top: 7, left: 7, right: 7, bottom: 7},
overlap: {left: 10, right: 10},
boxRenderer: svg.boxFactory({
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 1,
'rx': 10,
'ry': 10,
}),
labelAttrs: NOTE_ATTRS,
},
},
dividers: {
'': {
labelAttrs: DIVIDER_LABEL_ATTRS,
padding: {top: 2, left: 5, right: 5, bottom: 2},
extend: 0,
margin: 0,
render: () => ({}),
},
'line': {
labelAttrs: DIVIDER_LABEL_ATTRS,
padding: {top: 2, left: 5, right: 5, bottom: 2},
extend: 10,
margin: 0,
render: this.renderLineDivider.bind(this, {
lineAttrs: {
'stroke': '#000000',
},
}),
},
'delay': {
labelAttrs: DIVIDER_LABEL_ATTRS,
padding: {top: 2, left: 5, right: 5, bottom: 2},
extend: 0,
margin: 0,
render: this.renderDelayDivider.bind(this, {
dotSize: 1,
gapSize: 2,
}),
},
'tear': {
labelAttrs: DIVIDER_LABEL_ATTRS,
padding: {top: 2, left: 5, right: 5, bottom: 2},
extend: 10,
margin: 10,
render: this.renderTearDivider.bind(this, {
fadeBegin: 5,
fadeSize: 10,
zigWidth: 6,
zigHeight: 1,
lineAttrs: {
'stroke': '#000000',
},
}),
},
},
});
this.addConnectLine('solid', {attrs: {
'stroke': '#000000',
'stroke-width': 1,
}});
this.addConnectLine('dash', {attrs: {
'stroke-dasharray': '4, 2',
}});
this.addConnectLine('wave', {
attrs: {
'stroke-linejoin': 'round',
'stroke-linecap': 'round',
},
pattern: new WavePattern(6, 0.5),
});
}
}
class Factory {
constructor() {
this.name = 'basic';
}
build(svg) {
return new BasicTheme(svg);
}
}
/* eslint-disable sort-keys */ // Maybe later
const FONT$1 = 'Helvetica,Arial,Liberation Sans,sans-serif';
const LINE_HEIGHT$1 = 1.3;
const NOTE_ATTRS$1 = {
'font-family': FONT$1,
'font-size': 8,
'line-height': LINE_HEIGHT$1,
};
const DIVIDER_LABEL_ATTRS$1 = {
'font-family': FONT$1,
'font-size': 8,
'line-height': LINE_HEIGHT$1,
'text-anchor': 'middle',
};
class ChunkyTheme extends BaseTheme {
constructor(svg) {
super(svg, {
'font-family': FONT$1,
'font-size': 8,
'line-height': LINE_HEIGHT$1,
});
const sharedBlockSection = {
padding: {
top: 3,
bottom: 4,
},
tag: {
padding: {
top: 2,
left: 5,
right: 5,
bottom: 1,
},
boxRenderer: this.renderTag.bind(this, {
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 2,
'rx': 3,
'ry': 3,
}),
labelAttrs: {
'font-family': FONT$1,
'font-weight': 'bold',
'font-size': 9,
'line-height': LINE_HEIGHT$1,
'text-anchor': 'left',
},
},
label: {
minHeight: 5,
padding: {
top: 2,
left: 5,
right: 3,
bottom: 1,
},
labelAttrs: {
'font-family': FONT$1,
'font-size': 8,
'line-height': LINE_HEIGHT$1,
'text-anchor': 'left',
},
},
};
Object.assign(this, {
titleMargin: 12,
outerMargin: 5,
agentMargin: 8,
actionMargin: 5,
minActionMargin: 5,
agentLineHighlightRadius: 4,
agentCap: {
box: {
padding: {
top: 1,
left: 3,
right: 3,
bottom: 1,
},
arrowBottom: 2 + 14 * 1.3 / 2,
boxAttrs: {
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 3,
'rx': 4,
'ry': 4,
},
labelAttrs: {
'font-family': FONT$1,
'font-weight': 'bold',
'font-size': 14,
'line-height': LINE_HEIGHT$1,
'text-anchor': 'middle',
},
},
database: {
padding: {
top: 4,
left: 3,
right: 3,
bottom: 0,
},
arrowBottom: 2 + 14 * 1.3 / 2,
boxRenderer: this.renderDB.bind(this, {
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 3,
'db-z': 2,
}),
labelAttrs: {
'font-family': FONT$1,
'font-weight': 'bold',
'font-size': 14,
'line-height': LINE_HEIGHT$1,
'text-anchor': 'middle',
},
},
cross: {
size: 20,
render: svg.crossFactory({
'fill': 'none',
'stroke': '#000000',
'stroke-width': 3,
'stroke-linecap': 'round',
}),
},
bar: {
height: 4,
render: svg.boxFactory({
'fill': '#000000',
'stroke': '#000000',
'stroke-width': 3,
'rx': 2,
'ry': 2,
}),
},
fade: {
width: 5,
height: 10,
extend: 1,
},
none: {
height: 10,
},
},
connect: {
loopbackRadius: 8,
arrow: {
'single': {
width: 10,
height: 12,
render: this.renderArrowHead.bind(this),
attrs: {
'fill': '#000000',
'stroke': '#000000',
'stroke-width': 3,
'stroke-linejoin': 'round',
},
},
'double': {
width: 10,
height: 12,
render: this.renderArrowHead.bind(this),
attrs: {
'fill': 'none',
'stroke': '#000000',
'stroke-width': 3,
'stroke-linejoin': 'round',
'stroke-linecap': 'round',
},
},
'cross': {
short: 10,
radius: 5,
render: svg.crossFactory({
'fill': 'none',
'stroke': '#000000',
'stroke-width': 3,
'stroke-linejoin': 'round',
'stroke-linecap': 'round',
}),
},
},
label: {
padding: 7,
margin: {top: 2, bottom: 3},
attrs: {
'font-family': FONT$1,
'font-size': 8,
'line-height': LINE_HEIGHT$1,
'text-anchor': 'middle',
},
loopbackAttrs: {
'font-family': FONT$1,
'font-size': 8,
'line-height': LINE_HEIGHT$1,
},
},
source: {
radius: 5,
render: svg.circleFactory({
'fill': '#000000',
'stroke': '#000000',
'stroke-width': 3,
}),
},
mask: {
padding: {
top: 1,
left: 5,
right: 5,
bottom: 3,
},
},
},
agentLineAttrs: {
'': {
'fill': 'none',
'stroke': '#000000',
'stroke-width': 3,
},
'red': {
'stroke': '#DD0000',
},
},
blocks: {
'ref': {
margin: {
top: 0,
bottom: 0,
},
boxRenderer: this.renderRef.bind(this, {
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 4,
'rx': 5,
'ry': 5,
}),
section: sharedBlockSection,
},
'': {
margin: {
top: 0,
bottom: 0,
},
boxRenderer: svg.boxFactory({
'fill': 'none',
'stroke': '#000000',
'stroke-width': 4,
'rx': 5,
'ry': 5,
}),
collapsedBoxRenderer: this.renderRef.bind(this, {
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 4,
'rx': 5,
'ry': 5,
}),
section: sharedBlockSection,
sepRenderer: svg.lineFactory({
'stroke': '#000000',
'stroke-width': 2,
'stroke-dasharray': '5, 3',
}),
},
},
notes: {
'text': {
margin: {top: 0, left: 2, right: 2, bottom: 0},
padding: {top: 2, left: 2, right: 2, bottom: 2},
overlap: {left: 10, right: 10},
boxRenderer: svg.boxFactory({
'fill': '#FFFFFF',
}),
labelAttrs: NOTE_ATTRS$1,
},
'note': {
margin: {top: 0, left: 5, right: 5, bottom: 0},
padding: {top: 3, left: 3, right: 10, bottom: 3},
overlap: {left: 10, right: 10},
boxRenderer: svg.noteFactory({
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 2,
'stroke-linejoin': 'round',
}, {
'fill': 'none',
'stroke': '#000000',
'stroke-width': 1,
}),
labelAttrs: NOTE_ATTRS$1,
},
'state': {
margin: {top: 0, left: 5, right: 5, bottom: 0},
padding: {top: 5, left: 7, right: 7, bottom: 5},
overlap: {left: 10, right: 10},
boxRenderer: svg.boxFactory({
'fill': '#FFFFFF',
'stroke': '#000000',
'stroke-width': 3,
'rx': 10,
'ry': 10,
}),
labelAttrs: NOTE_ATTRS$1,
},
},
dividers: {
'': {
labelAttrs: DIVIDER_LABEL_ATTRS$1,
padding: {top: 2, left: 5, right: 5, bottom: 2},
extend: 0,
margin: 0,
render: () => ({}),
},
'line': {
labelAttrs: DIVIDER_LABEL_ATTRS$1,
padding: {top: 2, left: 5, right: 5, bottom: 2},
extend: 10,
margin: 0,
render: this.renderLineDivider.bind(this, {
lineAttrs: {
'stroke': '#000000',
'stroke-width': 2,
'stroke-linecap': 'round',
},
}),
},
'delay': {
labelAttrs: DIVIDER_LABEL_ATTRS$1,
padding: {top: 2, left: 5, right: 5, bottom: 2},
extend: 0,
margin: 0,
render: this.renderDelayDivider.bind(this, {
dotSize: 3,
gapSize: 3,
}),
},
'tear': {
labelAttrs: DIVIDER_LABEL_ATTRS$1,
padding: {top: 2, left: 5, right: 5, bottom: 2},
extend: 10,
margin: 10,
render: this.renderTearDivider.bind(this, {
fadeBegin: 5,
fadeSize: 10,
zigWidth: 6,
zigHeight: 1,
lineAttrs: {
'stroke': '#000000',
'stroke-width': 2,
'stroke-linejoin': 'round',
},
}),
},
},
});
this.addConnectLine('solid', {attrs: {
'stroke': '#000000',
'stroke-width': 3,
}});
this.addConnectLine('dash', {attrs: {
'stroke-dasharray': '10, 4',
}});
this.addConnectLine('wave', {
attrs: {
'stroke-linejoin': 'round',
'stroke-linecap': 'round',
},
pattern: new WavePattern(10, 1),
});
}
getTitleAttrs() {
return Object.assign(super.getTitleAttrs(), {
'font-weight': 'bolder',
});
}
}
class Factory$1 {
constructor() {
this.name = 'chunky';
}
build(svg) {
return new ChunkyTheme(svg);
}
}
class EventObject {
constructor() {
this.listeners = new Map();
this.forwards = new Set();
}
addEventListener(type, callback) {
const l = this.listeners.get(type);
if(l) {
l.push(callback);
} else {
this.listeners.set(type, [callback]);
}
}
removeEventListener(type, fn) {
const l = this.listeners.get(type);
if(!l) {
return;
}
const i = l.indexOf(fn);
if(i !== -1) {
l.splice(i, 1);
}
}
on(type, fn) {
this.addEventListener(type, fn);
return this;
}
off(type, fn) {
this.removeEventListener(type, fn);
return this;
}
countEventListeners(type) {
return (this.listeners.get(type) || []).length;
}
removeAllEventListeners(type) {
if(type) {
this.listeners.delete(type);
} else {
this.listeners.clear();
}
}
addEventForwarding(target) {
this.forwards.add(target);
}
removeEventForwarding(target) {
this.forwards.delete(target);
}
removeAllEventForwardings() {
this.forwards.clear();
}
trigger(type, params = []) {
(this.listeners.get(type) || []).forEach(
(listener) => listener(...params)
);
this.forwards.forEach((fwd) => fwd.trigger(type, params));
}
}
const nodejs = (typeof window === 'undefined');
// Thanks, https://stackoverflow.com/a/23522755/1180785
const safari = (
!nodejs &&
(/^((?!chrome|android).)*safari/i).test(window.navigator.userAgent)
);
// Thanks, https://stackoverflow.com/a/9851769/1180785
const firefox = (
!nodejs &&
typeof window.InstallTrigger !== 'undefined'
);
class Exporter {
constructor() {
this.latestSVG = null;
this.latestInternalSVG = null;
this.canvas = null;
this.context = null;
this.indexPNG = 0;
this.latestPNGIndex = 0;
this.latestPNG = null;
}
getSVGContent(renderer) {
let code = renderer.dom().outerHTML;
/*
* Firefox fails to render SVGs as
unless they have size
* attributes on the