diff --git a/package.json b/package.json
index fe9ecdc4e..299d8b83e 100644
--- a/package.json
+++ b/package.json
@@ -21,12 +21,22 @@
"packages/*"
],
"devDependencies": {
- "@typescript-eslint/eslint-plugin": "^2.29.0",
- "@typescript-eslint/parser": "^2.29.0",
+ "@types/jest": "^25.2.1",
+ "@types/node": "^13.13.4",
+ "@typescript-eslint/eslint-plugin": "^2.30.0",
+ "@typescript-eslint/parser": "^2.30.0",
"eslint": "^6.8.0",
"eslint-plugin-import": "^2.20.2",
- "eslint-plugin-prefer-arrow": "^1.2.0",
- "lerna": "^3.20.2"
+ "eslint-plugin-prefer-arrow": "^1.2.1",
+ "jest": "^25.5.4",
+ "jest-cli": "^25.5.4",
+ "jest-environment-jsdom": "^25.5.0",
+ "jest-extended": "^0.11.5",
+ "jest-junit": "^10.0.0",
+ "jsdom": "^16.2.2",
+ "jsdom-global": "^3.0.2",
+ "lerna": "^3.20.2",
+ "ts-jest": "^25.4.0"
},
"engines": {
"node": ">=12.13.1",
diff --git a/packages/common/package.json b/packages/common/package.json
index 2785c1e8d..7185a5ebd 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -69,27 +69,17 @@
},
"devDependencies": {
"@types/dompurify": "^2.0.1",
- "@types/jest": "^25.2.1",
- "@types/jquery": "^3.3.35",
+ "@types/jquery": "^3.3.36",
"@types/moment": "^2.13.0",
- "@types/node": "^13.13.2",
"autoprefixer": "^9.7.6",
"copyfiles": "^2.2.0",
"cross-env": "^7.0.2",
- "jest": "^25.4.0",
- "jest-cli": "^25.4.0",
- "jest-environment-jsdom": "^25.4.0",
- "jest-extended": "^0.11.5",
- "jest-junit": "^10.0.0",
- "jsdom": "^16.2.2",
- "jsdom-global": "^3.0.2",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "4.14.0",
"nodemon": "^2.0.3",
"npm-run-all": "^4.1.5",
- "postcss-cli": "^7.1.0",
+ "postcss-cli": "^7.1.1",
"rimraf": "^3.0.2",
- "ts-jest": "^25.4.0",
"typescript": "^3.8.3"
},
"engines": {
diff --git a/packages/common/src/editors/__tests__/dualInputEditor.spec.ts b/packages/common/src/editors/__tests__/dualInputEditor.spec.ts
new file mode 100644
index 000000000..67ce39320
--- /dev/null
+++ b/packages/common/src/editors/__tests__/dualInputEditor.spec.ts
@@ -0,0 +1,789 @@
+import { Editors } from '../index';
+import { DualInputEditor } from '../dualInputEditor';
+import { KeyCode } from '../../enums/index';
+import { Column, EditorArgs, EditorArguments, GridOption, ColumnEditorComboInput } from '../../interfaces/index';
+
+declare const Slick: any;
+const KEY_CHAR_0 = 48;
+const KEY_CHAR_A = 97;
+const containerId = 'demo-container';
+
+// define a
container to simulate the grid container
+const template = `
`;
+
+const dataViewStub = {
+ refresh: jest.fn(),
+};
+
+const gridOptionMock = {
+ autoCommitEdit: false,
+ editable: true,
+} as GridOption;
+
+const getEditorLockMock = {
+ commitCurrentEdit: jest.fn(),
+};
+
+const gridStub = {
+ getOptions: () => gridOptionMock,
+ getColumns: jest.fn(),
+ getEditorLock: () => getEditorLockMock,
+ getHeaderRowColumn: jest.fn(),
+ onValidationError: new Slick.Event(),
+ render: jest.fn(),
+};
+
+describe('DualInputEditor', () => {
+ let divContainer: HTMLDivElement;
+ let editor: DualInputEditor;
+ let editorArguments: EditorArguments;
+ let mockColumn: Column;
+ let mockItemData: any;
+
+ beforeEach(() => {
+ divContainer = document.createElement('div');
+ divContainer.innerHTML = template;
+ document.body.appendChild(divContainer);
+
+ mockColumn = { id: 'title', field: 'title', editable: true, editor: { model: Editors.text }, internalColumnEditor: {} } as Column;
+
+ editorArguments = {
+ grid: gridStub,
+ column: mockColumn,
+ item: mockItemData,
+ event: null,
+ cancelChanges: jest.fn(),
+ commitChanges: jest.fn(),
+ container: divContainer,
+ columnMetaData: null,
+ dataView: dataViewStub,
+ gridPosition: { top: 0, left: 0, bottom: 10, right: 10, height: 100, width: 100, visible: true },
+ position: { top: 0, left: 0, bottom: 10, right: 10, height: 100, width: 100, visible: true },
+ };
+ });
+
+ describe('with invalid Editor instance', () => {
+ it('should throw an error when trying to call init without any arguments', (done) => {
+ try {
+ editor = new DualInputEditor(null);
+ } catch (e) {
+ expect(e.toString()).toContain(`[Slickgrid-Universal] Something is wrong with this grid, an Editor must always have valid arguments.`);
+ done();
+ }
+ });
+
+ it('should throw an error when initialize the editor without the requires params leftInput/rightInput', (done) => {
+ try {
+ // @ts-ignore
+ editor = new DualInputEditor({});
+ } catch (e) {
+ expect(e.toString()).toContain(`[Slickgrid-Universal] Please make sure that your Combo Input Editor has params defined with "leftInput" and "rightInput"`);
+ done();
+ }
+ });
+ });
+
+ describe('with valid Editor instance', () => {
+ beforeEach(() => {
+ const editorParams = { leftInput: { field: 'from', type: 'float' }, rightInput: { field: 'to', type: 'float' } } as ColumnEditorComboInput;
+ mockItemData = { id: 1, from: 1, to: 22, isActive: true };
+ mockColumn = {
+ id: 'range', field: 'range', editable: true, internalColumnEditor: { params: editorParams },
+ editor: { model: Editors.dualInput, params: editorParams },
+ } as Column;
+
+ editorArguments.column = mockColumn;
+ editorArguments.item = mockItemData;
+ });
+
+ afterEach(() => {
+ editor.destroy();
+ });
+
+ it('should initialize the editor', () => {
+ editor = new DualInputEditor(editorArguments);
+ const editorCount = divContainer.querySelectorAll('input.dual-editor-text.editor-range').length;
+ expect(editorCount).toBe(2);
+ });
+
+ it('should have a placeholder on the left input when defined in its column definition', () => {
+ const testValue = 'test placeholder';
+ mockColumn.internalColumnEditor.params.leftInput.placeholder = testValue;
+
+ editor = new DualInputEditor(editorArguments);
+ const editorElm = divContainer.querySelector
('input.dual-editor-text.editor-range.left');
+
+ expect(editorElm.placeholder).toBe(testValue);
+ });
+
+ it('should have a placeholder on the right input when defined in its column definition', () => {
+ const testValue = 'test placeholder';
+ mockColumn.internalColumnEditor.params.rightInput.placeholder = testValue;
+
+ editor = new DualInputEditor(editorArguments);
+ const editorElm = divContainer.querySelector('input.dual-editor-text.editor-range.right');
+
+ expect(editorElm.placeholder).toBe(testValue);
+ });
+
+ it('should have a title (tooltip) on left input when defined in its column definition', () => {
+ const testValue = 'test title';
+ mockColumn.internalColumnEditor.params.leftInput.title = testValue;
+
+ editor = new DualInputEditor(editorArguments);
+ const editorElm = divContainer.querySelector('input.dual-editor-text.editor-range.left');
+
+ expect(editorElm.title).toBe(testValue);
+ });
+
+ it('should have a title (tooltip) on right input when defined in its column definition', () => {
+ const testValue = 'test title';
+ mockColumn.internalColumnEditor.params.rightInput.title = testValue;
+
+ editor = new DualInputEditor(editorArguments);
+ const editorElm = divContainer.querySelector('input.dual-editor-text.editor-range.right');
+
+ expect(editorElm.title).toBe(testValue);
+ });
+
+ it('should have a left input as type number and right input as readonly text input when that right input is set to "readonly"', () => {
+ mockColumn.internalColumnEditor.params.leftInput.type = 'float';
+ mockColumn.internalColumnEditor.params.rightInput.type = 'readonly';
+
+ editor = new DualInputEditor(editorArguments);
+ const editorLeftElm = divContainer.querySelector('input.dual-editor-text.editor-range.left');
+ const editorRightElm = divContainer.querySelector('input.dual-editor-text.editor-range.right');
+
+ expect(editorLeftElm.type).toBe('number');
+ expect(editorRightElm.type).toBe('text');
+ expect(editorLeftElm.readOnly).toBe(false);
+ expect(editorRightElm.readOnly).toBe(true);
+ });
+
+ it('should call "columnEditor" GETTER and expect to equal the editor settings we provided', () => {
+ mockColumn.internalColumnEditor.params = {
+ leftInput: {
+ field: 'from',
+ placeholder: 'test placeholder',
+ range: 'test title',
+ alwaysSaveOnEnterKey: false,
+ },
+ rightInput: {
+ field: 'to'
+ }
+ };
+
+ editor = new DualInputEditor(editorArguments);
+
+ expect(editor.columnEditor).toEqual(mockColumn.internalColumnEditor);
+ });
+
+ it('should call "setValue" and expect the DOM element value to be the same string when calling "getValue"', () => {
+ editor = new DualInputEditor(editorArguments);
+ editor.setValues([12, 34]);
+
+ expect(editor.getValue()).toEqual(['12', '34']);
+ });
+
+ it('should define an item datacontext containing a string as cell value and expect this value to be loaded in the editor when calling "loadValue"', () => {
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ const editorElm = editor.editorDomElement;
+
+ expect(editorElm).toBeTruthy();
+ expect(editor.getValue()).toEqual(['1', '22']);
+ });
+
+ it('should dispatch a keyboard event and expect "stopImmediatePropagation()" to have been called when using Left Arrow key', () => {
+ const event = new (window.window as any).KeyboardEvent('keydown', { keyCode: KeyCode.LEFT, bubbles: true, cancelable: true });
+ const spyEvent = jest.spyOn(event, 'stopImmediatePropagation');
+
+ editor = new DualInputEditor(editorArguments);
+ const editorElm = divContainer.querySelector('input.editor-range');
+
+ editor.focus();
+ editorElm.dispatchEvent(event);
+
+ expect(spyEvent).toHaveBeenCalled();
+ });
+
+ it('should dispatch a keyboard event and expect "stopImmediatePropagation()" to have been called when using Right Arrow key', () => {
+ const event = new (window.window as any).KeyboardEvent('keydown', { keyCode: KeyCode.RIGHT, bubbles: true, cancelable: true });
+ const spyEvent = jest.spyOn(event, 'stopImmediatePropagation');
+
+ editor = new DualInputEditor(editorArguments);
+ const editorElm = divContainer.querySelector('input.editor-range');
+
+ editor.focus();
+ editorElm.dispatchEvent(event);
+
+ expect(spyEvent).toHaveBeenCalled();
+ });
+
+ describe('isValueChanged method', () => {
+ it('should return True when previously dispatched keyboard event is a new char 0', () => {
+ const event = new (window.window as any).KeyboardEvent('keydown', { keyCode: KEY_CHAR_0, bubbles: true, cancelable: true });
+
+ editor = new DualInputEditor(editorArguments);
+ const editorElm = divContainer.querySelector('input.editor-range');
+
+ editor.focus();
+ editorElm.dispatchEvent(event);
+
+ expect(editor.isValueChanged()).toBe(true);
+ });
+
+ it('should return False when previously dispatched keyboard event is same number as current value', () => {
+ const event = new (window.window as any).KeyboardEvent('keydown', { keyCode: KEY_CHAR_0, bubbles: true, cancelable: true });
+
+ editor = new DualInputEditor(editorArguments);
+ const editorElm = divContainer.querySelector('input.editor-range');
+
+ editor.loadValue({ id: 1, range: '1-22', from: 0, to: 22, isActive: true });
+ editor.focus();
+ editorElm.dispatchEvent(event);
+
+ expect(editor.isValueChanged()).toBe(false);
+ });
+
+ it('should return False when previously dispatched keyboard event is same string number as current value', () => {
+ const event = new (window.window as any).KeyboardEvent('keydown', { keyCode: KEY_CHAR_0, bubbles: true, cancelable: true });
+
+ editor = new DualInputEditor(editorArguments);
+ const editorElm = divContainer.querySelector('input.editor-range');
+
+ editor.loadValue({ id: 1, range: '1-22', from: '0', to: '22', isActive: true });
+ editor.focus();
+ editorElm.dispatchEvent(event);
+
+ expect(editor.isValueChanged()).toBe(false);
+ });
+
+ it('should return True when left input last dispatched keyboard event is ENTER and "alwaysSaveOnEnterKey" is enabled', () => {
+ const event = new (window.window as any).KeyboardEvent('keydown', { keyCode: KeyCode.ENTER, bubbles: true, cancelable: true });
+ mockColumn.internalColumnEditor.params.leftInput.alwaysSaveOnEnterKey = true;
+
+ editor = new DualInputEditor(editorArguments);
+ const editorLeftElm = divContainer.querySelector('input.editor-range.left');
+
+ editor.focus();
+ editorLeftElm.dispatchEvent(event);
+
+ expect(editor.isValueChanged()).toBe(true);
+ });
+
+ it('should return True when right input last dispatched keyboard event is ENTER and "alwaysSaveOnEnterKey" is enabled', () => {
+ const event = new (window.window as any).KeyboardEvent('keydown', { keyCode: KeyCode.ENTER, bubbles: true, cancelable: true });
+ mockColumn.internalColumnEditor.params.rightInput.alwaysSaveOnEnterKey = true;
+
+ editor = new DualInputEditor(editorArguments);
+ const editorRightElm = divContainer.querySelector('input.editor-range.right');
+
+ editor.focus();
+ editorRightElm.dispatchEvent(event);
+
+ expect(editor.isValueChanged()).toBe(true);
+ });
+ });
+
+ describe('applyValue method', () => {
+ it('should apply the value to the range property when it passes validation', () => {
+ mockColumn.internalColumnEditor.params.leftInput.validator = null;
+ mockItemData = { id: 1, range: '1-22', from: 0, to: 22, isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.applyValue(mockItemData, { id: 1, from: 33, to: 78 });
+
+ expect(mockItemData).toEqual({ id: 1, range: '1-22', from: 33, to: 78, isActive: true });
+ });
+
+ it('should apply the value to the range property with a field having dot notation (complex object) that passes validation', () => {
+ mockColumn.internalColumnEditor.params.leftInput.validator = null;
+ mockColumn.field = 'part.from';
+ mockColumn.internalColumnEditor.params.leftInput.field = 'part.from';
+ mockColumn.internalColumnEditor.params.rightInput.field = 'part.to';
+ mockItemData = { id: 1, part: { range: '1-22', from: 0, to: 44 }, isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.applyValue(mockItemData, { id: 1, range: '1-22', from: 33, to: 78 });
+
+ expect(mockItemData).toEqual({ id: 1, part: { range: '1-22', from: 33, to: 78 }, isActive: true });
+ });
+
+ it('should return item data with an empty string in its left input value when it fails the custom validation', () => {
+ mockColumn.internalColumnEditor.params.leftInput.validator = (value: any, args: EditorArgs) => {
+ if (+value < 10) {
+ return { valid: false, msg: 'From value must be over 10.' };
+ }
+ return { valid: true, msg: '' };
+ };
+ mockItemData = { id: 1, range: '1-22', from: 22, to: 78, isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.applyValue(mockItemData, { id: 1, range: '1-22', from: 4, to: 5 });
+
+ expect(mockItemData).toEqual({ id: 1, range: '1-22', from: '', to: 5, isActive: true });
+ });
+
+ it('should return item data with an empty string in its right input value when it fails the custom validation', () => {
+ mockColumn.internalColumnEditor.params.rightInput.validator = (value: any, args: EditorArgs) => {
+ if (+value > 150) {
+ return { valid: false, msg: 'To value must be below 150.' };
+ }
+ return { valid: true, msg: '' };
+ };
+ mockItemData = { id: 1, range: '1-22', from: 22, to: 78, isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.applyValue(mockItemData, { id: 1, range: '1-22', from: 4, to: 155 });
+
+ expect(mockItemData).toEqual({ id: 1, range: '1-22', from: 4, to: '', isActive: true });
+ });
+ });
+
+ describe('serializeValue method', () => {
+ it('should return serialized value as a number', () => {
+ mockItemData = { id: 1, range: '13-22', from: 13, to: 22, isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ const output = editor.serializeValue();
+
+ expect(editor.getDecimalPlaces('leftInput')).toBe(0);
+ expect(editor.getDecimalPlaces('rightInput')).toBe(0);
+ expect(output).toEqual({ from: 13, to: 22 });
+ });
+
+ it('should return serialized value as a float number when "decimal" is set to 2', () => {
+ mockItemData = { id: 1, range: '32.789-45.67', from: 32.789, to: 45.67, isActive: true };
+ mockColumn.internalColumnEditor.params.leftInput.decimal = 1;
+ mockColumn.internalColumnEditor.params.rightInput.decimal = 3;
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ const output = editor.serializeValue();
+
+ expect(editor.getDecimalPlaces('leftInput')).toBe(1);
+ expect(editor.getDecimalPlaces('rightInput')).toBe(3);
+ expect(output).toEqual({ from: 32.8, to: 45.67 });
+ });
+
+ it('should return serialized value as a number even when the item property value is a number in a string', () => {
+ mockItemData = { id: 1, range: '1-33', from: '1', to: '33', isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ const output = editor.serializeValue();
+
+ expect(editor.getDecimalPlaces('leftInput')).toBe(0);
+ expect(editor.getDecimalPlaces('rightInput')).toBe(0);
+ expect(output).toEqual({ from: 1, to: 33 });
+ });
+
+ it('should return a rounded number when a float is provided without any decimal place defined', () => {
+ mockItemData = { id: 1, range: '2-32.7', from: '2', to: '32.7', isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ const output = editor.serializeValue();
+
+ expect(editor.getDecimalPlaces('leftInput')).toBe(0);
+ expect(editor.getDecimalPlaces('rightInput')).toBe(0);
+ expect(output).toEqual({ from: 2, to: 33 });
+ });
+
+ it('should return serialized value as an empty string when item value is also an empty string', () => {
+ mockItemData = { id: 1, range: '', from: '', to: 2, isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ const output = editor.serializeValue();
+
+ expect(editor.getDecimalPlaces('leftInput')).toBe(0);
+ expect(editor.getDecimalPlaces('rightInput')).toBe(0);
+ expect(output).toEqual({ from: '', to: 2 });
+ });
+
+ it('should return serialized value as an empty string when item value is null', () => {
+ mockItemData = { id: 1, range: null, from: null, to: 2, isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ const output = editor.serializeValue();
+
+ expect(editor.getDecimalPlaces('leftInput')).toBe(0);
+ expect(editor.getDecimalPlaces('rightInput')).toBe(0);
+ expect(output).toEqual({ from: '', to: 2 });
+ });
+
+ it('should return value as a number when using a dot (.) notation for complex object', () => {
+ mockColumn.field = 'part.from';
+ mockColumn.internalColumnEditor.params.leftInput.field = 'part.from';
+ mockColumn.internalColumnEditor.params.rightInput.field = 'part.to';
+ mockItemData = { id: 1, part: { range: '5-44', from: 5, to: 44 }, isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ const output = editor.serializeValue();
+
+ expect(output).toEqual({ part: { from: 5, to: 44 } });
+ });
+ });
+
+ describe('getInputDecimalSteps method', () => {
+ it('should return decimal step as 1 increment when decimal is not set', () => {
+ mockItemData = { id: 1, range: '2-33', from: 2, to: 33, isActive: true };
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+
+ expect(editor.getInputDecimalSteps('leftInput')).toBe('1');
+ expect(editor.getInputDecimalSteps('rightInput')).toBe('1');
+ });
+
+ it('should return decimal step as 0.1 increment when decimal is set to 1 decimal', () => {
+ mockItemData = { id: 1, range: '2-32.7', from: 2, to: 32.7, isActive: true };
+ mockColumn.internalColumnEditor.params.leftInput.decimal = 1;
+ mockColumn.internalColumnEditor.params.rightInput.decimal = 2;
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+
+ expect(editor.getInputDecimalSteps('leftInput')).toBe('0.1');
+ expect(editor.getInputDecimalSteps('rightInput')).toBe('0.01');
+ });
+
+ it('should return decimal step as 0.01 increment when decimal is set to 2 decimal', () => {
+ mockItemData = { id: 1, range: '2-32.7', from: 2, to: 32.7, isActive: true };
+ mockColumn.internalColumnEditor.params.leftInput.decimal = 1;
+ mockColumn.internalColumnEditor.params.rightInput.decimal = 2;
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+
+ expect(editor.getInputDecimalSteps('leftInput')).toBe('0.1');
+ expect(editor.getInputDecimalSteps('rightInput')).toBe('0.01');
+ });
+ });
+
+ describe('save method', () => {
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should call "getEditorLock" method when "hasAutoCommitEdit" is enabled', () => {
+ mockItemData = { id: 1, range: '3-32', from: 3, to: 32, isActive: true };
+ gridOptionMock.autoCommitEdit = true;
+ const spy = jest.spyOn(gridStub.getEditorLock(), 'commitCurrentEdit');
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ editor.setValues([2, 35]);
+ editor.save();
+
+ expect(spy).toHaveBeenCalled();
+ });
+
+ it('should call "commitChanges" method when "hasAutoCommitEdit" is disabled', () => {
+ mockItemData = { id: 1, range: '3-32', from: 3, to: 32, isActive: true };
+ gridOptionMock.autoCommitEdit = false;
+ const spy = jest.spyOn(editorArguments, 'commitChanges');
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ editor.setValues([2, 35]);
+ editor.save();
+
+ expect(spy).toHaveBeenCalled();
+ });
+
+ // it('should not call anything when the input value is not a valid float number', () => {
+ // mockItemData = { id: 1, range: null, from: null, to: null, isActive: true };
+ // gridOptionMock.autoCommitEdit = true;
+ // const spy = jest.spyOn(gridStub.getEditorLock(), 'commitCurrentEdit');
+
+ // editor = new DualInputEditor(editorArguments);
+ // editor.loadValue(mockItemData);
+ // editor.setValue(['-.', '-.']);
+ // editor.save();
+
+ // expect(spy).not.toHaveBeenCalled();
+ // });
+
+ it('should call "getEditorLock" and "save" methods when "hasAutoCommitEdit" is enabled and the left input event "focusout" is triggered', (done) => {
+ mockItemData = { id: 1, range: '3-32', from: 3, to: 32, isActive: true };
+ gridOptionMock.autoCommitEdit = true;
+ const spyGetEditor = jest.spyOn(gridStub, 'getEditorLock');
+ const spyCommit = jest.spyOn(gridStub.getEditorLock(), 'commitCurrentEdit');
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ editor.setValues([2, 35]);
+ const spySave = jest.spyOn(editor, 'save');
+ const editorLeftElm = editor.editorDomElement.leftInput;
+
+ editorLeftElm.dispatchEvent(new (window.window as any).Event('focusout'));
+
+ setTimeout(() => {
+ expect(spyGetEditor).toHaveBeenCalled();
+ expect(spyCommit).toHaveBeenCalled();
+ expect(spySave).toHaveBeenCalled();
+ done();
+ }, 0);
+ });
+
+ it('should call "getEditorLock" and "save" methods when "hasAutoCommitEdit" is enabled and the right input event "focusout" is triggered', (done) => {
+ mockItemData = { id: 1, range: '3-32', from: 3, to: 32, isActive: true };
+ gridOptionMock.autoCommitEdit = true;
+ const spyGetEditor = jest.spyOn(gridStub, 'getEditorLock');
+ const spyCommit = jest.spyOn(gridStub.getEditorLock(), 'commitCurrentEdit');
+
+ editor = new DualInputEditor(editorArguments);
+ editor.loadValue(mockItemData);
+ editor.setValues([2, 35]);
+ const spySave = jest.spyOn(editor, 'save');
+ const editorRightElm = editor.editorDomElement.rightInput;
+
+ editorRightElm.dispatchEvent(new (window.window as any).Event('focusout'));
+
+ setTimeout(() => {
+ expect(spyGetEditor).toHaveBeenCalled();
+ expect(spyCommit).toHaveBeenCalled();
+ expect(spySave).toHaveBeenCalled();
+ done();
+ }, 0);
+ });
+ });
+
+ describe('validate method', () => {
+ it('should set isValueSaveCalled to true when grid object triggered an "onValidationError"', () => {
+ editor = new DualInputEditor(editorArguments);
+ jest.spyOn(editor.eventHandler, 'subscribe');
+
+ expect(editor.eventHandler).toBeTruthy();
+ expect(editor.isValueSaveCalled).toBe(false);
+ gridStub.onValidationError.notify({ row: 0, cell: 0, validationResults: { valid: false, msg: 'Field is required' } });
+ expect(editor.isValueSaveCalled).toBe(true);
+ });
+
+ it('should return False when field is required and field is empty', () => {
+ mockColumn.internalColumnEditor.params.leftInput.required = true;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: '' });
+
+ expect(validation).toEqual({ valid: false, msg: 'Field is required' });
+ });
+
+ it('should return False when left input field is required and its value is empty when set by "setValues"', () => {
+ mockColumn.internalColumnEditor.params.leftInput.required = true;
+ editor = new DualInputEditor(editorArguments);
+ editor.setValues(['', 3]);
+ const validation = editor.validate();
+
+ expect(validation).toEqual({ valid: false, msg: 'Field is required' });
+ });
+
+ it('should return False when left input field is required and its value is empty when set by "setValues"', () => {
+ mockColumn.internalColumnEditor.params.rightInput.required = true;
+ editor = new DualInputEditor(editorArguments);
+ editor.setValues([2, '']);
+ const validation = editor.validate();
+
+ expect(validation).toEqual({ valid: false, msg: 'Field is required' });
+ });
+
+ it('should return False when editor is float but its field is not a valid float number', () => {
+ mockColumn.internalColumnEditor.params.rightInput.required = true;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'rightInput', inputValue: 'abc' });
+
+ expect(validation).toEqual({ valid: false, msg: 'Please enter a valid number' });
+ });
+
+ it('should return False when editor is integer but its field is not a valid integer number', () => {
+ mockColumn.internalColumnEditor.params.rightInput.type = 'integer';
+ mockColumn.internalColumnEditor.params.rightInput.required = true;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'rightInput', inputValue: 'abc' });
+
+ expect(validation).toEqual({ valid: false, msg: 'Please enter a valid integer number' });
+ });
+
+ it('should return False when editor is a required text input but its text value is not provided', () => {
+ mockColumn.internalColumnEditor.params.rightInput.type = 'text';
+ mockColumn.internalColumnEditor.params.rightInput.required = true;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'rightInput', inputValue: '' });
+
+ expect(validation).toEqual({ valid: false, msg: 'Field is required' });
+ });
+
+ it('should return False when editor is a required password input but its text value is not provided', () => {
+ mockColumn.internalColumnEditor.params.rightInput.type = 'password';
+ mockColumn.internalColumnEditor.params.rightInput.required = true;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'rightInput', inputValue: '' });
+
+ expect(validation).toEqual({ valid: false, msg: 'Field is required' });
+ });
+
+ it('should return False when field is lower than a minValue defined', () => {
+ mockColumn.internalColumnEditor.params.leftInput.minValue = 10.2;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: 10 });
+
+ expect(validation).toEqual({ valid: false, msg: 'Please enter a valid number that is greater than 10.2' });
+ });
+
+ it('should return True when field is equal to the minValue defined', () => {
+ mockColumn.internalColumnEditor.params.rightInput.minValue = 10.2;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'rightInput', inputValue: 10.2 });
+
+ expect(validation).toEqual({ valid: true, msg: '' });
+ });
+
+ it('should return False when field is greater than a maxValue defined', () => {
+ mockColumn.internalColumnEditor.params.leftInput.maxValue = 10.2;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: 10.22 });
+
+ expect(validation).toEqual({ valid: false, msg: 'Please enter a valid number that is lower than 10.2' });
+ });
+
+ it('should return True when field is equal to the maxValue defined', () => {
+ mockColumn.internalColumnEditor.params.rightInput.type = 'float';
+ mockColumn.internalColumnEditor.params.rightInput.maxValue = 10.2;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'rightInput', inputValue: 10.2 });
+
+ expect(validation).toEqual({ valid: true, msg: '' });
+ });
+
+ it('should return True when type is set to float and its field is equal to the maxValue defined and "operatorType" is set to "inclusive"', () => {
+ mockColumn.internalColumnEditor.params.rightInput.type = 'float';
+ mockColumn.internalColumnEditor.params.leftInput.maxValue = 10.2;
+ mockColumn.internalColumnEditor.params.leftInput.operatorConditionalType = 'inclusive';
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: 10.2 });
+
+ expect(validation).toEqual({ valid: true, msg: '' });
+ });
+
+ it('should return True when type is set to integer and its field is equal to the maxValue defined and "operatorType" is set to "inclusive"', () => {
+ mockColumn.internalColumnEditor.params.leftInput.type = 'integer';
+ mockColumn.internalColumnEditor.params.leftInput.maxValue = 11;
+ mockColumn.internalColumnEditor.params.leftInput.operatorConditionalType = 'inclusive';
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: 11 });
+
+ expect(validation).toEqual({ valid: true, msg: '' });
+ });
+
+ it('should return False when type is set to float and its field is equal to the maxValue defined but "operatorType" is set to "exclusive"', () => {
+ mockColumn.internalColumnEditor.params.rightInput.type = 'float';
+ mockColumn.internalColumnEditor.params.rightInput.maxValue = 10.2;
+ mockColumn.internalColumnEditor.params.rightInput.operatorConditionalType = 'exclusive';
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'rightInput', inputValue: 10.2 });
+
+ expect(validation).toEqual({ valid: false, msg: 'Please enter a valid number that is lower than 10.2' });
+ });
+
+ it('should return False when type is set to float and its field is equal to the maxValue defined but "operatorType" is set to "exclusive"', () => {
+ mockColumn.internalColumnEditor.params.rightInput.type = 'integer';
+ mockColumn.internalColumnEditor.params.rightInput.maxValue = 11;
+ mockColumn.internalColumnEditor.params.rightInput.operatorConditionalType = 'exclusive';
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'rightInput', inputValue: 11 });
+
+ expect(validation).toEqual({ valid: false, msg: 'Please enter a valid integer number that is lower than 11' });
+ });
+
+ it('should return False when type is set to float and its field is not between minValue & maxValue defined', () => {
+ mockColumn.internalColumnEditor.params.leftInput.minValue = 10.5;
+ mockColumn.internalColumnEditor.params.leftInput.maxValue = 99.5;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: 99.6 });
+
+ expect(validation).toEqual({ valid: false, msg: 'Please enter a valid number between 10.5 and 99.5' });
+ });
+
+ it('should return False when type is set to integer and its field is not between minValue & maxValue defined', () => {
+ mockColumn.internalColumnEditor.params.leftInput.type = 'integer';
+ mockColumn.internalColumnEditor.params.leftInput.minValue = 11;
+ mockColumn.internalColumnEditor.params.leftInput.maxValue = 99;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: 100 });
+
+ expect(validation).toEqual({ valid: false, msg: 'Please enter a valid integer number between 11 and 99' });
+ });
+
+ it('should return True when field is is equal to maxValue defined when both min/max values are defined', () => {
+ mockColumn.internalColumnEditor.params.rightInput.minValue = 10.5;
+ mockColumn.internalColumnEditor.params.rightInput.maxValue = 99.5;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'rightInput', inputValue: 99.5 });
+
+ expect(validation).toEqual({ valid: true, msg: '' });
+ });
+
+ it('should return True when field is is equal to minValue defined when "operatorType" is set to "inclusive" and both min/max values are defined', () => {
+ mockColumn.internalColumnEditor.params.leftInput.minValue = 10.5;
+ mockColumn.internalColumnEditor.params.leftInput.maxValue = 99.5;
+ mockColumn.internalColumnEditor.params.leftInput.operatorConditionalType = 'inclusive';
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: 10.5 });
+
+ expect(validation).toEqual({ valid: true, msg: '' });
+ });
+
+ it('should return False when field is equal to maxValue but "operatorType" is set to "exclusive" when both min/max values are defined', () => {
+ mockColumn.internalColumnEditor.params.rightInput.minValue = 10.5;
+ mockColumn.internalColumnEditor.params.rightInput.maxValue = 99.5;
+ mockColumn.internalColumnEditor.params.rightInput.operatorConditionalType = 'exclusive';
+ editor = new DualInputEditor(editorArguments);
+ const validation1 = editor.validate({ position: 'rightInput', inputValue: 99.5 });
+ const validation2 = editor.validate({ position: 'rightInput', inputValue: 10.5 });
+
+ expect(validation1).toEqual({ valid: false, msg: 'Please enter a valid number between 10.5 and 99.5' });
+ expect(validation2).toEqual({ valid: false, msg: 'Please enter a valid number between 10.5 and 99.5' });
+ });
+
+ it('should return False when field has more decimals than the "decimal" which is the maximum decimal allowed', () => {
+ mockColumn.internalColumnEditor.params.leftInput.decimal = 2;
+
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: 99.6433 });
+
+ expect(validation).toEqual({ valid: false, msg: 'Please enter a valid number with a maximum of 2 decimals' });
+ });
+
+ it('should return True when field has less decimals than the "decimal" which is valid', () => {
+ mockColumn.internalColumnEditor.params.rightInput.decimal = 2;
+
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'rightInput', inputValue: 99.6 });
+
+ expect(validation).toEqual({ valid: true, msg: '' });
+ });
+
+ it('should return True when field has same number of decimals than the "decimal" which is also valid', () => {
+ mockColumn.internalColumnEditor.params.leftInput.decimal = 2;
+
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: 99.65 });
+
+ expect(validation).toEqual({ valid: true, msg: '' });
+ });
+
+ it('should return True when field is required and field is a valid input value', () => {
+ mockColumn.internalColumnEditor.params.rightInput.required = true;
+ editor = new DualInputEditor(editorArguments);
+ const validation = editor.validate({ position: 'leftInput', inputValue: 2.5 });
+
+ expect(validation).toEqual({ valid: true, msg: '' });
+ });
+ });
+ });
+});
diff --git a/packages/common/src/editors/dualInputEditor.ts b/packages/common/src/editors/dualInputEditor.ts
index e0c70961a..806bde43d 100644
--- a/packages/common/src/editors/dualInputEditor.ts
+++ b/packages/common/src/editors/dualInputEditor.ts
@@ -71,9 +71,8 @@ export class DualInputEditor implements Editor {
return this.grid.getOptions().autoCommitEdit;
}
- /** Get the Validator function, can be passed in Editor property or Column Definition */
- get validator(): EditorValidator | undefined {
- return (this.columnEditor && this.columnEditor.validator) || (this.columnDef && this.columnDef.validator);
+ get isValueSaveCalled(): boolean {
+ return this._isValueSaveCalled;
}
init() {
@@ -91,8 +90,8 @@ export class DualInputEditor implements Editor {
containerElm.appendChild(this._rightInput);
}
- this._leftInput.onkeydown = this.handleKeyDown;
- this._rightInput.onkeydown = this.handleKeyDown;
+ this._leftInput.onkeydown = this.handleKeyDown.bind(this);
+ this._rightInput.onkeydown = this.handleKeyDown.bind(this);
// the lib does not get the focus out event for some reason, so register it here
if (this.hasAutoCommitEdit) {
@@ -106,7 +105,7 @@ export class DualInputEditor implements Editor {
handleFocusOut(event: any, position: 'leftInput' | 'rightInput') {
// when clicking outside the editable cell OR when focusing out of it
const targetClassNames = event.relatedTarget?.className || '';
- if (targetClassNames.indexOf('compound-editor') === -1 && this._lastEventType !== 'focusout-right') {
+ if (targetClassNames.indexOf('dual-editor') === -1 && this._lastEventType !== 'focusout-right') {
if (position === 'rightInput' || (position === 'leftInput' && this._lastEventType !== 'focusout-left')) {
this.save();
}
@@ -127,10 +126,9 @@ export class DualInputEditor implements Editor {
this._eventHandler.unsubscribeAll();
const columnId = this.columnDef && this.columnDef.id;
- const elm = document.querySelector(`.compound-editor-text.editor-${columnId}`);
- if (elm) {
- this._leftInput.removeEventListener('focusout', () => { });
- this._rightInput.removeEventListener('focusout', () => { });
+ const elements = document.querySelectorAll(`.dual-editor-text.editor-${columnId}`);
+ if (elements.length > 0) {
+ elements.forEach((elm) => elm.removeEventListener('focusout', () => { }));
}
}
@@ -146,7 +144,7 @@ export class DualInputEditor implements Editor {
const input = document.createElement('input') as HTMLInputElement;
input.id = `item-${itemId}`;
- input.className = `compound-editor-text editor-${columnId} ${position.replace(/input/gi, '')}`;
+ input.className = `dual-editor-text editor-${columnId} ${position.replace(/input/gi, '')}`;
input.type = fieldType || 'text';
input.setAttribute('role', 'presentation');
input.autocomplete = 'off';
@@ -165,12 +163,18 @@ export class DualInputEditor implements Editor {
// do nothing since we have 2 inputs and we might focus on left/right depending on which is invalid or new
}
- getValue(): string {
- return this._leftInput.value || '';
+ getValue(): Array {
+ return [
+ this._leftInput.value || '',
+ this._rightInput.value || ''
+ ];
}
- setValue(value: string) {
- this._leftInput.value = value;
+ setValues(values: Array) {
+ if (Array.isArray(values) && values.length === 2) {
+ this._leftInput.value = `${values[0]}`;
+ this._rightInput.value = `${values[1]}`;
+ }
}
applyValue(item: any, state: any) {
@@ -183,15 +187,23 @@ export class DualInputEditor implements Editor {
if (fieldName !== undefined) {
const isComplexObject = fieldName && fieldName.indexOf('.') > 0; // is the field a complex object, "address.streetNumber"
+ let fieldNameToUse = fieldName;
+ if (isComplexObject) {
+ const complexFieldNames = fieldName.split(/\.(.*)/);
+ fieldNameToUse = (complexFieldNames.length > 1 ? complexFieldNames[1] : complexFieldNames) as string;
+ }
+
// validate the value before applying it (if not valid we'll set an empty string)
- const validation = this.validate();
- const newValue = (validation && validation.valid) ? state[fieldName] : '';
+ const stateValue = isComplexObject ? getDescendantProperty(state, fieldNameToUse) : state[fieldName];
+ const validation = this.validate({ position, inputValue: stateValue });
// set the new value to the item datacontext
if (isComplexObject) {
+ const newValueFromComplex = getDescendantProperty(state, fieldNameToUse);
+ const newValue = (validation && validation.valid) ? newValueFromComplex : '';
setDeepValue(item, fieldName, newValue);
} else if (fieldName) {
- item[fieldName] = newValue;
+ item[fieldName] = (validation && validation.valid) ? state[fieldName] : '';
}
}
}
@@ -199,8 +211,10 @@ export class DualInputEditor implements Editor {
isValueChanged(): boolean {
const leftElmValue = this._leftInput.value;
const rightElmValue = this._rightInput.value;
+ const leftEditorParams = this.editorParams && this.editorParams.leftInput;
+ const rightEditorParams = this.editorParams && this.editorParams.rightInput;
const lastKeyEvent = this._lastInputKeyEvent && this._lastInputKeyEvent.keyCode;
- if (this.columnEditor && this.columnEditor.alwaysSaveOnEnterKey && lastKeyEvent === KeyCode.ENTER) {
+ if ((leftEditorParams && leftEditorParams.alwaysSaveOnEnterKey || rightEditorParams && rightEditorParams.alwaysSaveOnEnterKey) && lastKeyEvent === KeyCode.ENTER) {
return true;
}
const leftResult = (!(leftElmValue === '' && this.originalLeftValue === null)) && (leftElmValue !== this.originalLeftValue);
@@ -222,7 +236,7 @@ export class DualInputEditor implements Editor {
const isComplexObject = fieldName && fieldName.indexOf('.') > 0;
if (item && fieldName !== undefined && this.columnDef && (item.hasOwnProperty(fieldName) || isComplexObject)) {
- const itemValue = (isComplexObject) ? getDescendantProperty(item, fieldName) : (item.hasOwnProperty(fieldName) && item[fieldName] || '');
+ const itemValue = (isComplexObject) ? getDescendantProperty(item, fieldName) : (item.hasOwnProperty(fieldName) ? item[fieldName] : '');
this[originalValuePosition] = itemValue;
if (this.editorParams[position].type === 'float') {
const decimalPlaces = this.getDecimalPlaces(position);
@@ -230,14 +244,15 @@ export class DualInputEditor implements Editor {
this[originalValuePosition] = (+this[originalValuePosition]).toFixed(decimalPlaces);
}
}
- this[inputVarPosition].value = `${this[originalValuePosition]}`;
+ if (this[inputVarPosition]) {
+ this[inputVarPosition].value = `${this[originalValuePosition]}`;
+ }
}
}
save() {
const validation = this.validate();
const isValid = (validation && validation.valid) || false;
- const isChanged = this.isValueChanged();
if (!this._isValueSaveCalled) {
if (this.hasAutoCommitEdit && isValid) {
@@ -250,10 +265,14 @@ export class DualInputEditor implements Editor {
}
serializeValue() {
- return {
- [this._leftFieldName]: this.serializeValueByPosition('leftInput'),
- [this._rightFieldName]: this.serializeValueByPosition('rightInput')
- };
+ const obj = {};
+ const leftValue = this.serializeValueByPosition('leftInput');
+ const rightValue = this.serializeValueByPosition('rightInput');
+
+ setDeepValue(obj, this._leftFieldName, leftValue);
+ setDeepValue(obj, this._rightFieldName, rightValue);
+
+ return obj;
}
serializeValueByPosition(position: 'leftInput' | 'rightInput') {
@@ -277,7 +296,7 @@ export class DualInputEditor implements Editor {
// returns the number of fixed decimal places or null
const positionSide = position === 'leftInput' ? 'leftInput' : 'rightInput';
const sideParams = this.editorParams[positionSide];
- let rtn: number | undefined = sideParams?.decimal;
+ const rtn: number | undefined = sideParams?.decimal;
if (rtn === undefined) {
return defaultDecimalPlaces;
@@ -298,25 +317,38 @@ export class DualInputEditor implements Editor {
return '1';
}
- validate(): EditorValidatorOutput {
- const leftValidation = this.validateByPosition('leftInput');
- const rightValidation = this.validateByPosition('rightInput');
+ validate(inputValidation?: { position: 'leftInput' | 'rightInput', inputValue: any }): EditorValidatorOutput {
+ if (inputValidation) {
+ const posValidation = this.validateByPosition(inputValidation.position, inputValidation.inputValue);
+ if (!posValidation.valid) {
+ inputValidation.position === 'leftInput' ? this._leftInput.select() : this._rightInput.select();
+ return posValidation;
+ }
+ } else {
+ const leftValidation = this.validateByPosition('leftInput');
+ const rightValidation = this.validateByPosition('rightInput');
- if (!leftValidation.valid) {
- this._leftInput.select();
- return leftValidation;
- }
- if (!rightValidation.valid) {
- this._rightInput.select();
- return rightValidation;
+ if (!leftValidation.valid) {
+ this._leftInput.select();
+ return leftValidation;
+ }
+ if (!rightValidation.valid) {
+ this._rightInput.select();
+ return rightValidation;
+ }
}
- return { valid: true, msg: null };
+ return { valid: true, msg: '' };
}
- validateByPosition(position: 'leftInput' | 'rightInput'): EditorValidatorOutput {
+ validateByPosition(position: 'leftInput' | 'rightInput', inputValue?: any): EditorValidatorOutput {
const positionEditorParams = this.editorParams[position];
- const input = position === 'leftInput' ? this._leftInput : this._rightInput;
- const currentVal = input?.value;
+ let currentVal = '';
+ if (inputValue) {
+ currentVal = inputValue;
+ } else {
+ const input = position === 'leftInput' ? this._leftInput : this._rightInput;
+ currentVal = input && input.value;
+ }
const baseValidatorOptions = {
editorArgs: this.args,
errorMessage: positionEditorParams.errorMessage,
diff --git a/packages/common/src/services/utilities.ts b/packages/common/src/services/utilities.ts
index d9707ee7a..f8c80f190 100644
--- a/packages/common/src/services/utilities.ts
+++ b/packages/common/src/services/utilities.ts
@@ -723,14 +723,14 @@ export function setDeepValue(obj: any, path: string | string[], value: any) {
if (path.length > 1) {
const e = path.shift();
- if (obj && e !== undefined && obj.hasOwnProperty(e)) {
+ if (obj && e !== undefined) {
setDeepValue(
obj[e] = Object.prototype.toString.call(obj[e]) === '[object Object]' ? obj[e] : {},
path,
value
);
}
- } else if (obj && path[0] && obj.hasOwnProperty(path[0])) {
+ } else if (obj && path[0]) {
obj[path[0]] = value;
}
}
diff --git a/packages/common/src/styles/slick-default-theme.scss b/packages/common/src/styles/slick-default-theme.scss
index 5d8057e42..2946c3548 100644
--- a/packages/common/src/styles/slick-default-theme.scss
+++ b/packages/common/src/styles/slick-default-theme.scss
@@ -92,7 +92,7 @@
transform: translate(0, -2px);
}
- input.compound-editor-text {
+ input.dual-editor-text {
width: calc(50% + 1px - 5px); // 1px (is 2px / 2) and 5px (is space between the 2 inputs)
height: 100%;
outline: 0;
diff --git a/packages/common/src/styles/slick-editors.scss b/packages/common/src/styles/slick-editors.scss
index b5b044366..aaeb3b98d 100644
--- a/packages/common/src/styles/slick-editors.scss
+++ b/packages/common/src/styles/slick-editors.scss
@@ -3,7 +3,7 @@
.slick-row {
.slick-cell {
&.active {
- input.compound-editor-text,
+ input.dual-editor-text,
input.editor-text {
border: $text-editor-border;
border-radius: $text-editor-border-radius;
diff --git a/packages/web-demo-vanilla-bundle/package.json b/packages/web-demo-vanilla-bundle/package.json
index ee9b265b5..580ea3886 100644
--- a/packages/web-demo-vanilla-bundle/package.json
+++ b/packages/web-demo-vanilla-bundle/package.json
@@ -33,13 +33,13 @@
"moment-mini": "^2.24.0"
},
"devDependencies": {
- "@types/jquery": "^3.3.35",
+ "@types/jquery": "^3.3.36",
"@types/moment": "^2.13.0",
- "@types/node": "^13.13.2",
+ "@types/node": "^13.13.4",
"@types/webpack": "^4.41.12",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^5.1.1",
- "css-loader": "^3.5.2",
+ "css-loader": "^3.5.3",
"file-loader": "^6.0.0",
"fork-ts-checker-webpack-plugin": "^4.1.3",
"html-loader": "^1.1.0",
@@ -48,9 +48,9 @@
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "4.14.0",
"sass-loader": "^8.0.2",
- "style-loader": "^1.1.4",
- "ts-loader": "^7.0.1",
- "ts-node": "^8.9.0",
+ "style-loader": "^1.2.1",
+ "ts-loader": "^7.0.2",
+ "ts-node": "^8.9.1",
"typescript": "^3.8.3",
"url-loader": "^4.1.0",
"webpack": "^4.43.0",