Skip to content

Commit 9499d73

Browse files
authored
Merge pull request #55 from Suntgr/feature/big-number
feat: Enhance VariableEditor to support BigNumber type handling
2 parents 64d98a1 + 86c14ce commit 9499d73

File tree

11 files changed

+89
-20
lines changed

11 files changed

+89
-20
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ import ReactJsonView from '@microlink/react-json-view'
5151
'last-child': null
5252
},
5353
string_number: '1234',
54-
date: new Date()
54+
date: new Date(),
55+
bigNumber: new BigNumber('0.0060254656709730629123')
5556
}} />
5657
```
5758

@@ -81,7 +82,8 @@ import ReactJsonView from '@microlink/react-json-view'
8182
| `quotesOnKeys` | `boolean` | `true` | Set to `false` to remove quotes from keys (e.g., `"name":` vs. `name:`). |
8283
| `validationMessage` | `string` | "Validation Error" | Custom message for validation failures to `onEdit`, `onAdd`, or `onDelete` callbacks. |
8384
| `displayArrayKey` | `boolean` | `true` | When set to `true`, the index of the elements prefix values. |
84-
| `escapeStrings` | `boolean` | `true` | When set to `true`, strings sequences such as \n, \t, \r, \f will be escaped. |
85+
| `escapeStrings` | `boolean` | `true` | When set to `true`, strings sequences such as \n, \t, \r, \f will be escaped. |
86+
| `bigNumber` | `Class` | `null` | A custom class for handling large numbers. The class should have a constructor that accepts a numeric string/value and a `name` property for display purposes. You can use existing libraries like `bignumber.js`, `decimal.js`, `big.js`, or provide your own implementation. |
8587

8688
#### Callbacks
8789

dev-server/src/index.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,23 @@ import Moment from 'moment'
99
//import the react-json-view component (installed with npm)
1010
import JsonViewer from './../../src/js/index'
1111

12+
// custom big number class, You can use existing libraries like `bignumber.js`, `decimal.js`, `big.js` etc.
13+
class BigNumber {
14+
name = 'customName'
15+
constructor(value) {
16+
this.value = value
17+
}
18+
toString() {
19+
return this.value.toString()
20+
}
21+
}
22+
1223
//render 2 different examples of the react-json-view component
1324
ReactDom.render(
1425
<div>
1526
{/* just pass in your JSON to the src attribute */}
1627
<JsonViewer
28+
bigNumber={BigNumber}
1729
sortKeys
1830
style={{ padding: '30px', backgroundColor: 'white' }}
1931
src={getExampleJson1()}
@@ -59,6 +71,7 @@ ReactDom.render(
5971
{/* use a base16 theme */}
6072
<JsonViewer
6173
src={getExampleJson1()}
74+
bigNumber={BigNumber}
6275
theme='railscasts'
6376
validationMessage="You're doing something wrong."
6477
collapseStringsAfterLength={15}
@@ -139,6 +152,7 @@ ReactDom.render(
139152
<JsonViewer
140153
enableClipboard={false}
141154
src={getExampleJson1()}
155+
bigNumber={BigNumber}
142156
shouldCollapse={({ src, namespace, type }) =>
143157
namespace.indexOf('moment') > -1
144158
}
@@ -220,7 +234,8 @@ function getExampleJson1 () {
220234
string_number: '1234',
221235
date: new Date(),
222236
moment: Moment(),
223-
regexp: /[0-9]/gi
237+
regexp: /[0-9]/gi,
238+
bigNumber: new BigNumber('0.0060254656709730629123')
224239
}
225240
}
226241

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React from 'react'
2+
import DataTypeLabel from './DataTypeLabel'
3+
4+
// theme
5+
import Theme from './../../themes/getStyle'
6+
7+
export default class extends React.PureComponent {
8+
render () {
9+
const type_name = 'bigNumber'
10+
const { props } = this
11+
return (
12+
<div {...Theme(props.theme, 'bigNumber')}>
13+
<DataTypeLabel type_name={type_name} {...props} />
14+
{this.props.value.toString()}
15+
</div>
16+
)
17+
}
18+
}

src/js/components/DataTypes/DataTypes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ export { default as JsonObject } from './Object'
99
export { default as JsonRegexp } from './Regexp'
1010
export { default as JsonString } from './String'
1111
export { default as JsonUndefined } from './Undefined'
12+
export { default as JsonBigNumber } from './BigNumber'

src/js/components/DataTypes/Object.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,12 @@ class RjvObject extends React.PureComponent {
245245
}
246246

247247
keys.forEach(name => {
248-
variable = new JsonVariable(name, variables[name])
248+
variable = new JsonVariable(name, variables[name], props.bigNumber)
249249

250250
if (parent_type === 'array_group' && index_offset) {
251251
variable.name = parseInt(variable.name) + index_offset
252252
}
253-
if (!variables.hasOwnProperty(name)) {
253+
if (!Object.prototype.hasOwnProperty.call(variables, name)) {
254254
} else if (variable.type === 'object') {
255255
elements.push(
256256
<JsonObject
@@ -286,6 +286,7 @@ class RjvObject extends React.PureComponent {
286286
/>
287287
)
288288
} else {
289+
// include bigNumber
289290
elements.push(
290291
<VariableEditor
291292
key={variable.name + '_' + namespace}
@@ -305,10 +306,10 @@ class RjvObject extends React.PureComponent {
305306

306307
// just store name, value and type with a variable
307308
class JsonVariable {
308-
constructor (name, value) {
309+
constructor (name, value, bigNumber) {
309310
this.name = name
310311
this.value = value
311-
this.type = toType(value)
312+
this.type = toType(value, bigNumber)
312313
}
313314
}
314315

src/js/components/VariableEditor.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import {
1818
JsonNull,
1919
JsonRegexp,
2020
JsonString,
21-
JsonUndefined
21+
JsonUndefined,
22+
JsonBigNumber
2223
} from './DataTypes/DataTypes'
2324

2425
// clibboard icon
@@ -166,8 +167,8 @@ class VariableEditor extends React.PureComponent {
166167

167168
prepopInput = variable => {
168169
if (this.props.onEdit !== false) {
169-
const stringifiedValue = stringifyVariable(variable.value)
170-
const detected = parseInput(stringifiedValue)
170+
const stringifiedValue = stringifyVariable(variable.value, this.props.bigNumber)
171+
const detected = parseInput(stringifiedValue, this.props.bigNumber)
171172
this.setState({
172173
editMode: true,
173174
editValue: stringifiedValue,
@@ -236,6 +237,8 @@ class VariableEditor extends React.PureComponent {
236237
return <JsonDate value={variable.value} {...props} />
237238
case 'regexp':
238239
return <JsonRegexp value={variable.value} {...props} />
240+
case 'bigNumber':
241+
return <JsonBigNumber value={variable.value} {...props} />
239242
default:
240243
// catch-all for types that weren't anticipated
241244
return <div class='object-value'>{JSON.stringify(variable.value)}</div>
@@ -259,7 +262,7 @@ class VariableEditor extends React.PureComponent {
259262
class='variable-editor'
260263
onChange={event => {
261264
const value = event.target.value
262-
const detected = parseInput(value)
265+
const detected = parseInput(value, this.props.bigNumber)
263266
this.setState({
264267
editValue: value,
265268
parsedInput: {
@@ -320,12 +323,15 @@ class VariableEditor extends React.PureComponent {
320323
}
321324

322325
submitEdit = submit_detected => {
323-
const { variable, namespace, rjvId } = this.props
326+
const { variable, namespace, rjvId, bigNumber: BigNumber } = this.props
324327
const { editValue, parsedInput } = this.state
325328
let new_value = editValue
326329
if (submit_detected && parsedInput.type) {
327330
new_value = parsedInput.value
328-
}
331+
if (BigNumber && parsedInput.type === 'bigNumber') {
332+
new_value = new BigNumber(new_value)
333+
}
334+
}
329335
this.setState({
330336
editMode: false
331337
})
@@ -456,6 +462,8 @@ class VariableEditor extends React.PureComponent {
456462
return <JsonUndefined {...props} />
457463
case 'date':
458464
return <JsonDate value={new Date(value)} {...props} />
465+
case 'bignumber':
466+
return <JsonBigNumber value={value} {...props} />
459467
}
460468
}
461469
}

src/js/helpers/parseInput.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
export default function parseInput (input) {
1+
export default function parseInput (input, bigNumber) {
22
// following code is to make a best guess at
33
// the type for a variable being submitted.
44

55
// we are working with a serialized data representation
66
input = input.trim()
77
try {
8-
input = JSON.stringify(JSON.parse(input))
8+
input = structuredClone(input)
99
if (input[0] === '[') {
1010
// array
1111
return formatResponse('array', JSON.parse(input))
@@ -16,6 +16,10 @@ export default function parseInput (input) {
1616
input.match(/\-?\d+\.\d+/) &&
1717
input.match(/\-?\d+\.\d+/)[0] === input
1818
) {
19+
// big number
20+
if (bigNumber && parseFloat(input).toString() !== input) {
21+
return formatResponse('bigNumber', input)
22+
}
1923
// float
2024
return formatResponse('float', parseFloat(input))
2125
} else if (
@@ -25,6 +29,10 @@ export default function parseInput (input) {
2529
// scientific float
2630
return formatResponse('float', Number(input))
2731
} else if (input.match(/\-?\d+/) && input.match(/\-?\d+/)[0] === input) {
32+
// big number
33+
if (bigNumber && parseInt(input).toString() !== input) {
34+
return formatResponse('bigNumber', input)
35+
}
2836
// integer
2937
return formatResponse('integer', parseInt(input))
3038
} else if (

src/js/helpers/stringifyVariable.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { toType } from './util'
22

3-
export default value => {
4-
const type = toType(value)
3+
export default (value, bigNumber) => {
4+
const type = toType(value, bigNumber)
55
let string_value
66
switch (type) {
77
case 'undefined': {
@@ -14,6 +14,9 @@ export default value => {
1414
case 'string':
1515
string_value = value
1616
break
17+
case 'bigNumber':
18+
string_value = value.toString()
19+
break
1720
case 'date':
1821
string_value = value.toString()
1922
break

src/js/helpers/util.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
// returns a string "type" of input object
2-
export function toType (obj) {
2+
export function toType (obj, bigNumber) {
3+
4+
/* Check if the object is an instance of the custom BigNumber class passed in as a prop
5+
* If it matches, return 'bigNumber' type so it can be displayed appropriately
6+
*/
7+
if (bigNumber && obj?.constructor?.name === bigNumber?.name) {
8+
return 'bigNumber'
9+
}
310
let type = getType(obj)
411
// some extra disambiguation for numbers
512
if (type === 'number') {

src/js/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class ReactJsonView extends React.PureComponent {
5959
defaultValue: null,
6060
displayArrayKey: true,
6161
selectOnFocus: false,
62-
keyModifier: e => e.metaKey || e.ctrlKey
62+
keyModifier: e => e.metaKey || e.ctrlKey,
63+
bigNumber: null
6364
}
6465

6566
// will trigger whenever setState() is called, or parent passes in new props.

0 commit comments

Comments
 (0)