Cursors, Esc to cancel active tool (#946)
* basic drawing cursors * Esc to cancel tool, I shortcut bug fix * panel btns hover animation * minor changes * Linter fix * update packages * remove NYC coverage causing build errors would be nice to find out a replacement or a fix --------- Co-authored-by: JFH <20402845+jfhenon@users.noreply.github.com>master
parent
24f78d3d0f
commit
f75d1a83a0
|
@ -24,12 +24,12 @@ jobs:
|
|||
npm run test
|
||||
env:
|
||||
CI: true
|
||||
- name: Report NYC coverage
|
||||
uses: sidx1024/report-nyc-coverage-github-action@v1.2.6
|
||||
with:
|
||||
# Path to coverage file generated by "nyc report".
|
||||
coverage_file: "coverage/coverage-summary.json"
|
||||
base_coverage_file: "coverage/coverage-summary.json"
|
||||
comment_template_file: ".github/comment-template.md"
|
||||
# - name: Report NYC coverage - removed for now
|
||||
# uses: sidx1024/report-nyc-coverage-github-action@v1.2.6
|
||||
# with:
|
||||
# # Path to coverage file generated by "nyc report".
|
||||
# coverage_file: "coverage/coverage-summary.json"
|
||||
# base_coverage_file: "coverage/coverage-summary.json"
|
||||
# comment_template_file: ".github/comment-template.md"
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
|
@ -85,22 +85,22 @@
|
|||
"dependencies": {
|
||||
"@svgedit/svgcanvas": "7.2.2",
|
||||
"browser-fs-access": "0.35.0",
|
||||
"core-js": "3.34.0",
|
||||
"core-js": "3.35.0",
|
||||
"elix": "15.0.1",
|
||||
"html2canvas": "1.4.1",
|
||||
"i18next": "23.7.8",
|
||||
"i18next": "23.7.16",
|
||||
"jspdf": "2.5.1",
|
||||
"pathseg": "1.2.1",
|
||||
"regenerator-runtime": "0.14.0",
|
||||
"replace-in-file": "^7.0.2",
|
||||
"svg2pdf.js": "2.2.2"
|
||||
"regenerator-runtime": "0.14.1",
|
||||
"replace-in-file": "^7.1.0",
|
||||
"svg2pdf.js": "2.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.23.5",
|
||||
"@babel/preset-env": "7.23.5",
|
||||
"@babel/register": "7.22.15",
|
||||
"@babel/runtime-corejs3": "7.23.5",
|
||||
"@cypress/code-coverage": "3.12.13",
|
||||
"@babel/core": "7.23.7",
|
||||
"@babel/preset-env": "7.23.8",
|
||||
"@babel/register": "7.23.7",
|
||||
"@babel/runtime-corejs3": "7.23.8",
|
||||
"@cypress/code-coverage": "3.12.18",
|
||||
"@rollup/plugin-babel": "^6.0.4",
|
||||
"@rollup/plugin-commonjs": "25.0.7",
|
||||
"@rollup/plugin-dynamic-import-vars": "2.1.2",
|
||||
|
@ -112,23 +112,23 @@
|
|||
"@web/dev-server-rollup": "0.6.1",
|
||||
"babel-plugin-istanbul": "^6.1.1",
|
||||
"babel-plugin-transform-object-rest-spread": "7.0.0-beta.3",
|
||||
"core-js-bundle": "3.34.0",
|
||||
"core-js-bundle": "3.35.0",
|
||||
"cp-cli": "2.0.0",
|
||||
"cypress": "13.6.1",
|
||||
"cypress": "13.6.3",
|
||||
"cypress-multi-reporters": "1.6.4",
|
||||
"jamilih": "0.58.2",
|
||||
"jsdoc": "4.0.2",
|
||||
"node-static": "0.7.11",
|
||||
"npm-run-all": "4.1.5",
|
||||
"nyc": "15.1.0",
|
||||
"open-cli": "7.2.0",
|
||||
"open-cli": "8.0.0",
|
||||
"promise-fs": "2.1.1",
|
||||
"qr-manipulation": "0.7.0",
|
||||
"query-result": "1.0.5",
|
||||
"remark-cli": "12.0.0",
|
||||
"remark-lint-ordered-list-marker-value": "3.1.2",
|
||||
"rimraf": "5.0.5",
|
||||
"rollup": "4.7.0",
|
||||
"rollup": "4.9.5",
|
||||
"rollup-plugin-copy": "3.5.0",
|
||||
"rollup-plugin-filesize": "10.0.0",
|
||||
"rollup-plugin-html": "0.2.1",
|
||||
|
|
|
@ -96,6 +96,7 @@ class Editor extends EditorStartup {
|
|||
'zh-CN',
|
||||
'zh-TW'
|
||||
]
|
||||
|
||||
const modKey = isMac() ? 'meta+' : 'ctrl+'
|
||||
this.shortcuts = [
|
||||
// Shortcuts not associated with buttons
|
||||
|
@ -304,6 +305,14 @@ class Editor extends EditorStartup {
|
|||
fn: () => {
|
||||
this.pasteInCenter()
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'escape',
|
||||
fn: () => {
|
||||
if (this.enableToolCancel) {
|
||||
this.cancelTool()
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
this.leftPanel = new LeftPanel(this)
|
||||
|
|
|
@ -122,6 +122,11 @@ class EditorStartup {
|
|||
this.modeEvent = this.svgCanvas.modeEvent
|
||||
document.addEventListener('modeChange', (evt) => this.modeListener(evt))
|
||||
|
||||
/** if true - selected tool can be cancelled with Esc key
|
||||
* disables on dragging (mousedown) to avoid changing mode in the middle of drawing
|
||||
*/
|
||||
this.enableToolCancel = true
|
||||
|
||||
this.leftPanel.init()
|
||||
this.bottomPanel.init()
|
||||
this.topPanel.init()
|
||||
|
@ -309,6 +314,7 @@ class EditorStartup {
|
|||
return false
|
||||
})
|
||||
$id('svgcanvas').addEventListener('mousedown', (evt) => {
|
||||
this.enableToolCancel = false
|
||||
if (evt.button === 1 || keypan === true) {
|
||||
// prDefault to avoid firing of browser's panning on mousewheel
|
||||
evt.preventDefault()
|
||||
|
@ -331,6 +337,7 @@ class EditorStartup {
|
|||
})
|
||||
|
||||
window.addEventListener('mouseup', (evt) => {
|
||||
this.enableToolCancel = true
|
||||
if (evt.button === 1) {
|
||||
this.svgCanvas.setMode(previousMode ?? 'select')
|
||||
}
|
||||
|
@ -747,12 +754,36 @@ class EditorStartup {
|
|||
case 'zoom':
|
||||
cs = 'crosshair'
|
||||
break
|
||||
case 'circle':
|
||||
case 'ellipse':
|
||||
case 'rect':
|
||||
case 'square':
|
||||
case 'star':
|
||||
case 'polygon':
|
||||
cs = `url("./images/cursors/${mode}_cursor.svg"), crosshair`
|
||||
break
|
||||
case 'text':
|
||||
// #TODO: Cursor should be changed back to default after text element was created
|
||||
cs = 'text'
|
||||
break
|
||||
default:
|
||||
cs = 'auto'
|
||||
}
|
||||
|
||||
this.workarea.style.cursor = cs
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for Esc key to be pressed to cancel active mode, sets mode to Select
|
||||
*/
|
||||
cancelTool () {
|
||||
const mode = this.svgCanvas.getMode()
|
||||
// list of modes that are currently save to cancel
|
||||
const modesToCancel = ['zoom', 'rect', 'square', 'circle', 'ellipse', 'line', 'text', 'star', 'polygon', 'eyedropper']
|
||||
if (modesToCancel.includes(mode)) {
|
||||
this.leftPanel.clickSelect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default EditorStartup
|
||||
|
|
|
@ -3,9 +3,18 @@ import { t } from '../locale.js'
|
|||
const template = document.createElement('template')
|
||||
template.innerHTML = `
|
||||
<style>
|
||||
@keyframes btnHover {
|
||||
from {
|
||||
background-color: var(--main-bg-color);
|
||||
}
|
||||
|
||||
to {
|
||||
background-color: var(--icon-bg-color-hover);
|
||||
}
|
||||
}
|
||||
:host(:hover) :not(.disabled)
|
||||
{
|
||||
background-color: var(--icon-bg-color-hover);
|
||||
animation: btnHover 0.2s forwards;
|
||||
}
|
||||
div
|
||||
{
|
||||
|
|
|
@ -39,10 +39,18 @@ export class FlyingButton extends HTMLElement {
|
|||
:host {
|
||||
position:relative;
|
||||
}
|
||||
.overall:hover *
|
||||
{
|
||||
@keyframes btnHover {
|
||||
from {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
to {
|
||||
background-color: var(--icon-bg-color-hover);
|
||||
}
|
||||
}
|
||||
.overall .menu-button:hover {
|
||||
animation: btnHover 0.2s forwards;
|
||||
}
|
||||
img {
|
||||
border: none;
|
||||
width: 24px;
|
||||
|
|
|
@ -44,6 +44,23 @@ template.innerHTML = `
|
|||
margin-top: 2px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
#arrow-up, #arrow-down {
|
||||
user-select: none;
|
||||
}
|
||||
@keyframes hover-arrows {
|
||||
from {
|
||||
background: transparent;
|
||||
color: var(--icon-bg-color-hover);
|
||||
}
|
||||
|
||||
to {
|
||||
background: var(--icon-bg-color-hover);
|
||||
color: var(--orange-color);
|
||||
}
|
||||
}
|
||||
#arrow-up:hover, #arrow-down:hover {
|
||||
animation: hover-arrows 0.2s forwards;
|
||||
}
|
||||
#down{
|
||||
width:18px;
|
||||
height:23px;
|
||||
|
|
|
@ -83,6 +83,7 @@ export default {
|
|||
callback () {
|
||||
// Add the button and its handler(s)
|
||||
const title = `${name}:buttons.0.title`
|
||||
// #TODO: Come up with another shortcut (?) because 'I' is reserved for italic
|
||||
const key = `${name}:buttons.0.key`
|
||||
const buttonTemplate = `
|
||||
<se-button id="tool_eyedropper" title="${title}" src="eye_dropper.svg" shortcut=${key}></se-button>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0"?>
|
||||
<svg width="20" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||
<title>circle_cursor</title>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<g id="layer2">
|
||||
<path d="m0.1,7.76l7.7,-7.66l-7.7,0l0,7.66z" fill="#2b3c45" id="path9" stroke="#2b3c45"
|
||||
stroke-dashoffset="0" stroke-width="0.19" />
|
||||
</g>
|
||||
|
||||
<circle cx="9.44" cy="9.06" display="inline" fill="#ffffff" id="path10" r="5.98" stroke="#2b3c45"
|
||||
stroke-dashoffset="0" stroke-width="1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 599 B |
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0"?>
|
||||
<svg width="20" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||
<title>circle_cursor</title>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<g class="layer" id="svg_2">
|
||||
<g id="layer2">
|
||||
<path d="m0.1,6.37l6.3,-6.27l-6.3,0l0,6.27z" fill="#2b3c45" id="path9" stroke="#2b3c45"
|
||||
stroke-dashoffset="0" stroke-width="0.2" />
|
||||
</g>
|
||||
<ellipse cx="11.0" cy="7" fill="#ffffff" id="svg_1" rx="7.5" ry="3.43" stroke="#2b3c45" stroke-width="1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 623 B |
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0"?>
|
||||
<svg width="20" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||
<title>circle_cursor</title>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<g class="layer" id="svg_2">
|
||||
|
||||
<path d="m0.1,6.37l6.3,-6.27l-6.3,0l0,6.27z" fill="#2b3c45" id="path9" stroke="#2b3c45"
|
||||
stroke-dashoffset="0" stroke-width="0.2" />
|
||||
|
||||
</g>
|
||||
<rect fill="#ffffff" height="6.4" id="svg_3" stroke="#2b3c45" width="13.6" x="4.54" y="4.53" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 556 B |
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0"?>
|
||||
<svg width="20" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||
<title>circle_cursor</title>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<g class="layer" id="svg_2">
|
||||
<g id="layer2">
|
||||
<path d="m0.1,6.37l6.3,-6.27l-6.3,0l0,6.27z" fill="#2b3c45" id="path9" stroke="#2b3c45" stroke-dashoffset="0" stroke-width="0.2"/>
|
||||
</g>
|
||||
</g>
|
||||
<rect fill="#ffffff" height="8" id="svg_3" stroke="#2b3c45" width="8" x="5.04" y="4.43"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 517 B |
|
@ -764,25 +764,38 @@ class TopPanel {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are currently selected text elements to avoid firing of bold,italic when no text selected
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get anyTextSelected () {
|
||||
const selected = this.editor.svgCanvas.getSelectedElements()
|
||||
return selected.filter(el => el.tagName === 'text').length > 0
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {false}
|
||||
*/
|
||||
clickBold () {
|
||||
if (this.anyTextSelected) {
|
||||
this.editor.svgCanvas.setBold(!this.editor.svgCanvas.getBold())
|
||||
this.updateContextPanel()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {false}
|
||||
*/
|
||||
clickItalic () {
|
||||
if (this.anyTextSelected) {
|
||||
this.editor.svgCanvas.setItalic(!this.editor.svgCanvas.getItalic())
|
||||
this.updateContextPanel()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the click on the text decoration buttons
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
--icon-bg-color: #72797A;
|
||||
--icon-bg-color-hover: #2B3C45;
|
||||
--input-color: #B2B2B2;
|
||||
--orange-color: #f9bc01;
|
||||
--global-se-spin-input-width: 82px;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue