UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

147 lines (146 loc) 5.61 kB
import * as React from 'react'; import { renderWithAdaptableContext } from '../../../View/renderWithAdaptableContext'; import { InternalAdaptableNumberEditor, } from './InternalAdaptableNumberEditor'; import { KeyCode } from 'ag-grid-enterprise'; import { forwardRef, useImperativeHandle, useRef, useState } from 'react'; function shouldClearExistingValue(params) { return params.eventKey === KeyCode.BACKSPACE || params.eventKey === KeyCode.DELETE; } function isValidChar(char) { // allow only digits return ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].includes(char); // we do NOT allow key shortcuts for starting non-digits (minus sign, decimal separators) as the input[number] handling is very buggy and we would open a can of worms } export function getStartValue(params) { if (shouldClearExistingValue(params)) { return ''; } if (params.eventKey && isValidChar(params.eventKey)) { return Number(params.eventKey); } return params.value; } const defaultValueParser = ({ newValue, oldValue: _ }) => { return newValue; }; const style = { position: 'absolute', top: '0px', left: '0px', right: '0px', bottom: '0px', }; export const AdaptableReactNumberEditor = forwardRef((props, ref) => { const [initialValue] = useState(() => getStartValue(props)); const valueRef = useRef(initialValue); const columnId = props.column.getColId(); const adaptable = props.context.__adaptable; const colValueParser = props.column.getColDef().valueParser; const valueParser = typeof colValueParser === 'function' ? colValueParser : defaultValueParser; function onValueChange(value) { value = valueParser ? valueParser({ ...props, oldValue: props.value, newValue: value, }) : value; valueRef.current = value; props.onValueChange?.(value); } const editorRef = useRef(null); useImperativeHandle(ref, () => { return { focusIn() { editorRef.current?.focus(); }, // the final value to send to the grid, on completion of editing getValue() { return valueRef.current; }, }; }); const editorElement = (React.createElement(InternalAdaptableNumberEditor, { defaultValue: initialValue, showClearButton: props.showClearButton ?? true, emptyValue: props.emptyValue ?? '', onValueChange: onValueChange, ref: (editor) => { editorRef.current = editor; editor?.focus(); } })); function onKeyDown(keyDownEvent) { adaptable._emit('CellEditorKeyDown', { keyDownEvent, cellValue: valueRef.current, columnId, updateValueCallback: (updatedValue) => { editorRef.current.setValue(updatedValue); }, }); } return (React.createElement("div", { style: style, onKeyDown: onKeyDown }, renderWithAdaptableContext(editorElement, adaptable))); }); AdaptableReactNumberEditor.displayName = 'AdaptableReactNumberEditor'; /** * Number Editor provided by AdapTable and used by default for all `number` columns */ export class AdaptableNumberEditor { constructor() { this.valueParser = defaultValueParser; this.onValueChange = (value) => { this.value = this.valueParser ? this.valueParser({ ...this.params, oldValue: this.params.value, newValue: value, }) : value; }; } init(params) { this.value = getStartValue(params); this.params = params; this.columnId = params.column.getColId(); const { valueParser } = params.column.getColDef(); if (typeof valueParser === 'function') { this.valueParser = valueParser; } this.el = document.createElement('div'); Object.keys(style).forEach((key) => { //@ts-ignore this.el.style[key] = style[key]; }); } /* Component Editor Lifecycle methods */ // gets called once when grid ready to insert the element getGui() { return this.el; } // the final value to send to the grid, on completion of editing getValue() { return this.value; } focusIn() { this.editor?.focus(); } focusOut() { } // after this component has been created and inserted into the grid afterGuiAttached() { const adaptable = this.params.context.__adaptable; const defaultValue = this.value; const editorElement = (React.createElement(InternalAdaptableNumberEditor, { defaultValue: defaultValue, showClearButton: this.params.showClearButton ?? true, emptyValue: this.params.emptyValue ?? '', onValueChange: this.onValueChange, ref: (editor) => { this.editor = editor; editor?.focus(); } })); this.unmountReactRoot = adaptable.renderReactRoot(renderWithAdaptableContext(editorElement, adaptable), this.el); this.getGui().addEventListener('keydown', (keyDownEvent) => { adaptable._emit('CellEditorKeyDown', { keyDownEvent, cellValue: this.value, columnId: this.columnId, updateValueCallback: (updatedValue) => { this.editor.setValue(updatedValue); }, }); }); } destroy() { this.unmountReactRoot?.(); } }