floatLineComponent.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import * as React from "react";
  2. import { Observable } from "babylonjs/Misc/observable";
  3. import { PropertyChangedEvent } from "./propertyChangedEvent";
  4. import { GlobalState } from '../globalState';
  5. interface IFloatLineComponentProps {
  6. label: string;
  7. target: any;
  8. propertyName: string;
  9. onChange?: (newValue: number) => void;
  10. isInteger?: boolean;
  11. onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
  12. additionalClass?: string;
  13. step?: string,
  14. digits?: number;
  15. globalState: GlobalState
  16. }
  17. export class FloatLineComponent extends React.Component<IFloatLineComponentProps, { value: string }> {
  18. private _localChange = false;
  19. private _store: number;
  20. constructor(props: IFloatLineComponentProps) {
  21. super(props);
  22. let currentValue = this.props.target[this.props.propertyName];
  23. this.state = { value: currentValue ? (this.props.isInteger ? currentValue.toFixed(0) : currentValue.toFixed(this.props.digits || 2)) : "0" };
  24. this._store = currentValue;
  25. }
  26. shouldComponentUpdate(nextProps: IFloatLineComponentProps, nextState: { value: string }) {
  27. if (this._localChange) {
  28. this._localChange = false;
  29. return true;
  30. }
  31. const newValue = nextProps.target[nextProps.propertyName];
  32. const newValueString = newValue ? this.props.isInteger ? newValue.toFixed(0) : newValue.toFixed(this.props.digits || 2) : "0";
  33. if (newValueString !== nextState.value) {
  34. nextState.value = newValueString;
  35. return true;
  36. }
  37. return false;
  38. }
  39. raiseOnPropertyChanged(newValue: number, previousValue: number) {
  40. if (this.props.onChange) {
  41. this.props.onChange(newValue);
  42. }
  43. if (!this.props.onPropertyChangedObservable) {
  44. return;
  45. }
  46. this.props.onPropertyChangedObservable.notifyObservers({
  47. object: this.props.target,
  48. property: this.props.propertyName,
  49. value: newValue,
  50. initialValue: previousValue
  51. });
  52. }
  53. updateValue(valueString: string) {
  54. if (/[^0-9\.\-]/g.test(valueString)) {
  55. return;
  56. }
  57. valueString = valueString.replace(/(.+\...).+/, "$1");
  58. let valueAsNumber: number;
  59. if (this.props.isInteger) {
  60. valueAsNumber = parseInt(valueString);
  61. } else {
  62. valueAsNumber = parseFloat(valueString);
  63. }
  64. this._localChange = true;
  65. this.setState({ value: valueString});
  66. if (isNaN(valueAsNumber)) {
  67. return;
  68. }
  69. this.props.target[this.props.propertyName] = valueAsNumber;
  70. this.raiseOnPropertyChanged(valueAsNumber, this._store);
  71. this._store = valueAsNumber;
  72. }
  73. render() {
  74. return (
  75. <div>
  76. {
  77. <div className={this.props.additionalClass ? this.props.additionalClass + " floatLine" : "floatLine"}>
  78. <div className="label">
  79. {this.props.label}
  80. </div>
  81. <div className="value">
  82. <input type="number" step={this.props.step || "0.01"} className="numeric-input"
  83. onBlur={evt => {
  84. this.props.globalState.blockKeyboardEvents = false;
  85. }}
  86. onFocus={() => this.props.globalState.blockKeyboardEvents = true}
  87. value={this.state.value} onChange={evt => this.updateValue(evt.target.value)} />
  88. </div>
  89. </div>
  90. }
  91. </div>
  92. );
  93. }
  94. }