@panneau/field-number 1.0.0-alpha.98 → 1.0.3-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/css/styles.css +1 -1
- package/es/index.js +47 -31
- package/lib/index.js +65 -45
- package/package.json +10 -9
package/assets/css/styles.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.panneau-field-number-container{position:relative}.panneau-field-number-container input{-moz-appearance:textfield;padding-right:20px}.panneau-field-number-container input::-webkit-inner-spin-button,.panneau-field-number-container input::-webkit-outer-spin-button{-webkit-appearance:none;appearance:none}.panneau-field-number-container .panneau-field-number-arrow{display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%;pointer-events:none;position:absolute;right:0;top:0;width:20px}.panneau-field-number-container .panneau-field-number-arrowIcon{font-size:10px;margin:auto}.panneau-field-number-container .panneau-field-number-dataListItems{background-color:#fff;border:1px solid rgba(0,0,0,.25)
|
|
1
|
+
.panneau-field-number-container{position:relative}.panneau-field-number-container input{-moz-appearance:textfield;padding-right:20px}.panneau-field-number-container input::-webkit-inner-spin-button,.panneau-field-number-container input::-webkit-outer-spin-button{-webkit-appearance:none;appearance:none}.panneau-field-number-container .panneau-field-number-arrow{display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%;pointer-events:none;position:absolute;right:0;top:0;width:20px}.panneau-field-number-container .panneau-field-number-arrowIcon{font-size:10px;margin:auto}.panneau-field-number-container .panneau-field-number-dataListItems{background-color:#fff;border:1px solid rgba(0,0,0,.25);border-radius:4px;left:0;list-style-type:none;padding:0;position:absolute;top:100%;width:100%;z-index:2}.panneau-field-number-container .panneau-field-number-dataListItem{width:100%}.panneau-field-number-container .panneau-field-number-dataListItemButton{background-color:rgba(0,0,0,0);border:0;text-align:left;width:100%}.panneau-field-number-container .panneau-field-number-dataListItemButton:hover{background-color:rgba(0,0,0,.1)}
|
package/es/index.js
CHANGED
|
@@ -1,64 +1,85 @@
|
|
|
1
1
|
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
2
2
|
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
3
|
+
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
|
|
3
4
|
import React, { useCallback, useState } from 'react';
|
|
4
|
-
import PropTypes from 'prop-types';
|
|
5
|
-
import classNames from 'classnames';
|
|
6
|
-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
7
5
|
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
|
|
6
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
7
|
+
import classNames from 'classnames';
|
|
8
|
+
import isNaN from 'lodash/isNaN';
|
|
9
|
+
import isNumber from 'lodash/isNumber';
|
|
10
|
+
import PropTypes from 'prop-types';
|
|
8
11
|
import TextField from '@panneau/field-text';
|
|
9
12
|
|
|
10
13
|
var styles = {"container":"panneau-field-number-container","arrow":"panneau-field-number-arrow","arrowIcon":"panneau-field-number-arrowIcon","dataListItems":"panneau-field-number-dataListItems","dataListItem":"panneau-field-number-dataListItem","dataListItemButton":"panneau-field-number-dataListItemButton"};
|
|
11
14
|
|
|
15
|
+
var _excluded = ["value", "step", "floatStep", "float", "dataList", "autoComplete", "className", "onChange"];
|
|
12
16
|
var propTypes = {
|
|
13
|
-
|
|
14
|
-
value: PropTypes.number,
|
|
15
|
-
min: PropTypes.number,
|
|
16
|
-
max: PropTypes.number,
|
|
17
|
+
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
17
18
|
step: PropTypes.number,
|
|
18
19
|
floatStep: PropTypes.number,
|
|
19
20
|
"float": PropTypes.bool,
|
|
20
21
|
dataList: PropTypes.arrayOf(PropTypes.number),
|
|
21
22
|
autoComplete: PropTypes.bool,
|
|
22
|
-
placeholder: PropTypes.string,
|
|
23
23
|
className: PropTypes.string,
|
|
24
24
|
onChange: PropTypes.func
|
|
25
25
|
};
|
|
26
26
|
var defaultProps = {
|
|
27
|
-
name: null,
|
|
28
27
|
value: null,
|
|
29
|
-
min: null,
|
|
30
|
-
max: null,
|
|
31
28
|
step: 1,
|
|
32
29
|
floatStep: 0.1,
|
|
33
30
|
"float": false,
|
|
34
31
|
dataList: null,
|
|
35
32
|
autoComplete: false,
|
|
36
|
-
placeholder: null,
|
|
37
33
|
className: null,
|
|
38
34
|
onChange: null
|
|
39
35
|
};
|
|
40
36
|
|
|
37
|
+
function isNumeric(str) {
|
|
38
|
+
if (typeof str !== 'string') return false; // we only process strings!
|
|
39
|
+
|
|
40
|
+
return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
|
|
41
|
+
!isNaN(parseFloat(str));
|
|
42
|
+
}
|
|
43
|
+
|
|
41
44
|
var NumberField = function NumberField(_ref) {
|
|
42
|
-
var
|
|
43
|
-
value = _ref.value,
|
|
44
|
-
min = _ref.min,
|
|
45
|
-
max = _ref.max,
|
|
45
|
+
var value = _ref.value,
|
|
46
46
|
step = _ref.step,
|
|
47
47
|
floatStep = _ref.floatStep,
|
|
48
48
|
_float = _ref["float"],
|
|
49
49
|
dataList = _ref.dataList,
|
|
50
50
|
autoComplete = _ref.autoComplete,
|
|
51
|
-
placeholder = _ref.placeholder,
|
|
52
51
|
className = _ref.className,
|
|
53
|
-
onChange = _ref.onChange
|
|
52
|
+
onChange = _ref.onChange,
|
|
53
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
54
|
+
|
|
54
55
|
var parseValue = useCallback(function (newValue) {
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
if (newValue !== null) {
|
|
57
|
+
if (_float) {
|
|
58
|
+
return newValue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (isNumber(newValue)) {
|
|
62
|
+
return newValue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (isNumeric(newValue)) {
|
|
66
|
+
return _float ? parseFloat(newValue) : parseInt(newValue, 10);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return null;
|
|
71
|
+
}, [_float]);
|
|
57
72
|
var onInputChange = useCallback(function (val) {
|
|
58
73
|
if (onChange !== null) {
|
|
59
|
-
|
|
74
|
+
if (_float) {
|
|
75
|
+
onChange(val !== null && val.length > 0 ? val : null);
|
|
76
|
+
} else {
|
|
77
|
+
onChange(val !== null && val.length > 0 ? parseValue(val) : null);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
onChange(val !== null && val.length > 0 ? parseValue(val) : null);
|
|
60
81
|
}
|
|
61
|
-
}, [onChange]); // Datalist
|
|
82
|
+
}, [onChange, _float]); // Datalist
|
|
62
83
|
|
|
63
84
|
var hasDataList = dataList !== null;
|
|
64
85
|
|
|
@@ -78,27 +99,23 @@ var NumberField = function NumberField(_ref) {
|
|
|
78
99
|
}
|
|
79
100
|
}, [setDataListActive, hasDataList, dataListActive]);
|
|
80
101
|
var onDataListClick = useCallback(function (dataListValue) {
|
|
81
|
-
if (onChange !== null) {
|
|
102
|
+
if (onChange !== null && dataListValue !== null) {
|
|
82
103
|
onChange(parseValue(dataListValue));
|
|
83
104
|
setDataListActive(false);
|
|
84
105
|
}
|
|
85
106
|
}, [onChange, setDataListActive]);
|
|
86
107
|
return /*#__PURE__*/React.createElement("div", {
|
|
87
108
|
className: classNames([styles.container, _defineProperty({}, className, className !== null)])
|
|
88
|
-
}, /*#__PURE__*/React.createElement(TextField, {
|
|
109
|
+
}, /*#__PURE__*/React.createElement(TextField, Object.assign({
|
|
89
110
|
type: "number",
|
|
90
111
|
className: styles.input,
|
|
91
|
-
name: name,
|
|
92
112
|
value: value !== null ? "".concat(value) : '',
|
|
93
|
-
min: min,
|
|
94
|
-
max: max,
|
|
95
113
|
step: _float ? floatStep : step,
|
|
96
114
|
autoComplete: autoComplete ? 'on' : 'off',
|
|
97
|
-
placeholder: placeholder,
|
|
98
115
|
onChange: onInputChange,
|
|
99
116
|
onFocus: onInputFocus,
|
|
100
117
|
onBlur: onInputBlur
|
|
101
|
-
}), hasDataList ? /*#__PURE__*/React.createElement("div", {
|
|
118
|
+
}, props)), hasDataList ? /*#__PURE__*/React.createElement("div", {
|
|
102
119
|
className: styles.arrow
|
|
103
120
|
}, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
|
|
104
121
|
className: styles.arrowIcon,
|
|
@@ -130,5 +147,4 @@ var definition = {
|
|
|
130
147
|
component: 'Number'
|
|
131
148
|
};
|
|
132
149
|
|
|
133
|
-
export default
|
|
134
|
-
export { definition };
|
|
150
|
+
export { NumberField as default, definition };
|
package/lib/index.js
CHANGED
|
@@ -4,79 +4,103 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
|
|
6
6
|
var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
|
|
7
|
+
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
|
|
7
8
|
var React = require('react');
|
|
8
|
-
var PropTypes = require('prop-types');
|
|
9
|
-
var classNames = require('classnames');
|
|
10
|
-
var reactFontawesome = require('@fortawesome/react-fontawesome');
|
|
11
9
|
var freeSolidSvgIcons = require('@fortawesome/free-solid-svg-icons');
|
|
10
|
+
var reactFontawesome = require('@fortawesome/react-fontawesome');
|
|
11
|
+
var classNames = require('classnames');
|
|
12
|
+
var isNaN = require('lodash/isNaN');
|
|
13
|
+
var isNumber = require('lodash/isNumber');
|
|
14
|
+
var PropTypes = require('prop-types');
|
|
12
15
|
var TextField = require('@panneau/field-text');
|
|
13
16
|
|
|
14
17
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
15
18
|
|
|
16
19
|
var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
|
|
17
20
|
var _slicedToArray__default = /*#__PURE__*/_interopDefaultLegacy(_slicedToArray);
|
|
21
|
+
var _objectWithoutProperties__default = /*#__PURE__*/_interopDefaultLegacy(_objectWithoutProperties);
|
|
18
22
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
19
|
-
var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
|
|
20
23
|
var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
|
|
24
|
+
var isNaN__default = /*#__PURE__*/_interopDefaultLegacy(isNaN);
|
|
25
|
+
var isNumber__default = /*#__PURE__*/_interopDefaultLegacy(isNumber);
|
|
26
|
+
var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
|
|
21
27
|
var TextField__default = /*#__PURE__*/_interopDefaultLegacy(TextField);
|
|
22
28
|
|
|
23
29
|
var styles = {"container":"panneau-field-number-container","arrow":"panneau-field-number-arrow","arrowIcon":"panneau-field-number-arrowIcon","dataListItems":"panneau-field-number-dataListItems","dataListItem":"panneau-field-number-dataListItem","dataListItemButton":"panneau-field-number-dataListItemButton"};
|
|
24
30
|
|
|
31
|
+
var _excluded = ["value", "step", "floatStep", "float", "dataList", "autoComplete", "className", "onChange"];
|
|
25
32
|
var propTypes = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
autoComplete: PropTypes__default['default'].bool,
|
|
35
|
-
placeholder: PropTypes__default['default'].string,
|
|
36
|
-
className: PropTypes__default['default'].string,
|
|
37
|
-
onChange: PropTypes__default['default'].func
|
|
33
|
+
value: PropTypes__default["default"].oneOfType([PropTypes__default["default"].number, PropTypes__default["default"].string]),
|
|
34
|
+
step: PropTypes__default["default"].number,
|
|
35
|
+
floatStep: PropTypes__default["default"].number,
|
|
36
|
+
"float": PropTypes__default["default"].bool,
|
|
37
|
+
dataList: PropTypes__default["default"].arrayOf(PropTypes__default["default"].number),
|
|
38
|
+
autoComplete: PropTypes__default["default"].bool,
|
|
39
|
+
className: PropTypes__default["default"].string,
|
|
40
|
+
onChange: PropTypes__default["default"].func
|
|
38
41
|
};
|
|
39
42
|
var defaultProps = {
|
|
40
|
-
name: null,
|
|
41
43
|
value: null,
|
|
42
|
-
min: null,
|
|
43
|
-
max: null,
|
|
44
44
|
step: 1,
|
|
45
45
|
floatStep: 0.1,
|
|
46
46
|
"float": false,
|
|
47
47
|
dataList: null,
|
|
48
48
|
autoComplete: false,
|
|
49
|
-
placeholder: null,
|
|
50
49
|
className: null,
|
|
51
50
|
onChange: null
|
|
52
51
|
};
|
|
53
52
|
|
|
53
|
+
function isNumeric(str) {
|
|
54
|
+
if (typeof str !== 'string') return false; // we only process strings!
|
|
55
|
+
|
|
56
|
+
return !isNaN__default["default"](str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
|
|
57
|
+
!isNaN__default["default"](parseFloat(str));
|
|
58
|
+
}
|
|
59
|
+
|
|
54
60
|
var NumberField = function NumberField(_ref) {
|
|
55
|
-
var
|
|
56
|
-
value = _ref.value,
|
|
57
|
-
min = _ref.min,
|
|
58
|
-
max = _ref.max,
|
|
61
|
+
var value = _ref.value,
|
|
59
62
|
step = _ref.step,
|
|
60
63
|
floatStep = _ref.floatStep,
|
|
61
64
|
_float = _ref["float"],
|
|
62
65
|
dataList = _ref.dataList,
|
|
63
66
|
autoComplete = _ref.autoComplete,
|
|
64
|
-
placeholder = _ref.placeholder,
|
|
65
67
|
className = _ref.className,
|
|
66
|
-
onChange = _ref.onChange
|
|
68
|
+
onChange = _ref.onChange,
|
|
69
|
+
props = _objectWithoutProperties__default["default"](_ref, _excluded);
|
|
70
|
+
|
|
67
71
|
var parseValue = React.useCallback(function (newValue) {
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
if (newValue !== null) {
|
|
73
|
+
if (_float) {
|
|
74
|
+
return newValue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (isNumber__default["default"](newValue)) {
|
|
78
|
+
return newValue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (isNumeric(newValue)) {
|
|
82
|
+
return _float ? parseFloat(newValue) : parseInt(newValue, 10);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return null;
|
|
87
|
+
}, [_float]);
|
|
70
88
|
var onInputChange = React.useCallback(function (val) {
|
|
71
89
|
if (onChange !== null) {
|
|
72
|
-
|
|
90
|
+
if (_float) {
|
|
91
|
+
onChange(val !== null && val.length > 0 ? val : null);
|
|
92
|
+
} else {
|
|
93
|
+
onChange(val !== null && val.length > 0 ? parseValue(val) : null);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
onChange(val !== null && val.length > 0 ? parseValue(val) : null);
|
|
73
97
|
}
|
|
74
|
-
}, [onChange]); // Datalist
|
|
98
|
+
}, [onChange, _float]); // Datalist
|
|
75
99
|
|
|
76
100
|
var hasDataList = dataList !== null;
|
|
77
101
|
|
|
78
102
|
var _useState = React.useState(false),
|
|
79
|
-
_useState2 = _slicedToArray__default[
|
|
103
|
+
_useState2 = _slicedToArray__default["default"](_useState, 2),
|
|
80
104
|
dataListActive = _useState2[0],
|
|
81
105
|
setDataListActive = _useState2[1];
|
|
82
106
|
|
|
@@ -91,38 +115,34 @@ var NumberField = function NumberField(_ref) {
|
|
|
91
115
|
}
|
|
92
116
|
}, [setDataListActive, hasDataList, dataListActive]);
|
|
93
117
|
var onDataListClick = React.useCallback(function (dataListValue) {
|
|
94
|
-
if (onChange !== null) {
|
|
118
|
+
if (onChange !== null && dataListValue !== null) {
|
|
95
119
|
onChange(parseValue(dataListValue));
|
|
96
120
|
setDataListActive(false);
|
|
97
121
|
}
|
|
98
122
|
}, [onChange, setDataListActive]);
|
|
99
|
-
return /*#__PURE__*/React__default[
|
|
100
|
-
className: classNames__default[
|
|
101
|
-
}, /*#__PURE__*/React__default[
|
|
123
|
+
return /*#__PURE__*/React__default["default"].createElement("div", {
|
|
124
|
+
className: classNames__default["default"]([styles.container, _defineProperty__default["default"]({}, className, className !== null)])
|
|
125
|
+
}, /*#__PURE__*/React__default["default"].createElement(TextField__default["default"], Object.assign({
|
|
102
126
|
type: "number",
|
|
103
127
|
className: styles.input,
|
|
104
|
-
name: name,
|
|
105
128
|
value: value !== null ? "".concat(value) : '',
|
|
106
|
-
min: min,
|
|
107
|
-
max: max,
|
|
108
129
|
step: _float ? floatStep : step,
|
|
109
130
|
autoComplete: autoComplete ? 'on' : 'off',
|
|
110
|
-
placeholder: placeholder,
|
|
111
131
|
onChange: onInputChange,
|
|
112
132
|
onFocus: onInputFocus,
|
|
113
133
|
onBlur: onInputBlur
|
|
114
|
-
}), hasDataList ? /*#__PURE__*/React__default[
|
|
134
|
+
}, props)), hasDataList ? /*#__PURE__*/React__default["default"].createElement("div", {
|
|
115
135
|
className: styles.arrow
|
|
116
|
-
}, /*#__PURE__*/React__default[
|
|
136
|
+
}, /*#__PURE__*/React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, {
|
|
117
137
|
className: styles.arrowIcon,
|
|
118
138
|
icon: freeSolidSvgIcons.faChevronDown
|
|
119
|
-
})) : null, hasDataList && dataListActive ? /*#__PURE__*/React__default[
|
|
139
|
+
})) : null, hasDataList && dataListActive ? /*#__PURE__*/React__default["default"].createElement("ul", {
|
|
120
140
|
className: styles.dataListItems
|
|
121
141
|
}, dataList.map(function (dataListValue) {
|
|
122
|
-
return /*#__PURE__*/React__default[
|
|
142
|
+
return /*#__PURE__*/React__default["default"].createElement("li", {
|
|
123
143
|
key: "data-list-".concat(dataListValue),
|
|
124
144
|
className: styles.dataListItem
|
|
125
|
-
}, /*#__PURE__*/React__default[
|
|
145
|
+
}, /*#__PURE__*/React__default["default"].createElement("button", {
|
|
126
146
|
className: styles.dataListItemButton,
|
|
127
147
|
type: "button",
|
|
128
148
|
onTouchStart: function onTouchStart() {
|
|
@@ -143,5 +163,5 @@ var definition = {
|
|
|
143
163
|
component: 'Number'
|
|
144
164
|
};
|
|
145
165
|
|
|
146
|
-
exports
|
|
166
|
+
exports["default"] = NumberField;
|
|
147
167
|
exports.definition = definition;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@panneau/field-number",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3-alpha.1",
|
|
4
4
|
"description": "A number field",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"javascript"
|
|
@@ -44,26 +44,27 @@
|
|
|
44
44
|
"prepare": "../../scripts/prepare-package.sh"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"react": "^16.8.0",
|
|
48
|
-
"react-dom": "^16.8.0"
|
|
47
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
48
|
+
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
|
-
"react": "^16.8.0",
|
|
52
|
-
"react-dom": "^16.8.0"
|
|
51
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
52
|
+
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@babel/runtime": "^7.12.5",
|
|
56
56
|
"@fortawesome/fontawesome-svg-core": "^1.2.35",
|
|
57
57
|
"@fortawesome/free-solid-svg-icons": "^5.15.3",
|
|
58
58
|
"@fortawesome/react-fontawesome": "^0.1.14",
|
|
59
|
-
"@panneau/core": "^1.0.
|
|
60
|
-
"@panneau/field-text": "^1.0.
|
|
61
|
-
"@panneau/themes": "^1.0.
|
|
59
|
+
"@panneau/core": "^1.0.3-alpha.1",
|
|
60
|
+
"@panneau/field-text": "^1.0.3-alpha.1",
|
|
61
|
+
"@panneau/themes": "^1.0.3-alpha.1",
|
|
62
62
|
"classnames": "^2.2.6",
|
|
63
|
+
"lodash": "^4.17.21",
|
|
63
64
|
"prop-types": "^15.7.2"
|
|
64
65
|
},
|
|
65
66
|
"publishConfig": {
|
|
66
67
|
"access": "public"
|
|
67
68
|
},
|
|
68
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "e04e663c7f1eb692f89a0136f2e8f45024fbe355"
|
|
69
70
|
}
|