Merge pull request #60 from OptimistikSAS/issues/39
#39 opacity button/stroke size/radius button don’t allow the 0 value
This commit is contained in:
@@ -1,10 +1,9 @@
|
|||||||
/* eslint-disable node/no-unpublished-import */
|
/* eslint-disable node/no-unpublished-import */
|
||||||
import ListComboBox from 'elix/define/ListComboBox.js';
|
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 {defaultState} from 'elix/src/base/internal.js';
|
||||||
import {templateFrom, fragmentFrom} from 'elix/src/core/htmlLiterals.js';
|
import {templateFrom, fragmentFrom} from 'elix/src/core/htmlLiterals.js';
|
||||||
import {internal} from 'elix';
|
import {internal} from 'elix';
|
||||||
|
import NumberSpinBox from '../dialogs/se-elix/define/NumberSpinBox.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Dropdown
|
* @class Dropdown
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
/* eslint-disable node/no-unpublished-import */
|
import '../dialogs/se-elix/define/NumberSpinBox.js';
|
||||||
import 'elix/define/NumberSpinBox.js';
|
|
||||||
|
|
||||||
const template = document.createElement('template');
|
const template = document.createElement('template');
|
||||||
template.innerHTML = `
|
template.innerHTML = `
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
/* eslint-disable node/no-unpublished-import */
|
/* eslint-disable node/no-unpublished-import */
|
||||||
import ListComboBox from 'elix/define/ListComboBox.js';
|
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 * as internal from 'elix/src/base/internal.js';
|
||||||
import {templateFrom, fragmentFrom} from 'elix/src/core/htmlLiterals.js';
|
import {templateFrom, fragmentFrom} from 'elix/src/core/htmlLiterals.js';
|
||||||
|
import NumberSpinBox from '../dialogs/se-elix/define/NumberSpinBox.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Dropdown
|
* @class Dropdown
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/* eslint-disable max-len */
|
|
||||||
/* eslint-disable node/no-unpublished-import */
|
/* eslint-disable node/no-unpublished-import */
|
||||||
import 'elix/define/Dialog.js';
|
import 'elix/define/Dialog.js';
|
||||||
import 'elix/define/NumberSpinBox.js';
|
import './se-elix/define/NumberSpinBox.js';
|
||||||
|
|
||||||
const template = document.createElement('template');
|
const template = document.createElement('template');
|
||||||
template.innerHTML = `
|
template.innerHTML = `
|
||||||
|
|||||||
7
src/editor/dialogs/se-elix/define/NumberSpinBox.js
Normal file
7
src/editor/dialogs/se-elix/define/NumberSpinBox.js
Normal 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);
|
||||||
248
src/editor/dialogs/se-elix/src/base/NumberSpinBox.js
Normal file
248
src/editor/dialogs/se-elix/src/base/NumberSpinBox.js
Normal 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;
|
||||||
10
src/editor/dialogs/se-elix/src/plain/PlainNumberSpinBox.js
Normal file
10
src/editor/dialogs/se-elix/src/plain/PlainNumberSpinBox.js
Normal 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;
|
||||||
@@ -43,7 +43,7 @@ export class SePromptDialog extends HTMLElement {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error('unkonw attr for:', name, 'newValue =', newValue);
|
console.error('unknown attr for:', name, 'newValue =', newValue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* globals jQuery seConfirm seAlert seSelect */
|
/* globals jQuery seConfirm seAlert */
|
||||||
/**
|
/**
|
||||||
* The main module for the visual SVG this.
|
* The main module for the visual SVG this.
|
||||||
*
|
*
|
||||||
@@ -1538,7 +1538,7 @@ class Editor extends EditorStartup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @function copySelected
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
copySelected () {
|
copySelected () {
|
||||||
|
|||||||
@@ -190,6 +190,8 @@ export const changeSelectedAttributeNoUndoMethod = function (attr, newValue, ele
|
|||||||
setHref(elem, newValue);
|
setHref(elem, newValue);
|
||||||
} else if (newValue) {
|
} else if (newValue) {
|
||||||
elem.setAttribute(attr, newValue);
|
elem.setAttribute(attr, newValue);
|
||||||
|
} else if (typeof newValue === 'number') {
|
||||||
|
elem.setAttribute(attr, newValue);
|
||||||
} else {
|
} else {
|
||||||
elem.removeAttribute(attr);
|
elem.removeAttribute(attr);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user