]> git.wincent.com - hextrapolate.git/blob - src/Field.react.js
6bc42c27b8104030fb779643f304038f4fd55ba1
[hextrapolate.git] / src / Field.react.js
1 /**
2  * Copyright 2015-present Greg Hurrell. All rights reserved.
3  * Licensed under the terms of the MIT license.
4  *
5  * @flow
6  */
7
8 'use strict';
9
10 import React from 'react';
11 import convert from './convert';
12
13 const DIGITS = '0123456789abcdef';
14
15 /**
16  * Convert from canonical (hexadecimal) value to `base`.
17  */
18 function fromValue(value: string, base: number): string {
19   if (base === 16) {
20     return value;
21   }
22   return convert(value, 16, base);
23 }
24
25 /**
26  * Convert from `base` value to canonical (hexadecimal) value.
27  */
28 function toValue(value: string, base: number): string {
29   if (base === 16) {
30     return value;
31   }
32   return convert(value, base, 16);
33 }
34
35 export default class Field extends React.Component {
36   static propTypes = {
37     base: React.PropTypes.number,
38     onValueChange: React.PropTypes.func.required,
39     value: React.PropTypes.string.required,
40   };
41   static defaultProps = {
42     base: 10,
43   };
44
45   constructor(props) {
46     super(props);
47     if (props.base < 2 || props.base > DIGITS.length) {
48       throw new Error(
49         `base prop must be between 2..${DIGITS.length}`
50       );
51     }
52   }
53
54   _isValid(value: string): boolean {
55     const validator = new RegExp(
56       `^[${DIGITS.slice(0, this.props.base)}]*$`
57     );
58     return validator.test(value.trim().toLowerCase());
59   }
60
61   _onChange = event => {
62     const value = event.currentTarget.value;
63     if (this._isValid(value)) {
64       this.props.onValueChange(toValue(value, this.props.base));
65     }
66   }
67
68   render() {
69     return (
70       <input
71         onChange={this._onChange}
72         type="text"
73         value={fromValue(this.props.value, this.props.base)}
74       />
75     );
76   }
77 }