Merge pull request #60 from OptimistikSAS/issues/39

#39 opacity button/stroke size/radius button don’t allow the 0 value
master
JFH 2021-01-19 19:39:28 +01:00 committed by GitHub
commit 12a26edc2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 275 additions and 12 deletions

View File

@ -1,10 +1,9 @@
/* eslint-disable node/no-unpublished-import */
import ListComboBox from 'elix/define/ListComboBox.js';
import NumberSpinBox from 'elix/define/NumberSpinBox.js';
// import Input from 'elix/src/base/Input.js';
import {defaultState} from 'elix/src/base/internal.js';
import {templateFrom, fragmentFrom} from 'elix/src/core/htmlLiterals.js';
import {internal} from 'elix';
import NumberSpinBox from '../dialogs/se-elix/define/NumberSpinBox.js';
/**
* @class Dropdown

View File

@ -1,5 +1,4 @@
/* eslint-disable node/no-unpublished-import */
import 'elix/define/NumberSpinBox.js';
import '../dialogs/se-elix/define/NumberSpinBox.js';
const template = document.createElement('template');
template.innerHTML = `

View File

@ -1,9 +1,8 @@
/* eslint-disable node/no-unpublished-import */
import ListComboBox from 'elix/define/ListComboBox.js';
import NumberSpinBox from 'elix/define/NumberSpinBox.js';
// import Input from 'elix/src/base/Input.js';
import * as internal from 'elix/src/base/internal.js';
import {templateFrom, fragmentFrom} from 'elix/src/core/htmlLiterals.js';
import NumberSpinBox from '../dialogs/se-elix/define/NumberSpinBox.js';
/**
* @class Dropdown

View File

@ -1,7 +1,6 @@
/* eslint-disable max-len */
/* eslint-disable node/no-unpublished-import */
import 'elix/define/Dialog.js';
import 'elix/define/NumberSpinBox.js';
import './se-elix/define/NumberSpinBox.js';
const template = document.createElement('template');
template.innerHTML = `
@ -102,7 +101,7 @@ export class SeExportDialog extends HTMLElement {
this.$okBtn = this._shadowRoot.querySelector('#export_ok');
this.$cancelBtn = this._shadowRoot.querySelector('#export_cancel');
this.$exportOption = this._shadowRoot.querySelector('#se-storage-pref');
this.$qualityCont = this._shadowRoot.querySelector('#se-quality');
this.$qualityCont = this._shadowRoot.querySelector('#se-quality');
this.$input = this._shadowRoot.querySelector('elix-number-spin-box');
this.value = 1;
}

View File

@ -0,0 +1,7 @@
import PlainNumberSpinBox from '../src/plain/PlainNumberSpinBox.js';
/**
* @class ElixNumberSpinBox
*/
export default class ElixNumberSpinBox extends PlainNumberSpinBox {}
customElements.define('elix-number-spin-box', ElixNumberSpinBox);

View File

@ -0,0 +1,248 @@
/* eslint-disable class-methods-use-this */
/* eslint-disable node/no-unpublished-import */
import {
defaultState,
setState,
state,
stateEffects
} from 'elix/src/base/internal.js';
import {
SpinBox
} from 'elix/src/base/SpinBox.js';
/**
* @class NumberSpinBox
*/
class NumberSpinBox extends SpinBox {
/**
* @function attributeChangedCallback
* @param {string} name
* @param {string} oldValue
* @param {string} newValue
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (name === 'max') {
this.max = parseFloat(newValue);
} else if (name === 'min') {
this.min = parseFloat(newValue);
} else if (name === 'step') {
this.step = parseFloat(newValue);
} else {
super.attributeChangedCallback(name, oldValue, newValue);
}
}
/**
* @function observedAttributes
* @returns {any} observed
*/
get [defaultState] () {
return Object.assign(super[defaultState], {
max: null,
min: null,
step: 1
});
}
/**
* @function formatValue
* Format the numeric value as a string.
*
* This is used after incrementing/decrementing the value to reformat the
* value as a string.
*
* @param {number} value
* @param {number} precision
* @returns {number}
*/
formatValue (value, precision) {
return Number(value).toFixed(precision);
}
/**
* The maximum allowable value of the `value` property.
*
* @type {number|null}
* @default 1
*/
get max () {
return this[state].max;
}
/**
* The maximum allowable value of the `value` property.
*
* @type {number|null}
* @default 1
*/
set max (max) {
this[setState]({
max
});
}
/**
* The minimum allowable value of the `value` property.
*
* @type {number|null}
* @default 1
*/
get min () {
return this[state].min;
}
/**
* @function set
* @returns {void}
*/
set min (min) {
this[setState]({
min
});
}
/**
* @function parseValue
* @param {number} value
* @param {number} precision
* @returns {int}
*/
parseValue (value, precision) {
const parsed = precision === 0 ? parseInt(value) : parseFloat(value);
return isNaN(parsed) ? 0 : parsed;
}
/**
* @function stateEffects
* @param {any} state
* @param {any} changed
* @returns {any}
*/
[stateEffects] (state, changed) {
const effects = super[stateEffects];
// If step changed, calculate its precision (number of digits after
// the decimal).
if (changed.step) {
const {
step
} = state;
const decimalRegex = /\.(\d)+$/;
const match = decimalRegex.exec(String(step));
const precision = match && match[1] ? match[1].length : 0;
Object.assign(effects, {
precision
});
}
if (changed.max || changed.min || changed.value) {
// The value is valid if it falls between the min and max.
// TODO: We need a way to let other classes/mixins on the prototype chain
// contribute to validity -- if someone else thinks the value is invalid,
// we should respect that, even if the value falls within the min/max
// bounds.
const {
max,
min,
precision,
value
} = state;
const parsed = parseInt(value, precision);
if (value !== '' && isNaN(parsed)) {
Object.assign(effects, {
valid: false,
validationMessage: 'Value must be a number'
});
} else if (!(max === null || parsed <= max)) {
Object.assign(effects, {
valid: false,
validationMessage: `Value must be less than or equal to ${max}.`
});
} else if (!(min === null || parsed >= min)) {
Object.assign(effects, {
valid: false,
validationMessage: `Value must be greater than or equal to ${min}.`
});
} else {
Object.assign(effects, {
valid: true,
validationMessage: ''
});
}
// We can only go up if we're below max.
Object.assign(effects, {
canGoUp: isNaN(parsed) || state.max === null || parsed <= state.max
});
// We can only go down if we're above min.
Object.assign(effects, {
canGoDown: isNaN(parsed) || state.min === null || parsed >= state.min
});
}
return effects;
}
/**
* @function get
* @returns {any}
*/
get step () {
return this[state].step;
}
/**
* @function set
* @returns {void}
*/
set step (step) {
if (!isNaN(step)) {
this[setState]({
step
});
}
}
/**
* @function stepDown
* @returns {void}
*/
stepDown () {
super.stepDown();
const {
max,
precision,
value
} = this[state];
let result = this.parseValue(value, precision) - this.step;
if (max !== null) {
result = Math.min(result, max);
}
const {
min
} = this[state];
if (min === null || result >= min) {
this.value = this.formatValue(result, precision);
}
}
/**
* @function stepUp
* @returns {void}
*/
stepUp () {
super.stepUp();
const {
min,
precision,
value
} = this[state];
let result = this.parseValue(value, precision) + this.step;
if (min !== null) {
result = Math.max(result, min);
}
const {
max
} = this[state];
if (max === null || result <= max) {
this.value = this.formatValue(result, precision);
}
}
}
export default NumberSpinBox;

View File

@ -0,0 +1,10 @@
/* eslint-disable node/no-unpublished-import */
import PlainSpinBoxMixin from 'elix/src/plain/PlainSpinBoxMixin.js';
import NumberSpinBox from '../base/NumberSpinBox.js';
/**
* @class PlainNumberSpinBox
*/
class PlainNumberSpinBox extends PlainSpinBoxMixin(NumberSpinBox) {}
export default PlainNumberSpinBox;

View File

@ -43,7 +43,7 @@ export class SePromptDialog extends HTMLElement {
break;
default:
// eslint-disable-next-line no-console
console.error('unkonw attr for:', name, 'newValue =', newValue);
console.error('unknown attr for:', name, 'newValue =', newValue);
break;
}
}

View File

@ -1,4 +1,4 @@
/* globals jQuery seConfirm seAlert seSelect */
/* globals jQuery seConfirm seAlert */
/**
* The main module for the visual SVG this.
*
@ -1538,7 +1538,7 @@ class Editor extends EditorStartup {
}
/**
*
* @function copySelected
* @returns {void}
*/
copySelected () {

View File

@ -190,6 +190,8 @@ export const changeSelectedAttributeNoUndoMethod = function (attr, newValue, ele
setHref(elem, newValue);
} else if (newValue) {
elem.setAttribute(attr, newValue);
} else if (typeof newValue === 'number') {
elem.setAttribute(attr, newValue);
} else {
elem.removeAttribute(attr);
}