Improve editor and library pages on iOS
This commit is contained in:
parent
80175c65f5
commit
135f0b1e0d
|
@ -14,6 +14,9 @@
|
|||
img-src 'self' blob:;
|
||||
form-action 'none';
|
||||
">
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, minimal-ui">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
|
||||
<title>Sequence Diagram</title>
|
||||
<link rel="icon" href="web/resources/favicon.png">
|
||||
|
@ -89,8 +92,8 @@
|
|||
<p class="loadmsg">Loading…</p>
|
||||
<noscript><p class="noscript">This tool requires Javascript!<p></noscript>
|
||||
<nav>
|
||||
<a href="library.htm" target="_blank">Library</a>
|
||||
<a href="https://github.com/davidje13/SequenceDiagram" target="_blank">GitHub</a>
|
||||
<a href="library.htm" target="_blank" data-touch="API">Library</a>
|
||||
<a href="https://github.com/davidje13/SequenceDiagram" target="_blank" data-touch="Git">GitHub</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -6984,6 +6984,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
DOMWrapper.WrappedElement = WrappedElement;
|
||||
|
||||
function merge(state, newState) {
|
||||
for(const k in state) {
|
||||
if(Object.prototype.hasOwnProperty.call(state, k)) {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -6984,6 +6984,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
DOMWrapper.WrappedElement = WrappedElement;
|
||||
|
||||
function merge(state, newState) {
|
||||
for(const k in state) {
|
||||
if(Object.prototype.hasOwnProperty.call(state, k)) {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
img-src 'self';
|
||||
form-action 'none';
|
||||
">
|
||||
<meta name="viewport" content="initial-scale=1.0, minimum-scale=1.0">
|
||||
|
||||
<title>Sequence Diagram Library</title>
|
||||
<link rel="icon" href="web/resources/favicon.png">
|
||||
|
|
|
@ -204,3 +204,5 @@ export default class DOMWrapper {
|
|||
return this.document.createTextNode(content);
|
||||
}
|
||||
}
|
||||
|
||||
DOMWrapper.WrappedElement = WrappedElement;
|
||||
|
|
|
@ -550,6 +550,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
DOMWrapper.WrappedElement = WrappedElement;
|
||||
|
||||
/* eslint-disable max-lines */
|
||||
|
||||
const DELAY_AGENTCHANGE = 500;
|
||||
|
@ -636,14 +638,57 @@
|
|||
return opts + uri + '.svg';
|
||||
}
|
||||
|
||||
function makeSplit(require, nodes, options) {
|
||||
function makeSplit(nodes, options) {
|
||||
const filteredNodes = [];
|
||||
const filteredOpts = {
|
||||
direction: options.direction,
|
||||
minSize: [],
|
||||
sizes: [],
|
||||
snapOffset: options.snapOffset,
|
||||
};
|
||||
|
||||
let total = 0;
|
||||
for(let i = 0; i < nodes.length; ++ i) {
|
||||
if(nodes[i]) {
|
||||
filteredNodes.push(nodes[i]);
|
||||
filteredOpts.minSize.push(options.minSize[i]);
|
||||
filteredOpts.sizes.push(options.sizes[i]);
|
||||
total += options.sizes[i];
|
||||
}
|
||||
}
|
||||
for(let i = 0; i < filteredNodes.length; ++ i) {
|
||||
filteredOpts.minSize[i] *= 100 / total;
|
||||
filteredOpts.sizes[i] *= 100 / total;
|
||||
|
||||
const percent = filteredOpts.sizes[i] + '%';
|
||||
if(filteredOpts.direction === 'vertical') {
|
||||
nodes[i].styles({
|
||||
boxSizing: 'border-box',
|
||||
height: percent,
|
||||
width: '100%',
|
||||
});
|
||||
} else {
|
||||
nodes[i].styles({
|
||||
boxSizing: 'border-box',
|
||||
display: 'inline-block',
|
||||
height: '100%',
|
||||
verticalAlign: 'top', // Safari fix
|
||||
width: percent,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(filteredNodes.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load on demand for progressive enhancement
|
||||
// (failure to load external module will not block functionality)
|
||||
require(['split'], (Split) => {
|
||||
options.require(['split'], (Split) => {
|
||||
// Patches for:
|
||||
// https://github.com/nathancahill/Split.js/issues/97
|
||||
// https://github.com/nathancahill/Split.js/issues/111
|
||||
const parent = nodes[0].parentNode;
|
||||
const parent = nodes[0].element.parentNode;
|
||||
const oldAEL = parent.addEventListener;
|
||||
const oldREL = parent.removeEventListener;
|
||||
parent.addEventListener = (event, callback) => {
|
||||
|
@ -662,9 +707,13 @@
|
|||
};
|
||||
|
||||
let oldCursor = null;
|
||||
const resolvedOptions = Object.assign({
|
||||
cursor: (options.direction === 'vertical') ?
|
||||
'row-resize' : 'col-resize',
|
||||
const cursor = (filteredOpts.direction === 'vertical') ?
|
||||
'row-resize' : 'col-resize';
|
||||
|
||||
return new Split(
|
||||
filteredNodes.map((node) => node.element),
|
||||
Object.assign({
|
||||
cursor,
|
||||
direction: 'vertical',
|
||||
gutterSize: 0,
|
||||
onDragEnd: () => {
|
||||
|
@ -673,14 +722,19 @@
|
|||
},
|
||||
onDragStart: () => {
|
||||
oldCursor = document.body.style.cursor;
|
||||
document.body.style.cursor = resolvedOptions.cursor;
|
||||
document.body.style.cursor = cursor;
|
||||
},
|
||||
}, options);
|
||||
|
||||
return new Split(nodes, resolvedOptions);
|
||||
}, filteredOpts)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
DOMWrapper.WrappedElement.prototype.split = function(nodes, options) {
|
||||
this.add(nodes);
|
||||
makeSplit(nodes, options);
|
||||
return this;
|
||||
};
|
||||
|
||||
function hasDroppedFile(event, mime) {
|
||||
if(!event.dataTransfer.items && event.dataTransfer.files.length === 0) {
|
||||
// Work around Safari not supporting dataTransfer.items
|
||||
|
@ -714,6 +768,35 @@
|
|||
});
|
||||
}
|
||||
|
||||
DOMWrapper.WrappedElement.prototype.fastClick = function() {
|
||||
const pt = {x: -1, y: 0};
|
||||
return this
|
||||
.on('touchstart', (e) => {
|
||||
const [touch] = e.touches;
|
||||
pt.x = touch.pageX;
|
||||
pt.y = touch.pageY;
|
||||
})
|
||||
.on('touchend', (e) => {
|
||||
if(
|
||||
pt.x === -1 ||
|
||||
e.touches.length !== 0 ||
|
||||
e.changedTouches.length !== 1
|
||||
) {
|
||||
pt.x = -1;
|
||||
return;
|
||||
}
|
||||
const [touch] = e.changedTouches;
|
||||
if(
|
||||
Math.abs(pt.x - touch.pageX) < 10 &&
|
||||
Math.abs(pt.y - touch.pageY) < 10
|
||||
) {
|
||||
e.preventDefault();
|
||||
e.target.click();
|
||||
}
|
||||
pt.x = -1;
|
||||
});
|
||||
};
|
||||
|
||||
class Interface {
|
||||
constructor({
|
||||
sequenceDiagram,
|
||||
|
@ -722,6 +805,7 @@
|
|||
library = [],
|
||||
links = [],
|
||||
require = null,
|
||||
touchUI = false,
|
||||
}) {
|
||||
this.diagram = sequenceDiagram;
|
||||
this.defaultCode = defaultCode;
|
||||
|
@ -730,6 +814,7 @@
|
|||
this.links = links;
|
||||
this.minScale = 1.5;
|
||||
this.require = require || (() => null);
|
||||
this.touchUI = touchUI;
|
||||
|
||||
this.debounced = null;
|
||||
this.latestSeq = null;
|
||||
|
@ -743,7 +828,6 @@
|
|||
this._downloadPNGClick = this._downloadPNGClick.bind(this);
|
||||
this._downloadPNGFocus = this._downloadPNGFocus.bind(this);
|
||||
this._downloadURLClick = this._downloadURLClick.bind(this);
|
||||
this._showDropStyle = this._showDropStyle.bind(this);
|
||||
this._hideDropStyle = this._hideDropStyle.bind(this);
|
||||
|
||||
this.diagram
|
||||
|
@ -808,14 +892,21 @@
|
|||
});
|
||||
|
||||
const copy = this.dom.el('button').setClass('copy')
|
||||
.add('\uD83D\uDCCB')
|
||||
.attr('title', 'Copy to clipboard')
|
||||
.fastClick()
|
||||
.on('click', () => {
|
||||
if(this.touchUI) {
|
||||
this.urlOutput.styles({display: 'block'});
|
||||
}
|
||||
this.urlOutput
|
||||
.focus()
|
||||
.select(0, this.urlOutput.element.value.length)
|
||||
.element.ownerDocument.execCommand('copy');
|
||||
copy.focus();
|
||||
this.container.delClass('keyinput');
|
||||
if(this.touchUI) {
|
||||
this.urlOutput.styles({display: 'none'});
|
||||
}
|
||||
copied.styles({
|
||||
'display': 'block',
|
||||
'opacity': 1,
|
||||
|
@ -870,7 +961,7 @@
|
|||
copied
|
||||
);
|
||||
|
||||
this.urlBuilder = this.dom.el('div').setClass('urlbuilder')
|
||||
const urlBuilder = this.dom.el('div').setClass('urlbuilder')
|
||||
.styles({'display': 'none'})
|
||||
.add(
|
||||
this.dom.el('div').setClass('message')
|
||||
|
@ -887,17 +978,17 @@
|
|||
path = relativePath;
|
||||
}
|
||||
this.renderService = new URL(path, window.location.href).href;
|
||||
this.urlBuilder.empty().add(urlOpts);
|
||||
urlBuilder.empty().add(urlOpts);
|
||||
this._refreshURL();
|
||||
})
|
||||
.catch(() => {
|
||||
this.urlBuilder.empty().add(
|
||||
urlBuilder.empty().add(
|
||||
this.dom.el('div').setClass('message')
|
||||
.add('No online rendering service available.')
|
||||
);
|
||||
});
|
||||
|
||||
return this.urlBuilder;
|
||||
return urlBuilder;
|
||||
}
|
||||
|
||||
_refreshURL() {
|
||||
|
@ -913,14 +1004,24 @@
|
|||
return;
|
||||
}
|
||||
this.builderVisible = true;
|
||||
if(this.touchUI) {
|
||||
this.urlBuilder.styles({
|
||||
'bottom': '-210px',
|
||||
'display': 'block',
|
||||
});
|
||||
} else {
|
||||
this.urlBuilder.styles({
|
||||
'display': 'block',
|
||||
'height': '0px',
|
||||
'padding': '0px',
|
||||
'width': this.optsHold.element.clientWidth + 'px',
|
||||
});
|
||||
}
|
||||
clearTimeout(this.builderTm);
|
||||
this.builderTm = setTimeout(() => {
|
||||
if(this.touchUI) {
|
||||
this.urlBuilder.styles({'bottom': 0});
|
||||
} else {
|
||||
this.urlBuilder.styles({
|
||||
'height': '150px',
|
||||
'padding': '10px',
|
||||
|
@ -929,6 +1030,7 @@
|
|||
this.optsHold.styles({
|
||||
'box-shadow': '10px 10px 25px 12px rgba(0,0,0,0.3)',
|
||||
});
|
||||
}
|
||||
}, 0);
|
||||
|
||||
this._refreshURL();
|
||||
|
@ -939,6 +1041,11 @@
|
|||
return;
|
||||
}
|
||||
this.builderVisible = false;
|
||||
if(this.touchUI) {
|
||||
this.urlBuilder.styles({
|
||||
'bottom': (-this.urlBuilder.element.clientHeight - 60) + 'px',
|
||||
});
|
||||
} else {
|
||||
this.urlBuilder.styles({
|
||||
'height': '0px',
|
||||
'padding': '0px',
|
||||
|
@ -947,6 +1054,8 @@
|
|||
this.optsHold.styles({
|
||||
'box-shadow': 'none',
|
||||
});
|
||||
}
|
||||
this.container.delClass('keyinput');
|
||||
clearTimeout(this.builderTm);
|
||||
this.builderTm = setTimeout(() => {
|
||||
this.urlBuilder.styles({'display': 'none'});
|
||||
|
@ -955,12 +1064,14 @@
|
|||
|
||||
buildOptionsDownloads() {
|
||||
this.downloadPNG = this.dom.el('a')
|
||||
.text('Download PNG')
|
||||
.text('Export PNG')
|
||||
.attrs({
|
||||
'download': 'SequenceDiagram.png',
|
||||
'href': '#',
|
||||
})
|
||||
.on(['focus', 'mouseover', 'mousedown'], this._downloadPNGFocus)
|
||||
// Exploit delay between touchend and click on mobile
|
||||
.on('touchend', this._downloadPNGFocus)
|
||||
.on('click', this._downloadPNGClick);
|
||||
|
||||
this.downloadSVG = this.dom.el('a')
|
||||
|
@ -969,18 +1080,22 @@
|
|||
'download': 'SequenceDiagram.svg',
|
||||
'href': '#',
|
||||
})
|
||||
.fastClick()
|
||||
.on('click', this._downloadSVGClick);
|
||||
|
||||
this.downloadURL = this.dom.el('a')
|
||||
.text('URL')
|
||||
.attrs({'href': '#'})
|
||||
.fastClick()
|
||||
.on('click', this._downloadURLClick);
|
||||
|
||||
this.urlBuilder = this.buildURLBuilder();
|
||||
|
||||
this.optsHold = this.dom.el('div').setClass('options downloads').add(
|
||||
this.downloadPNG,
|
||||
this.downloadSVG,
|
||||
this.downloadURL,
|
||||
this.buildURLBuilder()
|
||||
this.urlBuilder
|
||||
);
|
||||
|
||||
return this.optsHold;
|
||||
|
@ -994,6 +1109,7 @@
|
|||
const hold = this.dom.el('div')
|
||||
.setClass('library-item')
|
||||
.add(holdInner)
|
||||
.fastClick()
|
||||
.on('click', this.addCodeBlock.bind(this, lib.code))
|
||||
.attach(container);
|
||||
|
||||
|
@ -1017,10 +1133,33 @@
|
|||
return container;
|
||||
}
|
||||
|
||||
buildCodePane() {
|
||||
this.code = this.dom.el('textarea')
|
||||
.setClass('editor-simple')
|
||||
.val(this.loadCode() || this.defaultCode)
|
||||
.on('input', () => this.update(false));
|
||||
|
||||
return this.dom.el('div').setClass('pane-code')
|
||||
.add(this.code);
|
||||
}
|
||||
|
||||
buildLibPane() {
|
||||
if(this.library.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.dom.el('div').setClass('pane-library')
|
||||
.add(this.dom.el('div').setClass('pane-library-scroller')
|
||||
.add(this.buildLibrary(
|
||||
this.dom.el('div').setClass('pane-library-inner')
|
||||
)));
|
||||
}
|
||||
|
||||
buildViewPane() {
|
||||
this.viewPaneInner = this.dom.el('div').setClass('pane-view-inner')
|
||||
.add(this.diagram.dom())
|
||||
.on('click', () => this._hideURLBuilder());
|
||||
.on('touchstart', () => this._hideURLBuilder())
|
||||
.on('mousedown', () => this._hideURLBuilder());
|
||||
|
||||
this.errorMsg = this.dom.el('div').setClass('msg-error');
|
||||
|
||||
|
@ -1032,53 +1171,10 @@
|
|||
);
|
||||
}
|
||||
|
||||
buildLeftPanes() {
|
||||
const container = this.dom.el('div').setClass('pane-side');
|
||||
|
||||
this.code = this.dom.el('textarea')
|
||||
.setClass('editor-simple')
|
||||
.val(this.loadCode() || this.defaultCode)
|
||||
.on('input', () => this.update(false));
|
||||
|
||||
const codePane = this.dom.el('div').setClass('pane-code')
|
||||
.add(this.code)
|
||||
.attach(container);
|
||||
|
||||
if(this.library.length > 0) {
|
||||
const libPane = this.dom.el('div').setClass('pane-library')
|
||||
.add(this.dom.el('div').setClass('pane-library-scroller')
|
||||
.add(this.buildLibrary(
|
||||
this.dom.el('div').setClass('pane-library-inner')
|
||||
)))
|
||||
.attach(container);
|
||||
|
||||
makeSplit(this.require, [codePane.element, libPane.element], {
|
||||
direction: 'vertical',
|
||||
minSize: [100, 5],
|
||||
sizes: [70, 30],
|
||||
snapOffset: 5,
|
||||
});
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
build(container) {
|
||||
this.dom = new DOMWrapper(container.ownerDocument);
|
||||
const lPane = this.buildLeftPanes();
|
||||
const viewPane = this.buildViewPane();
|
||||
|
||||
this.container = this.dom.wrap(container)
|
||||
.add(this.dom.el('div').setClass('pane-hold')
|
||||
.add(
|
||||
lPane,
|
||||
viewPane,
|
||||
this.dom.el('div').setClass('options links')
|
||||
.add(this.links.map((link) => this.dom.el('a')
|
||||
.attrs({'href': link.href, 'target': '_blank'})
|
||||
.text(link.label))),
|
||||
this.buildOptionsDownloads()
|
||||
))
|
||||
.on('dragover', (event) => {
|
||||
event.preventDefault();
|
||||
if(hasDroppedFile(event, 'image/svg+xml')) {
|
||||
|
@ -1097,14 +1193,66 @@
|
|||
if(file) {
|
||||
this.loadFile(file);
|
||||
}
|
||||
});
|
||||
})
|
||||
.on('focusin', () => this.container.addClass('keyinput'))
|
||||
.on('focusout', () => this.container.delClass('keyinput'));
|
||||
|
||||
makeSplit(this.require, [lPane.element, viewPane.element], {
|
||||
const codePane = this.buildCodePane();
|
||||
const libPane = this.buildLibPane();
|
||||
const viewPane = this.buildViewPane();
|
||||
|
||||
const links = this.links.map((link) => this.dom.el('a')
|
||||
.attrs({'href': link.href, 'target': '_blank'})
|
||||
.text(this.touchUI ? link.touchLabel : link.label));
|
||||
|
||||
if(this.touchUI) {
|
||||
this.buildOptionsDownloads();
|
||||
this.container
|
||||
.addClass('touch')
|
||||
.add(
|
||||
this.dom.el('div').setClass('pane-hold')
|
||||
.split([viewPane, codePane], {
|
||||
direction: 'vertical',
|
||||
minSize: [10, 10],
|
||||
require: this.require,
|
||||
sizes: [80, 20],
|
||||
snapOffset: 20,
|
||||
}),
|
||||
libPane.styles({'display': 'none', 'top': '100%'}),
|
||||
this.urlBuilder,
|
||||
this.dom.el('div').setClass('optbar')
|
||||
.add(
|
||||
...links,
|
||||
this.downloadPNG.text('PNG'),
|
||||
this.downloadSVG.text('SVG'),
|
||||
this.downloadURL.text('URL')
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this.container
|
||||
.add(
|
||||
this.dom.el('div').setClass('pane-hold')
|
||||
.split([
|
||||
this.dom.el('div').setClass('pane-side')
|
||||
.split([codePane, libPane], {
|
||||
direction: 'vertical',
|
||||
minSize: [100, 5],
|
||||
require: this.require,
|
||||
sizes: [70, 30],
|
||||
snapOffset: 5,
|
||||
}),
|
||||
viewPane,
|
||||
], {
|
||||
direction: 'horizontal',
|
||||
minSize: [10, 10],
|
||||
require: this.require,
|
||||
sizes: [30, 70],
|
||||
snapOffset: 70,
|
||||
});
|
||||
}),
|
||||
this.dom.el('div').setClass('options links').add(links),
|
||||
this.buildOptionsDownloads()
|
||||
);
|
||||
}
|
||||
|
||||
if(typeof window !== 'undefined') {
|
||||
window.addEventListener('keydown', (e) => {
|
||||
|
@ -1389,6 +1537,8 @@
|
|||
});
|
||||
});
|
||||
|
||||
code.on('focus', () => this._hideURLBuilder());
|
||||
|
||||
code.on('cursorActivity', () => {
|
||||
const from = code.getCursor('from').line;
|
||||
const to = code.getCursor('to').line;
|
||||
|
@ -1468,9 +1618,11 @@
|
|||
const linkElements = nav.getElementsByTagName('a');
|
||||
const links = [];
|
||||
for(let i = 0; i < linkElements.length; ++ i) {
|
||||
const element = linkElements[i];
|
||||
links.push({
|
||||
href: linkElements[i].getAttribute('href'),
|
||||
label: linkElements[i].textContent,
|
||||
href: element.getAttribute('href'),
|
||||
label: element.textContent,
|
||||
touchLabel: element.dataset.touch,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1481,6 +1633,7 @@
|
|||
localStorage: 'src',
|
||||
require,
|
||||
sequenceDiagram: new SequenceDiagram(),
|
||||
touchUI: ('ontouchstart' in window),
|
||||
});
|
||||
loader.parentNode.removeChild(loader);
|
||||
ui.build(window.document.body);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -28,9 +28,11 @@ window.addEventListener('load', () => {
|
|||
const linkElements = nav.getElementsByTagName('a');
|
||||
const links = [];
|
||||
for(let i = 0; i < linkElements.length; ++ i) {
|
||||
const element = linkElements[i];
|
||||
links.push({
|
||||
href: linkElements[i].getAttribute('href'),
|
||||
label: linkElements[i].textContent,
|
||||
href: element.getAttribute('href'),
|
||||
label: element.textContent,
|
||||
touchLabel: element.dataset.touch,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -41,6 +43,7 @@ window.addEventListener('load', () => {
|
|||
localStorage: 'src',
|
||||
require,
|
||||
sequenceDiagram: new SequenceDiagram(),
|
||||
touchUI: ('ontouchstart' in window),
|
||||
});
|
||||
loader.parentNode.removeChild(loader);
|
||||
ui.build(window.document.body);
|
||||
|
|
|
@ -86,14 +86,57 @@ function makeURL(code, {height, width, zoom}) {
|
|||
return opts + uri + '.svg';
|
||||
}
|
||||
|
||||
function makeSplit(require, nodes, options) {
|
||||
function makeSplit(nodes, options) {
|
||||
const filteredNodes = [];
|
||||
const filteredOpts = {
|
||||
direction: options.direction,
|
||||
minSize: [],
|
||||
sizes: [],
|
||||
snapOffset: options.snapOffset,
|
||||
};
|
||||
|
||||
let total = 0;
|
||||
for(let i = 0; i < nodes.length; ++ i) {
|
||||
if(nodes[i]) {
|
||||
filteredNodes.push(nodes[i]);
|
||||
filteredOpts.minSize.push(options.minSize[i]);
|
||||
filteredOpts.sizes.push(options.sizes[i]);
|
||||
total += options.sizes[i];
|
||||
}
|
||||
}
|
||||
for(let i = 0; i < filteredNodes.length; ++ i) {
|
||||
filteredOpts.minSize[i] *= 100 / total;
|
||||
filteredOpts.sizes[i] *= 100 / total;
|
||||
|
||||
const percent = filteredOpts.sizes[i] + '%';
|
||||
if(filteredOpts.direction === 'vertical') {
|
||||
nodes[i].styles({
|
||||
boxSizing: 'border-box',
|
||||
height: percent,
|
||||
width: '100%',
|
||||
});
|
||||
} else {
|
||||
nodes[i].styles({
|
||||
boxSizing: 'border-box',
|
||||
display: 'inline-block',
|
||||
height: '100%',
|
||||
verticalAlign: 'top', // Safari fix
|
||||
width: percent,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(filteredNodes.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load on demand for progressive enhancement
|
||||
// (failure to load external module will not block functionality)
|
||||
require(['split'], (Split) => {
|
||||
options.require(['split'], (Split) => {
|
||||
// Patches for:
|
||||
// https://github.com/nathancahill/Split.js/issues/97
|
||||
// https://github.com/nathancahill/Split.js/issues/111
|
||||
const parent = nodes[0].parentNode;
|
||||
const parent = nodes[0].element.parentNode;
|
||||
const oldAEL = parent.addEventListener;
|
||||
const oldREL = parent.removeEventListener;
|
||||
parent.addEventListener = (event, callback) => {
|
||||
|
@ -112,9 +155,13 @@ function makeSplit(require, nodes, options) {
|
|||
};
|
||||
|
||||
let oldCursor = null;
|
||||
const resolvedOptions = Object.assign({
|
||||
cursor: (options.direction === 'vertical') ?
|
||||
'row-resize' : 'col-resize',
|
||||
const cursor = (filteredOpts.direction === 'vertical') ?
|
||||
'row-resize' : 'col-resize';
|
||||
|
||||
return new Split(
|
||||
filteredNodes.map((node) => node.element),
|
||||
Object.assign({
|
||||
cursor,
|
||||
direction: 'vertical',
|
||||
gutterSize: 0,
|
||||
onDragEnd: () => {
|
||||
|
@ -123,14 +170,19 @@ function makeSplit(require, nodes, options) {
|
|||
},
|
||||
onDragStart: () => {
|
||||
oldCursor = document.body.style.cursor;
|
||||
document.body.style.cursor = resolvedOptions.cursor;
|
||||
document.body.style.cursor = cursor;
|
||||
},
|
||||
}, options);
|
||||
|
||||
return new Split(nodes, resolvedOptions);
|
||||
}, filteredOpts)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
DOMWrapper.WrappedElement.prototype.split = function(nodes, options) {
|
||||
this.add(nodes);
|
||||
makeSplit(nodes, options);
|
||||
return this;
|
||||
};
|
||||
|
||||
function hasDroppedFile(event, mime) {
|
||||
if(!event.dataTransfer.items && event.dataTransfer.files.length === 0) {
|
||||
// Work around Safari not supporting dataTransfer.items
|
||||
|
@ -164,6 +216,35 @@ function getFileContent(file) {
|
|||
});
|
||||
}
|
||||
|
||||
DOMWrapper.WrappedElement.prototype.fastClick = function() {
|
||||
const pt = {x: -1, y: 0};
|
||||
return this
|
||||
.on('touchstart', (e) => {
|
||||
const [touch] = e.touches;
|
||||
pt.x = touch.pageX;
|
||||
pt.y = touch.pageY;
|
||||
})
|
||||
.on('touchend', (e) => {
|
||||
if(
|
||||
pt.x === -1 ||
|
||||
e.touches.length !== 0 ||
|
||||
e.changedTouches.length !== 1
|
||||
) {
|
||||
pt.x = -1;
|
||||
return;
|
||||
}
|
||||
const [touch] = e.changedTouches;
|
||||
if(
|
||||
Math.abs(pt.x - touch.pageX) < 10 &&
|
||||
Math.abs(pt.y - touch.pageY) < 10
|
||||
) {
|
||||
e.preventDefault();
|
||||
e.target.click();
|
||||
}
|
||||
pt.x = -1;
|
||||
});
|
||||
};
|
||||
|
||||
export default class Interface {
|
||||
constructor({
|
||||
sequenceDiagram,
|
||||
|
@ -172,6 +253,7 @@ export default class Interface {
|
|||
library = [],
|
||||
links = [],
|
||||
require = null,
|
||||
touchUI = false,
|
||||
}) {
|
||||
this.diagram = sequenceDiagram;
|
||||
this.defaultCode = defaultCode;
|
||||
|
@ -180,6 +262,7 @@ export default class Interface {
|
|||
this.links = links;
|
||||
this.minScale = 1.5;
|
||||
this.require = require || (() => null);
|
||||
this.touchUI = touchUI;
|
||||
|
||||
this.debounced = null;
|
||||
this.latestSeq = null;
|
||||
|
@ -193,7 +276,6 @@ export default class Interface {
|
|||
this._downloadPNGClick = this._downloadPNGClick.bind(this);
|
||||
this._downloadPNGFocus = this._downloadPNGFocus.bind(this);
|
||||
this._downloadURLClick = this._downloadURLClick.bind(this);
|
||||
this._showDropStyle = this._showDropStyle.bind(this);
|
||||
this._hideDropStyle = this._hideDropStyle.bind(this);
|
||||
|
||||
this.diagram
|
||||
|
@ -258,14 +340,21 @@ export default class Interface {
|
|||
});
|
||||
|
||||
const copy = this.dom.el('button').setClass('copy')
|
||||
.add('\uD83D\uDCCB')
|
||||
.attr('title', 'Copy to clipboard')
|
||||
.fastClick()
|
||||
.on('click', () => {
|
||||
if(this.touchUI) {
|
||||
this.urlOutput.styles({display: 'block'});
|
||||
}
|
||||
this.urlOutput
|
||||
.focus()
|
||||
.select(0, this.urlOutput.element.value.length)
|
||||
.element.ownerDocument.execCommand('copy');
|
||||
copy.focus();
|
||||
this.container.delClass('keyinput');
|
||||
if(this.touchUI) {
|
||||
this.urlOutput.styles({display: 'none'});
|
||||
}
|
||||
copied.styles({
|
||||
'display': 'block',
|
||||
'opacity': 1,
|
||||
|
@ -320,7 +409,7 @@ export default class Interface {
|
|||
copied
|
||||
);
|
||||
|
||||
this.urlBuilder = this.dom.el('div').setClass('urlbuilder')
|
||||
const urlBuilder = this.dom.el('div').setClass('urlbuilder')
|
||||
.styles({'display': 'none'})
|
||||
.add(
|
||||
this.dom.el('div').setClass('message')
|
||||
|
@ -337,17 +426,17 @@ export default class Interface {
|
|||
path = relativePath;
|
||||
}
|
||||
this.renderService = new URL(path, window.location.href).href;
|
||||
this.urlBuilder.empty().add(urlOpts);
|
||||
urlBuilder.empty().add(urlOpts);
|
||||
this._refreshURL();
|
||||
})
|
||||
.catch(() => {
|
||||
this.urlBuilder.empty().add(
|
||||
urlBuilder.empty().add(
|
||||
this.dom.el('div').setClass('message')
|
||||
.add('No online rendering service available.')
|
||||
);
|
||||
});
|
||||
|
||||
return this.urlBuilder;
|
||||
return urlBuilder;
|
||||
}
|
||||
|
||||
_refreshURL() {
|
||||
|
@ -363,14 +452,24 @@ export default class Interface {
|
|||
return;
|
||||
}
|
||||
this.builderVisible = true;
|
||||
if(this.touchUI) {
|
||||
this.urlBuilder.styles({
|
||||
'bottom': '-210px',
|
||||
'display': 'block',
|
||||
});
|
||||
} else {
|
||||
this.urlBuilder.styles({
|
||||
'display': 'block',
|
||||
'height': '0px',
|
||||
'padding': '0px',
|
||||
'width': this.optsHold.element.clientWidth + 'px',
|
||||
});
|
||||
}
|
||||
clearTimeout(this.builderTm);
|
||||
this.builderTm = setTimeout(() => {
|
||||
if(this.touchUI) {
|
||||
this.urlBuilder.styles({'bottom': 0});
|
||||
} else {
|
||||
this.urlBuilder.styles({
|
||||
'height': '150px',
|
||||
'padding': '10px',
|
||||
|
@ -379,6 +478,7 @@ export default class Interface {
|
|||
this.optsHold.styles({
|
||||
'box-shadow': '10px 10px 25px 12px rgba(0,0,0,0.3)',
|
||||
});
|
||||
}
|
||||
}, 0);
|
||||
|
||||
this._refreshURL();
|
||||
|
@ -389,6 +489,11 @@ export default class Interface {
|
|||
return;
|
||||
}
|
||||
this.builderVisible = false;
|
||||
if(this.touchUI) {
|
||||
this.urlBuilder.styles({
|
||||
'bottom': (-this.urlBuilder.element.clientHeight - 60) + 'px',
|
||||
});
|
||||
} else {
|
||||
this.urlBuilder.styles({
|
||||
'height': '0px',
|
||||
'padding': '0px',
|
||||
|
@ -397,6 +502,8 @@ export default class Interface {
|
|||
this.optsHold.styles({
|
||||
'box-shadow': 'none',
|
||||
});
|
||||
}
|
||||
this.container.delClass('keyinput');
|
||||
clearTimeout(this.builderTm);
|
||||
this.builderTm = setTimeout(() => {
|
||||
this.urlBuilder.styles({'display': 'none'});
|
||||
|
@ -405,12 +512,14 @@ export default class Interface {
|
|||
|
||||
buildOptionsDownloads() {
|
||||
this.downloadPNG = this.dom.el('a')
|
||||
.text('Download PNG')
|
||||
.text('Export PNG')
|
||||
.attrs({
|
||||
'download': 'SequenceDiagram.png',
|
||||
'href': '#',
|
||||
})
|
||||
.on(['focus', 'mouseover', 'mousedown'], this._downloadPNGFocus)
|
||||
// Exploit delay between touchend and click on mobile
|
||||
.on('touchend', this._downloadPNGFocus)
|
||||
.on('click', this._downloadPNGClick);
|
||||
|
||||
this.downloadSVG = this.dom.el('a')
|
||||
|
@ -419,18 +528,22 @@ export default class Interface {
|
|||
'download': 'SequenceDiagram.svg',
|
||||
'href': '#',
|
||||
})
|
||||
.fastClick()
|
||||
.on('click', this._downloadSVGClick);
|
||||
|
||||
this.downloadURL = this.dom.el('a')
|
||||
.text('URL')
|
||||
.attrs({'href': '#'})
|
||||
.fastClick()
|
||||
.on('click', this._downloadURLClick);
|
||||
|
||||
this.urlBuilder = this.buildURLBuilder();
|
||||
|
||||
this.optsHold = this.dom.el('div').setClass('options downloads').add(
|
||||
this.downloadPNG,
|
||||
this.downloadSVG,
|
||||
this.downloadURL,
|
||||
this.buildURLBuilder()
|
||||
this.urlBuilder
|
||||
);
|
||||
|
||||
return this.optsHold;
|
||||
|
@ -444,6 +557,7 @@ export default class Interface {
|
|||
const hold = this.dom.el('div')
|
||||
.setClass('library-item')
|
||||
.add(holdInner)
|
||||
.fastClick()
|
||||
.on('click', this.addCodeBlock.bind(this, lib.code))
|
||||
.attach(container);
|
||||
|
||||
|
@ -467,10 +581,33 @@ export default class Interface {
|
|||
return container;
|
||||
}
|
||||
|
||||
buildCodePane() {
|
||||
this.code = this.dom.el('textarea')
|
||||
.setClass('editor-simple')
|
||||
.val(this.loadCode() || this.defaultCode)
|
||||
.on('input', () => this.update(false));
|
||||
|
||||
return this.dom.el('div').setClass('pane-code')
|
||||
.add(this.code);
|
||||
}
|
||||
|
||||
buildLibPane() {
|
||||
if(this.library.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.dom.el('div').setClass('pane-library')
|
||||
.add(this.dom.el('div').setClass('pane-library-scroller')
|
||||
.add(this.buildLibrary(
|
||||
this.dom.el('div').setClass('pane-library-inner')
|
||||
)));
|
||||
}
|
||||
|
||||
buildViewPane() {
|
||||
this.viewPaneInner = this.dom.el('div').setClass('pane-view-inner')
|
||||
.add(this.diagram.dom())
|
||||
.on('click', () => this._hideURLBuilder());
|
||||
.on('touchstart', () => this._hideURLBuilder())
|
||||
.on('mousedown', () => this._hideURLBuilder());
|
||||
|
||||
this.errorMsg = this.dom.el('div').setClass('msg-error');
|
||||
|
||||
|
@ -482,53 +619,10 @@ export default class Interface {
|
|||
);
|
||||
}
|
||||
|
||||
buildLeftPanes() {
|
||||
const container = this.dom.el('div').setClass('pane-side');
|
||||
|
||||
this.code = this.dom.el('textarea')
|
||||
.setClass('editor-simple')
|
||||
.val(this.loadCode() || this.defaultCode)
|
||||
.on('input', () => this.update(false));
|
||||
|
||||
const codePane = this.dom.el('div').setClass('pane-code')
|
||||
.add(this.code)
|
||||
.attach(container);
|
||||
|
||||
if(this.library.length > 0) {
|
||||
const libPane = this.dom.el('div').setClass('pane-library')
|
||||
.add(this.dom.el('div').setClass('pane-library-scroller')
|
||||
.add(this.buildLibrary(
|
||||
this.dom.el('div').setClass('pane-library-inner')
|
||||
)))
|
||||
.attach(container);
|
||||
|
||||
makeSplit(this.require, [codePane.element, libPane.element], {
|
||||
direction: 'vertical',
|
||||
minSize: [100, 5],
|
||||
sizes: [70, 30],
|
||||
snapOffset: 5,
|
||||
});
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
build(container) {
|
||||
this.dom = new DOMWrapper(container.ownerDocument);
|
||||
const lPane = this.buildLeftPanes();
|
||||
const viewPane = this.buildViewPane();
|
||||
|
||||
this.container = this.dom.wrap(container)
|
||||
.add(this.dom.el('div').setClass('pane-hold')
|
||||
.add(
|
||||
lPane,
|
||||
viewPane,
|
||||
this.dom.el('div').setClass('options links')
|
||||
.add(this.links.map((link) => this.dom.el('a')
|
||||
.attrs({'href': link.href, 'target': '_blank'})
|
||||
.text(link.label))),
|
||||
this.buildOptionsDownloads()
|
||||
))
|
||||
.on('dragover', (event) => {
|
||||
event.preventDefault();
|
||||
if(hasDroppedFile(event, 'image/svg+xml')) {
|
||||
|
@ -547,14 +641,66 @@ export default class Interface {
|
|||
if(file) {
|
||||
this.loadFile(file);
|
||||
}
|
||||
});
|
||||
})
|
||||
.on('focusin', () => this.container.addClass('keyinput'))
|
||||
.on('focusout', () => this.container.delClass('keyinput'));
|
||||
|
||||
makeSplit(this.require, [lPane.element, viewPane.element], {
|
||||
const codePane = this.buildCodePane();
|
||||
const libPane = this.buildLibPane();
|
||||
const viewPane = this.buildViewPane();
|
||||
|
||||
const links = this.links.map((link) => this.dom.el('a')
|
||||
.attrs({'href': link.href, 'target': '_blank'})
|
||||
.text(this.touchUI ? link.touchLabel : link.label));
|
||||
|
||||
if(this.touchUI) {
|
||||
this.buildOptionsDownloads();
|
||||
this.container
|
||||
.addClass('touch')
|
||||
.add(
|
||||
this.dom.el('div').setClass('pane-hold')
|
||||
.split([viewPane, codePane], {
|
||||
direction: 'vertical',
|
||||
minSize: [10, 10],
|
||||
require: this.require,
|
||||
sizes: [80, 20],
|
||||
snapOffset: 20,
|
||||
}),
|
||||
libPane.styles({'display': 'none', 'top': '100%'}),
|
||||
this.urlBuilder,
|
||||
this.dom.el('div').setClass('optbar')
|
||||
.add(
|
||||
...links,
|
||||
this.downloadPNG.text('PNG'),
|
||||
this.downloadSVG.text('SVG'),
|
||||
this.downloadURL.text('URL')
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this.container
|
||||
.add(
|
||||
this.dom.el('div').setClass('pane-hold')
|
||||
.split([
|
||||
this.dom.el('div').setClass('pane-side')
|
||||
.split([codePane, libPane], {
|
||||
direction: 'vertical',
|
||||
minSize: [100, 5],
|
||||
require: this.require,
|
||||
sizes: [70, 30],
|
||||
snapOffset: 5,
|
||||
}),
|
||||
viewPane,
|
||||
], {
|
||||
direction: 'horizontal',
|
||||
minSize: [10, 10],
|
||||
require: this.require,
|
||||
sizes: [30, 70],
|
||||
snapOffset: 70,
|
||||
});
|
||||
}),
|
||||
this.dom.el('div').setClass('options links').add(links),
|
||||
this.buildOptionsDownloads()
|
||||
);
|
||||
}
|
||||
|
||||
if(typeof window !== 'undefined') {
|
||||
window.addEventListener('keydown', (e) => {
|
||||
|
@ -839,6 +985,8 @@ export default class Interface {
|
|||
});
|
||||
});
|
||||
|
||||
code.on('focus', () => this._hideURLBuilder());
|
||||
|
||||
code.on('cursorActivity', () => {
|
||||
const from = code.getCursor('from').line;
|
||||
const to = code.getCursor('to').line;
|
||||
|
|
|
@ -2,6 +2,15 @@ html, body {
|
|||
margin: 0;
|
||||
padding: 0;
|
||||
font: 1em sans-serif;
|
||||
|
||||
text-size-adjust: none;
|
||||
-webkit-text-size-adjust: none;
|
||||
|
||||
/* disable whole-page elastic scrolling in iOS */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#loader {
|
||||
|
@ -63,32 +72,22 @@ html, body {
|
|||
}
|
||||
|
||||
.pane-side {
|
||||
display: inline-block;
|
||||
width: 30%;
|
||||
height: 100%;
|
||||
border-right: 1px solid #808080;
|
||||
box-sizing: border-box;
|
||||
vertical-align: top; /* Safari fix */
|
||||
}
|
||||
|
||||
.pane-code {
|
||||
height: 70%;
|
||||
}
|
||||
|
||||
.pane-library {
|
||||
background: #EEEEEE;
|
||||
user-select: none;
|
||||
height: 30%;
|
||||
-webkit-user-select: none;
|
||||
border-top: 1px solid #808080;
|
||||
box-sizing: border-box;
|
||||
overscroll-behavior: contain;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.pane-view {
|
||||
display: inline-block;
|
||||
width: 70%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
vertical-align: top; /* Safari fix */
|
||||
overscroll-behavior: contain;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.gutter {
|
||||
|
@ -266,6 +265,7 @@ html, body {
|
|||
position: absolute;
|
||||
background: #FFFFFF;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
z-index: 30;
|
||||
}
|
||||
|
||||
|
@ -369,6 +369,10 @@ html, body {
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.urlbuilder .copy:before {
|
||||
content: "\1F4CB";
|
||||
}
|
||||
|
||||
.urlbuilder .copy:active {
|
||||
background: #EEEEEE;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
|
@ -393,6 +397,127 @@ svg a:active, svg a:hover {
|
|||
fill: #0080CC;
|
||||
}
|
||||
|
||||
.touch .pane-hold {
|
||||
bottom: 50px;
|
||||
}
|
||||
|
||||
.touch.keyinput .pane-hold {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.touch .pane-code {
|
||||
border-top: 1px solid #808080;
|
||||
}
|
||||
|
||||
.touch .pane-library {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
transition: top 0.2s ease;
|
||||
}
|
||||
|
||||
.touch .urlbuilder {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 160px;
|
||||
margin-bottom: 50px;
|
||||
max-height: 100%;
|
||||
left: 0;
|
||||
transition: bottom 0.2s ease;
|
||||
border-top: 1px solid #808080;
|
||||
font-size: 1em;
|
||||
background: #FFFFFF;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.touch.keyinput .urlbuilder {
|
||||
margin-bottom: 0;
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
.touch .urlbuilder input[type=number] {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.touch .urlbuilder .output {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.touch .urlbuilder .copy {
|
||||
width: auto;
|
||||
left: 10px;
|
||||
height: 36px;
|
||||
border-radius: 100px;
|
||||
padding: 0;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
.touch.keyinput .copy {
|
||||
bottom: 30px;
|
||||
}
|
||||
|
||||
.touch .urlbuilder .copy:before {
|
||||
content: "Copy URL to Clipboard \1F4CB";
|
||||
}
|
||||
|
||||
.touch .urlbuilder .copy:active {
|
||||
background: #FFFFFF;
|
||||
box-shadow: none;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.touch .urlbuilder .copied {
|
||||
height: 36px;
|
||||
border-radius: 100px;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
.touch.keyinput .copied {
|
||||
bottom: 30px;
|
||||
}
|
||||
|
||||
.touch .options {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.optbar {
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 50px;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid #AAAAAA;
|
||||
background: #FAFAFA;
|
||||
font-size: 1.5em;
|
||||
font-weight: 100;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
.touch.keyinput .optbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.optbar a:link, .optbar a:visited {
|
||||
color: #5577FF;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.optbar a:active, .optbar a:hover {
|
||||
color: #2244CC;
|
||||
}
|
||||
|
||||
.optbar a {
|
||||
display: inline-block;
|
||||
width: 20%;
|
||||
height: 49px;
|
||||
line-height: 49px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.drop-target:after {
|
||||
display: none;
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
body {
|
||||
background: rgb(140, 185, 231);
|
||||
margin: 30px 30px 80px;
|
||||
margin: 30px 0 80px;
|
||||
padding: 0;
|
||||
font-family: sans-serif;
|
||||
line-height: 1.5;
|
||||
|
||||
text-size-adjust: none;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
article {
|
||||
|
@ -21,6 +24,7 @@ article > header {
|
|||
padding: 10px 20px;
|
||||
background: linear-gradient(#DDEEFF, #FFFFFF);
|
||||
border-radius: 2px;
|
||||
text-align: center;
|
||||
page-break-inside: avoid;
|
||||
break-inside: avoid;
|
||||
}
|
||||
|
@ -30,11 +34,11 @@ article > header > h1 {
|
|||
padding: 0;
|
||||
font: 3.5em 'Vollkorn', serif;
|
||||
clear: both;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
article > header > .sequence-diagram {
|
||||
filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.2));
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
article > h2 {
|
||||
|
@ -128,6 +132,7 @@ a:hover, a:active {
|
|||
.sequence-diagram[data-sd-interactive] .region.expanded {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.sequence-diagram[data-sd-interactive] .region.collapsed:hover .outline,
|
||||
|
@ -171,6 +176,115 @@ nav a:hover {
|
|||
background: #EEEEEE;
|
||||
}
|
||||
|
||||
@media (max-width: 860px) {
|
||||
body {
|
||||
background: transparent;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
article {
|
||||
max-width: 100%;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
margin: 0px;
|
||||
padding: 10px;
|
||||
border-radius: 0;
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
|
||||
article > header {
|
||||
margin: -10px -10px 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
article > header > h1 {
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
article > header > .sequence-diagram {
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
article > h2 {
|
||||
margin: 15px -10px 5px;
|
||||
padding: 5px 10px 0;
|
||||
}
|
||||
|
||||
article h3 {
|
||||
margin: 10px -10px 5px;
|
||||
padding: 5px 10px 0;
|
||||
}
|
||||
|
||||
article h4 {
|
||||
margin: 5px -10px 5px;
|
||||
padding: 5px 10px 0;
|
||||
}
|
||||
|
||||
.sequence-diagram {
|
||||
max-height: calc(100vh - 100px);
|
||||
}
|
||||
|
||||
pre.example {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
nav {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
article {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
pre {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
pre.example {
|
||||
padding: 5px;
|
||||
width: calc(100% - 205px);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.example-diagram {
|
||||
max-width: none;
|
||||
width: 200px;
|
||||
box-sizing: border-box;
|
||||
margin-left: 0;
|
||||
background: #FFFFFF;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 470px) {
|
||||
article > header > h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
pre.example {
|
||||
width: auto;
|
||||
margin: 5px -5px;
|
||||
}
|
||||
|
||||
.example-diagram {
|
||||
display: block;
|
||||
float: none;
|
||||
margin: 0 auto 10px;
|
||||
width: 300px;
|
||||
max-width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
background: transparent;
|
||||
|
@ -237,7 +351,6 @@ nav a:hover {
|
|||
font-size: 0.8em;
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.example-diagram {
|
||||
|
|
Loading…
Reference in New Issue