@contentful/field-editor-number 1.2.5 → 1.2.6

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/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.2.6](https://github.com/contentful/field-editors/compare/@contentful/field-editor-number@1.2.5...@contentful/field-editor-number@1.2.6) (2023-04-19)
7
+
8
+ **Note:** Version bump only for package @contentful/field-editor-number
9
+
6
10
  ## [1.2.5](https://github.com/contentful/field-editors/compare/@contentful/field-editor-number@1.2.4...@contentful/field-editor-number@1.2.5) (2023-03-14)
7
11
 
8
12
  **Note:** Version bump only for package @contentful/field-editor-number
@@ -11,7 +11,7 @@ var fieldEditorShared = require('@contentful/field-editor-shared');
11
11
  var tokens = _interopDefault(require('@contentful/f36-tokens'));
12
12
  var emotion = require('emotion');
13
13
 
14
- var styles = {
14
+ const styles = {
15
15
  container: /*#__PURE__*/emotion.css({
16
16
  position: 'relative'
17
17
  }),
@@ -33,7 +33,7 @@ var styles = {
33
33
  padding: 0,
34
34
  margin: 0,
35
35
  outline: 'none',
36
- border: "0 solid " + tokens.gray300,
36
+ border: `0 solid ${tokens.gray300}`,
37
37
  background: 'none',
38
38
  borderLeftWidth: '1px',
39
39
  '&:first-of-type': {
@@ -65,27 +65,25 @@ function parseNumber(value, type) {
65
65
 
66
66
  return type === 'Integer' ? parseInt(value, 10) : parseFloat(value);
67
67
  }
68
- var FLOAT_REGEX = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/;
69
- var INT_REGEX = /^[+-]?([0-9]*)$/;
68
+ const FLOAT_REGEX = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/;
69
+ const INT_REGEX = /^[+-]?([0-9]*)$/;
70
70
  function isNumberInputValueValid(value, type) {
71
- var regex = type === 'Integer' ? INT_REGEX : FLOAT_REGEX;
71
+ const regex = type === 'Integer' ? INT_REGEX : FLOAT_REGEX;
72
72
  return regex.test(value);
73
73
  }
74
74
 
75
- var getRangeFromField = function getRangeFromField(field) {
76
- var validations = field.validations || [];
77
- var result = validations.find(function (validation) {
78
- return validation.range;
79
- });
75
+ const getRangeFromField = field => {
76
+ const validations = field.validations || [];
77
+ const result = validations.find(validation => validation.range);
80
78
  return result ? result.range : {};
81
79
  };
82
- var valueToString = function valueToString(value) {
80
+ const valueToString = value => {
83
81
  return value === undefined ? '' : String(value);
84
82
  };
85
- var countDecimals = function countDecimals(number) {
86
- var _number$toString$spli, _number$toString$spli2;
83
+ const countDecimals = number => {
84
+ var _number$toString$spli;
87
85
 
88
- return (_number$toString$spli = (_number$toString$spli2 = number.toString().split('.')[1]) == null ? void 0 : _number$toString$spli2.length) != null ? _number$toString$spli : 0;
86
+ return ((_number$toString$spli = number.toString().split('.')[1]) == null ? void 0 : _number$toString$spli.length) ?? 0;
89
87
  };
90
88
 
91
89
  var StepChangeType;
@@ -95,23 +93,20 @@ var StepChangeType;
95
93
  StepChangeType["Decrement"] = "decrement";
96
94
  })(StepChangeType || (StepChangeType = {}));
97
95
 
98
- var NUMBER_STEP = 1;
99
-
100
- function InnerNumberEditor(_ref) {
101
- var disabled = _ref.disabled,
102
- errors = _ref.errors,
103
- field = _ref.field,
104
- setValue = _ref.setValue,
105
- sdkValue = _ref.value;
106
-
107
- var _React$useState = React.useState(valueToString(sdkValue)),
108
- inputValue = _React$useState[0],
109
- setInputValue = _React$useState[1];
110
-
111
- var range = getRangeFromField(field);
112
- var inputRef = React.useRef(null);
113
- React.useEffect(function () {
114
- var stringSdkValue = valueToString(sdkValue); // Update the input value if the SDK value (numeric) changes
96
+ const NUMBER_STEP = 1;
97
+
98
+ function InnerNumberEditor({
99
+ disabled,
100
+ errors,
101
+ field,
102
+ setValue,
103
+ value: sdkValue
104
+ }) {
105
+ const [inputValue, setInputValue] = React.useState(valueToString(sdkValue));
106
+ const range = getRangeFromField(field);
107
+ const inputRef = React.useRef(null);
108
+ React.useEffect(() => {
109
+ const stringSdkValue = valueToString(sdkValue); // Update the input value if the SDK value (numeric) changes
115
110
 
116
111
  if (stringSdkValue !== inputValue) {
117
112
  setInputValue(stringSdkValue);
@@ -119,15 +114,15 @@ function InnerNumberEditor(_ref) {
119
114
 
120
115
  }, [sdkValue]);
121
116
 
122
- var updateExternalValue = function updateExternalValue(value) {
117
+ const updateExternalValue = value => {
123
118
  if (sdkValue !== value) {
124
119
  setValue(value);
125
120
  }
126
121
  };
127
122
 
128
- var changeValueByStep = function changeValueByStep(type) {
129
- var currentValue = Number.isNaN(+inputValue) ? 0 : +inputValue;
130
- var nextValue = type === StepChangeType.Increment ? currentValue + NUMBER_STEP : currentValue - NUMBER_STEP; // Floating point numbers cannot represent all decimals precisely in binary.
123
+ const changeValueByStep = type => {
124
+ const currentValue = Number.isNaN(+inputValue) ? 0 : +inputValue;
125
+ let nextValue = type === StepChangeType.Increment ? currentValue + NUMBER_STEP : currentValue - NUMBER_STEP; // Floating point numbers cannot represent all decimals precisely in binary.
131
126
  // This can lead to unexpected results, such as 0.1 + 0.2 = 0.30000000000000004.
132
127
  // See more details: https://floating-point-gui.de/
133
128
 
@@ -137,23 +132,19 @@ function InnerNumberEditor(_ref) {
137
132
  }; // Keeps focus on the input
138
133
 
139
134
 
140
- var handleControlPointerDown = function handleControlPointerDown(event) {
135
+ const handleControlPointerDown = event => {
141
136
  var _inputRef$current;
142
137
 
143
138
  event.preventDefault();
144
139
  (_inputRef$current = inputRef.current) == null ? void 0 : _inputRef$current.focus();
145
140
  };
146
141
 
147
- var handleKeyDown = function handleKeyDown(event) {
148
- var keyToFnMap = {
149
- ArrowUp: function ArrowUp() {
150
- return changeValueByStep(StepChangeType.Increment);
151
- },
152
- ArrowDown: function ArrowDown() {
153
- return changeValueByStep(StepChangeType.Decrement);
154
- }
142
+ const handleKeyDown = event => {
143
+ const keyToFnMap = {
144
+ ArrowUp: () => changeValueByStep(StepChangeType.Increment),
145
+ ArrowDown: () => changeValueByStep(StepChangeType.Decrement)
155
146
  };
156
- var fn = keyToFnMap[event.key];
147
+ const fn = keyToFnMap[event.key];
157
148
 
158
149
  if (fn) {
159
150
  event.preventDefault();
@@ -161,8 +152,8 @@ function InnerNumberEditor(_ref) {
161
152
  }
162
153
  };
163
154
 
164
- var handleInputChange = function handleInputChange(e) {
165
- var value = e.target.value;
155
+ const handleInputChange = e => {
156
+ const value = e.target.value;
166
157
 
167
158
  if (!value) {
168
159
  setInputValue(value);
@@ -175,7 +166,7 @@ function InnerNumberEditor(_ref) {
175
166
  }
176
167
 
177
168
  setInputValue(value);
178
- var parsedNumber = parseNumber(value, field.type);
169
+ const parsedNumber = parseNumber(value, field.type);
179
170
  field.setInvalid(parsedNumber === undefined);
180
171
 
181
172
  if (parsedNumber !== undefined) {
@@ -208,7 +199,7 @@ function InnerNumberEditor(_ref) {
208
199
  // The same role that input type="number" has
209
200
  // See more details: https://www.digitala11y.com/spinbutton-role/
210
201
  role: "spinbutton",
211
- "aria-valuenow": sdkValue != null ? sdkValue : 0,
202
+ "aria-valuenow": sdkValue ?? 0,
212
203
  "aria-valuetext": inputValue,
213
204
  "aria-valuemin": range.min,
214
205
  "aria-valuemax": range.max
@@ -218,18 +209,14 @@ function InnerNumberEditor(_ref) {
218
209
  }, React.createElement("button", {
219
210
  tabIndex: -1,
220
211
  className: styles.control,
221
- onClick: function onClick() {
222
- return changeValueByStep(StepChangeType.Increment);
223
- },
212
+ onClick: () => changeValueByStep(StepChangeType.Increment),
224
213
  onPointerDown: handleControlPointerDown
225
214
  }, React.createElement(f36Icons.ArrowUpTrimmedIcon, {
226
215
  size: "medium"
227
216
  })), React.createElement("button", {
228
217
  tabIndex: -1,
229
218
  className: styles.control,
230
- onClick: function onClick() {
231
- return changeValueByStep(StepChangeType.Decrement);
232
- },
219
+ onClick: () => changeValueByStep(StepChangeType.Decrement),
233
220
  onPointerDown: handleControlPointerDown
234
221
  }, React.createElement(f36Icons.ArrowDownTrimmedIcon, {
235
222
  size: "medium"
@@ -237,23 +224,24 @@ function InnerNumberEditor(_ref) {
237
224
  }
238
225
 
239
226
  function NumberEditor(props) {
240
- var field = props.field;
227
+ const {
228
+ field
229
+ } = props;
241
230
  return React.createElement(fieldEditorShared.FieldConnector, {
242
231
  field: field,
243
232
  isInitiallyDisabled: props.isInitiallyDisabled
244
- }, function (_ref2) {
245
- var value = _ref2.value,
246
- errors = _ref2.errors,
247
- disabled = _ref2.disabled,
248
- setValue = _ref2.setValue;
249
- return React.createElement(InnerNumberEditor, {
250
- disabled: disabled,
251
- errors: errors,
252
- field: field,
253
- setValue: setValue,
254
- value: value
255
- });
256
- });
233
+ }, ({
234
+ value,
235
+ errors,
236
+ disabled,
237
+ setValue
238
+ }) => React.createElement(InnerNumberEditor, {
239
+ disabled: disabled,
240
+ errors: errors,
241
+ field: field,
242
+ setValue: setValue,
243
+ value: value
244
+ }));
257
245
  }
258
246
  NumberEditor.defaultProps = {
259
247
  isInitiallyDisabled: true
@@ -1 +1 @@
1
- {"version":3,"file":"field-editor-number.cjs.development.js","sources":["../src/NumberEditor.styles.ts","../src/parseNumber.ts","../src/utils.ts","../src/NumberEditor.tsx"],"sourcesContent":["import tokens from '@contentful/f36-tokens';\nimport { css } from 'emotion';\n\nexport const styles = {\n container: css({\n position: 'relative',\n }),\n controlsWrapper: css({\n position: 'absolute',\n top: '1px',\n right: '1px',\n width: tokens.spacingL,\n height: 'calc(100% - 2px)',\n display: 'flex',\n flexDirection: 'column',\n }),\n control: css({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 0,\n cursor: 'pointer',\n padding: 0,\n margin: 0,\n outline: 'none',\n border: `0 solid ${tokens.gray300}`,\n background: 'none',\n borderLeftWidth: '1px',\n\n '&:first-of-type': {\n borderTopRightRadius: tokens.borderRadiusMedium,\n },\n\n '&:last-of-type': {\n borderTopWidth: '1px',\n borderBottomRightRadius: tokens.borderRadiusMedium,\n },\n\n svg: {\n fill: tokens.gray600,\n },\n\n '&:hover': {\n backgroundColor: tokens.gray200,\n },\n\n '&:active': {\n backgroundColor: tokens.gray300,\n },\n }),\n input: css({\n paddingRight: tokens.spacingXl,\n }),\n};\n","export function parseNumber(value: string, type: string) {\n if (Number.isNaN(+value)) {\n return;\n }\n\n return type === 'Integer' ? parseInt(value, 10) : parseFloat(value);\n}\n\nconst FLOAT_REGEX = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/;\nconst INT_REGEX = /^[+-]?([0-9]*)$/;\n\nexport function isNumberInputValueValid(value: string, type: string) {\n const regex = type === 'Integer' ? INT_REGEX : FLOAT_REGEX;\n\n return regex.test(value);\n}\n","import { FieldAPI } from '@contentful/field-editor-shared';\n\ntype RangeValidation = { min?: number; max?: number };\n\nexport const getRangeFromField = (field: FieldAPI): RangeValidation => {\n const validations = field.validations || [];\n const result = validations.find((validation) => (validation as any).range) as\n | { range: RangeValidation }\n | undefined;\n return result ? result.range : {};\n};\n\nexport const valueToString = (value: number | null | undefined) => {\n return value === undefined ? '' : String(value);\n};\n\nexport const countDecimals = (number: number) => {\n return number.toString().split('.')[1]?.length ?? 0;\n};\n","import * as React from 'react';\n\nimport { TextInput } from '@contentful/f36-components';\nimport { ArrowUpTrimmedIcon, ArrowDownTrimmedIcon } from '@contentful/f36-icons';\nimport {\n FieldAPI,\n FieldConnector,\n FieldConnectorChildProps,\n} from '@contentful/field-editor-shared';\n\nimport { styles } from './NumberEditor.styles';\nimport { isNumberInputValueValid, parseNumber } from './parseNumber';\nimport { getRangeFromField, valueToString, countDecimals } from './utils';\n\nexport interface NumberEditorProps {\n /**\n * is the field disabled initially\n */\n isInitiallyDisabled: boolean;\n\n /**\n * sdk.field\n */\n field: FieldAPI;\n}\n\ntype InnerNumberEditorProps = Pick<\n FieldConnectorChildProps<number>,\n 'disabled' | 'errors' | 'setValue' | 'value'\n> & {\n field: NumberEditorProps['field'];\n};\n\nenum StepChangeType {\n Increment = 'increment',\n Decrement = 'decrement',\n}\n\nconst NUMBER_STEP = 1;\n\nfunction InnerNumberEditor({\n disabled,\n errors,\n field,\n setValue,\n value: sdkValue,\n}: InnerNumberEditorProps) {\n const [inputValue, setInputValue] = React.useState(valueToString(sdkValue));\n const range = getRangeFromField(field);\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n React.useEffect(() => {\n const stringSdkValue = valueToString(sdkValue);\n // Update the input value if the SDK value (numeric) changes\n if (stringSdkValue !== inputValue) {\n setInputValue(stringSdkValue);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- we want to trigger it only when sdkValue has changed\n }, [sdkValue]);\n\n const updateExternalValue = (value: number | undefined) => {\n if (sdkValue !== value) {\n setValue(value);\n }\n };\n\n const changeValueByStep = (type: StepChangeType) => {\n const currentValue = Number.isNaN(+inputValue) ? 0 : +inputValue;\n let nextValue =\n type === StepChangeType.Increment ? currentValue + NUMBER_STEP : currentValue - NUMBER_STEP;\n // Floating point numbers cannot represent all decimals precisely in binary.\n // This can lead to unexpected results, such as 0.1 + 0.2 = 0.30000000000000004.\n // See more details: https://floating-point-gui.de/\n nextValue = +nextValue.toFixed(countDecimals(currentValue));\n\n setInputValue(valueToString(nextValue));\n setValue(nextValue);\n };\n\n // Keeps focus on the input\n const handleControlPointerDown: React.PointerEventHandler<HTMLButtonElement> = (event) => {\n event.preventDefault();\n inputRef.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<any>) => {\n const keyToFnMap: {\n [key: string]: () => void;\n } = {\n ArrowUp: () => changeValueByStep(StepChangeType.Increment),\n ArrowDown: () => changeValueByStep(StepChangeType.Decrement),\n };\n\n const fn = keyToFnMap[event.key];\n if (fn) {\n event.preventDefault();\n fn();\n }\n };\n\n const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {\n const value = e.target.value;\n if (!value) {\n setInputValue(value);\n updateExternalValue(undefined);\n return;\n }\n\n if (!isNumberInputValueValid(value, field.type)) {\n return;\n }\n\n setInputValue(value);\n\n const parsedNumber = parseNumber(value, field.type);\n field.setInvalid(parsedNumber === undefined);\n if (parsedNumber !== undefined) {\n updateExternalValue(parsedNumber);\n }\n };\n\n return (\n <div data-test-id=\"number-editor\" className={styles.container}>\n <TextInput\n // With type=\"number\" react doesn't call onChange for certain inputs, for example if you type `e`\n // so we use \"text\" instead and fully rely on our own validation.\n // See more details: https://github.com/facebook/react/issues/6556\n type=\"text\"\n testId=\"number-editor-input\"\n className={styles.input}\n min={range.min}\n max={range.max}\n isRequired={field.required}\n isInvalid={errors.length > 0}\n isDisabled={disabled}\n value={inputValue}\n ref={inputRef}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n // The same role that input type=\"number\" has\n // See more details: https://www.digitala11y.com/spinbutton-role/\n role=\"spinbutton\"\n aria-valuenow={sdkValue ?? 0}\n aria-valuetext={inputValue}\n aria-valuemin={range.min}\n aria-valuemax={range.max}\n />\n {/**\n * We hide this controls from screen readers and keyboard focus.\n * For those purposes we have a keyboard handler. The same way native input number works.\n */}\n {!disabled && (\n <div className={styles.controlsWrapper} aria-hidden=\"true\">\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Increment)}\n onPointerDown={handleControlPointerDown}>\n <ArrowUpTrimmedIcon size=\"medium\" />\n </button>\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Decrement)}\n onPointerDown={handleControlPointerDown}>\n <ArrowDownTrimmedIcon size=\"medium\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport function NumberEditor(props: NumberEditorProps) {\n const { field } = props;\n\n return (\n <FieldConnector<number> field={field} isInitiallyDisabled={props.isInitiallyDisabled}>\n {({\n value,\n errors,\n disabled,\n setValue,\n }: Pick<FieldConnectorChildProps<number>, 'disabled' | 'errors' | 'setValue' | 'value'>) => (\n <InnerNumberEditor\n disabled={disabled}\n errors={errors}\n field={field}\n setValue={setValue}\n value={value}\n />\n )}\n </FieldConnector>\n );\n}\n\nNumberEditor.defaultProps = {\n isInitiallyDisabled: true,\n};\n"],"names":["styles","container","css","position","controlsWrapper","top","right","width","tokens","spacingL","height","display","flexDirection","control","alignItems","justifyContent","minHeight","cursor","padding","margin","outline","border","gray300","background","borderLeftWidth","borderTopRightRadius","borderRadiusMedium","borderTopWidth","borderBottomRightRadius","svg","fill","gray600","backgroundColor","gray200","input","paddingRight","spacingXl","parseNumber","value","type","Number","isNaN","parseInt","parseFloat","FLOAT_REGEX","INT_REGEX","isNumberInputValueValid","regex","test","getRangeFromField","field","validations","result","find","validation","range","valueToString","undefined","String","countDecimals","number","toString","split","length","StepChangeType","NUMBER_STEP","InnerNumberEditor","disabled","errors","setValue","sdkValue","React","inputValue","setInputValue","inputRef","stringSdkValue","updateExternalValue","changeValueByStep","currentValue","nextValue","Increment","toFixed","handleControlPointerDown","event","preventDefault","current","focus","handleKeyDown","keyToFnMap","ArrowUp","ArrowDown","Decrement","fn","key","handleInputChange","e","target","parsedNumber","setInvalid","className","TextInput","testId","min","max","isRequired","required","isInvalid","isDisabled","ref","onChange","onKeyDown","role","tabIndex","onClick","onPointerDown","ArrowUpTrimmedIcon","size","ArrowDownTrimmedIcon","NumberEditor","props","FieldConnector","isInitiallyDisabled","defaultProps"],"mappings":"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"}
1
+ {"version":3,"file":"field-editor-number.cjs.development.js","sources":["../src/NumberEditor.styles.ts","../src/parseNumber.ts","../src/utils.ts","../src/NumberEditor.tsx"],"sourcesContent":["import tokens from '@contentful/f36-tokens';\nimport { css } from 'emotion';\n\nexport const styles = {\n container: css({\n position: 'relative',\n }),\n controlsWrapper: css({\n position: 'absolute',\n top: '1px',\n right: '1px',\n width: tokens.spacingL,\n height: 'calc(100% - 2px)',\n display: 'flex',\n flexDirection: 'column',\n }),\n control: css({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 0,\n cursor: 'pointer',\n padding: 0,\n margin: 0,\n outline: 'none',\n border: `0 solid ${tokens.gray300}`,\n background: 'none',\n borderLeftWidth: '1px',\n\n '&:first-of-type': {\n borderTopRightRadius: tokens.borderRadiusMedium,\n },\n\n '&:last-of-type': {\n borderTopWidth: '1px',\n borderBottomRightRadius: tokens.borderRadiusMedium,\n },\n\n svg: {\n fill: tokens.gray600,\n },\n\n '&:hover': {\n backgroundColor: tokens.gray200,\n },\n\n '&:active': {\n backgroundColor: tokens.gray300,\n },\n }),\n input: css({\n paddingRight: tokens.spacingXl,\n }),\n};\n","export function parseNumber(value: string, type: string) {\n if (Number.isNaN(+value)) {\n return;\n }\n\n return type === 'Integer' ? parseInt(value, 10) : parseFloat(value);\n}\n\nconst FLOAT_REGEX = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/;\nconst INT_REGEX = /^[+-]?([0-9]*)$/;\n\nexport function isNumberInputValueValid(value: string, type: string) {\n const regex = type === 'Integer' ? INT_REGEX : FLOAT_REGEX;\n\n return regex.test(value);\n}\n","import { FieldAPI } from '@contentful/field-editor-shared';\n\ntype RangeValidation = { min?: number; max?: number };\n\nexport const getRangeFromField = (field: FieldAPI): RangeValidation => {\n const validations = field.validations || [];\n const result = validations.find((validation) => (validation as any).range) as\n | { range: RangeValidation }\n | undefined;\n return result ? result.range : {};\n};\n\nexport const valueToString = (value: number | null | undefined) => {\n return value === undefined ? '' : String(value);\n};\n\nexport const countDecimals = (number: number) => {\n return number.toString().split('.')[1]?.length ?? 0;\n};\n","import * as React from 'react';\n\nimport { TextInput } from '@contentful/f36-components';\nimport { ArrowUpTrimmedIcon, ArrowDownTrimmedIcon } from '@contentful/f36-icons';\nimport {\n FieldAPI,\n FieldConnector,\n FieldConnectorChildProps,\n} from '@contentful/field-editor-shared';\n\nimport { styles } from './NumberEditor.styles';\nimport { isNumberInputValueValid, parseNumber } from './parseNumber';\nimport { getRangeFromField, valueToString, countDecimals } from './utils';\n\nexport interface NumberEditorProps {\n /**\n * is the field disabled initially\n */\n isInitiallyDisabled: boolean;\n\n /**\n * sdk.field\n */\n field: FieldAPI;\n}\n\ntype InnerNumberEditorProps = Pick<\n FieldConnectorChildProps<number>,\n 'disabled' | 'errors' | 'setValue' | 'value'\n> & {\n field: NumberEditorProps['field'];\n};\n\nenum StepChangeType {\n Increment = 'increment',\n Decrement = 'decrement',\n}\n\nconst NUMBER_STEP = 1;\n\nfunction InnerNumberEditor({\n disabled,\n errors,\n field,\n setValue,\n value: sdkValue,\n}: InnerNumberEditorProps) {\n const [inputValue, setInputValue] = React.useState(valueToString(sdkValue));\n const range = getRangeFromField(field);\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n React.useEffect(() => {\n const stringSdkValue = valueToString(sdkValue);\n // Update the input value if the SDK value (numeric) changes\n if (stringSdkValue !== inputValue) {\n setInputValue(stringSdkValue);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- we want to trigger it only when sdkValue has changed\n }, [sdkValue]);\n\n const updateExternalValue = (value: number | undefined) => {\n if (sdkValue !== value) {\n setValue(value);\n }\n };\n\n const changeValueByStep = (type: StepChangeType) => {\n const currentValue = Number.isNaN(+inputValue) ? 0 : +inputValue;\n let nextValue =\n type === StepChangeType.Increment ? currentValue + NUMBER_STEP : currentValue - NUMBER_STEP;\n // Floating point numbers cannot represent all decimals precisely in binary.\n // This can lead to unexpected results, such as 0.1 + 0.2 = 0.30000000000000004.\n // See more details: https://floating-point-gui.de/\n nextValue = +nextValue.toFixed(countDecimals(currentValue));\n\n setInputValue(valueToString(nextValue));\n setValue(nextValue);\n };\n\n // Keeps focus on the input\n const handleControlPointerDown: React.PointerEventHandler<HTMLButtonElement> = (event) => {\n event.preventDefault();\n inputRef.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<any>) => {\n const keyToFnMap: {\n [key: string]: () => void;\n } = {\n ArrowUp: () => changeValueByStep(StepChangeType.Increment),\n ArrowDown: () => changeValueByStep(StepChangeType.Decrement),\n };\n\n const fn = keyToFnMap[event.key];\n if (fn) {\n event.preventDefault();\n fn();\n }\n };\n\n const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {\n const value = e.target.value;\n if (!value) {\n setInputValue(value);\n updateExternalValue(undefined);\n return;\n }\n\n if (!isNumberInputValueValid(value, field.type)) {\n return;\n }\n\n setInputValue(value);\n\n const parsedNumber = parseNumber(value, field.type);\n field.setInvalid(parsedNumber === undefined);\n if (parsedNumber !== undefined) {\n updateExternalValue(parsedNumber);\n }\n };\n\n return (\n <div data-test-id=\"number-editor\" className={styles.container}>\n <TextInput\n // With type=\"number\" react doesn't call onChange for certain inputs, for example if you type `e`\n // so we use \"text\" instead and fully rely on our own validation.\n // See more details: https://github.com/facebook/react/issues/6556\n type=\"text\"\n testId=\"number-editor-input\"\n className={styles.input}\n min={range.min}\n max={range.max}\n isRequired={field.required}\n isInvalid={errors.length > 0}\n isDisabled={disabled}\n value={inputValue}\n ref={inputRef}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n // The same role that input type=\"number\" has\n // See more details: https://www.digitala11y.com/spinbutton-role/\n role=\"spinbutton\"\n aria-valuenow={sdkValue ?? 0}\n aria-valuetext={inputValue}\n aria-valuemin={range.min}\n aria-valuemax={range.max}\n />\n {/**\n * We hide this controls from screen readers and keyboard focus.\n * For those purposes we have a keyboard handler. The same way native input number works.\n */}\n {!disabled && (\n <div className={styles.controlsWrapper} aria-hidden=\"true\">\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Increment)}\n onPointerDown={handleControlPointerDown}>\n <ArrowUpTrimmedIcon size=\"medium\" />\n </button>\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Decrement)}\n onPointerDown={handleControlPointerDown}>\n <ArrowDownTrimmedIcon size=\"medium\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport function NumberEditor(props: NumberEditorProps) {\n const { field } = props;\n\n return (\n <FieldConnector<number> field={field} isInitiallyDisabled={props.isInitiallyDisabled}>\n {({\n value,\n errors,\n disabled,\n setValue,\n }: Pick<FieldConnectorChildProps<number>, 'disabled' | 'errors' | 'setValue' | 'value'>) => (\n <InnerNumberEditor\n disabled={disabled}\n errors={errors}\n field={field}\n setValue={setValue}\n value={value}\n />\n )}\n </FieldConnector>\n );\n}\n\nNumberEditor.defaultProps = {\n isInitiallyDisabled: true,\n};\n"],"names":["styles","container","css","position","controlsWrapper","top","right","width","tokens","spacingL","height","display","flexDirection","control","alignItems","justifyContent","minHeight","cursor","padding","margin","outline","border","gray300","background","borderLeftWidth","borderTopRightRadius","borderRadiusMedium","borderTopWidth","borderBottomRightRadius","svg","fill","gray600","backgroundColor","gray200","input","paddingRight","spacingXl","parseNumber","value","type","Number","isNaN","parseInt","parseFloat","FLOAT_REGEX","INT_REGEX","isNumberInputValueValid","regex","test","getRangeFromField","field","validations","result","find","validation","range","valueToString","undefined","String","countDecimals","number","toString","split","length","StepChangeType","NUMBER_STEP","InnerNumberEditor","disabled","errors","setValue","sdkValue","inputValue","setInputValue","React","inputRef","stringSdkValue","updateExternalValue","changeValueByStep","currentValue","nextValue","Increment","toFixed","handleControlPointerDown","event","preventDefault","current","focus","handleKeyDown","keyToFnMap","ArrowUp","ArrowDown","Decrement","fn","key","handleInputChange","e","target","parsedNumber","setInvalid","className","TextInput","testId","min","max","isRequired","required","isInvalid","isDisabled","ref","onChange","onKeyDown","role","tabIndex","onClick","onPointerDown","ArrowUpTrimmedIcon","size","ArrowDownTrimmedIcon","NumberEditor","props","FieldConnector","isInitiallyDisabled","defaultProps"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t,n=require("react"),r=require("@contentful/f36-components"),i=require("@contentful/f36-icons"),o=require("@contentful/field-editor-shared"),a=(e=require("@contentful/f36-tokens"))&&"object"==typeof e&&"default"in e?e.default:e,u=require("emotion"),l={container:u.css({position:"relative"}),controlsWrapper:u.css({position:"absolute",top:"1px",right:"1px",width:a.spacingL,height:"calc(100% - 2px)",display:"flex",flexDirection:"column"}),control:u.css({display:"flex",alignItems:"center",justifyContent:"center",minHeight:0,cursor:"pointer",padding:0,margin:0,outline:"none",border:"0 solid "+a.gray300,background:"none",borderLeftWidth:"1px","&:first-of-type":{borderTopRightRadius:a.borderRadiusMedium},"&:last-of-type":{borderTopWidth:"1px",borderBottomRightRadius:a.borderRadiusMedium},svg:{fill:a.gray600},"&:hover":{backgroundColor:a.gray200},"&:active":{backgroundColor:a.gray300}}),input:u.css({paddingRight:a.spacingXl})},c=/^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/,s=/^[+-]?([0-9]*)$/,d=function(e){return void 0===e?"":String(e)};function f(e){var o=e.disabled,a=e.errors,u=e.field,f=e.setValue,m=e.value,p=n.useState(d(m)),v=p[0],b=p[1],g=function(e){var t=(e.validations||[]).find((function(e){return e.range}));return t?t.range:{}}(u),x=n.useRef(null);n.useEffect((function(){var e=d(m);e!==v&&b(e)}),[m]);var y=function(e){m!==e&&f(e)},I=function(e){var n,r,i,o=Number.isNaN(+v)?0:+v,a=e===t.Increment?o+1:o-1;a=+a.toFixed((n=o,null!=(r=null==(i=n.toString().split(".")[1])?void 0:i.length)?r:0)),b(d(a)),f(a)},h=function(e){var t;e.preventDefault(),null==(t=x.current)||t.focus()};return n.createElement("div",{"data-test-id":"number-editor",className:l.container},n.createElement(r.TextInput,{type:"text",testId:"number-editor-input",className:l.input,min:g.min,max:g.max,isRequired:u.required,isInvalid:a.length>0,isDisabled:o,value:v,ref:x,onChange:function(e){var t=e.target.value;if(!t)return b(t),void y(void 0);if(function(e,t){return("Integer"===t?s:c).test(e)}(t,u.type)){b(t);var n=function(e,t){if(!Number.isNaN(+e))return"Integer"===t?parseInt(e,10):parseFloat(e)}(t,u.type);u.setInvalid(void 0===n),void 0!==n&&y(n)}},onKeyDown:function(e){var n={ArrowUp:function(){return I(t.Increment)},ArrowDown:function(){return I(t.Decrement)}}[e.key];n&&(e.preventDefault(),n())},role:"spinbutton","aria-valuenow":null!=m?m:0,"aria-valuetext":v,"aria-valuemin":g.min,"aria-valuemax":g.max}),!o&&n.createElement("div",{className:l.controlsWrapper,"aria-hidden":"true"},n.createElement("button",{tabIndex:-1,className:l.control,onClick:function(){return I(t.Increment)},onPointerDown:h},n.createElement(i.ArrowUpTrimmedIcon,{size:"medium"})),n.createElement("button",{tabIndex:-1,className:l.control,onClick:function(){return I(t.Decrement)},onPointerDown:h},n.createElement(i.ArrowDownTrimmedIcon,{size:"medium"}))))}function m(e){var t=e.field;return n.createElement(o.FieldConnector,{field:t,isInitiallyDisabled:e.isInitiallyDisabled},(function(e){return n.createElement(f,{disabled:e.disabled,errors:e.errors,field:t,setValue:e.setValue,value:e.value})}))}!function(e){e.Increment="increment",e.Decrement="decrement"}(t||(t={})),m.defaultProps={isInitiallyDisabled:!0},exports.NumberEditor=m;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("react"),n=require("@contentful/f36-components"),r=require("@contentful/f36-icons"),i=require("@contentful/field-editor-shared"),o=(e=require("@contentful/f36-tokens"))&&"object"==typeof e&&"default"in e?e.default:e,a=require("emotion");const l={container:a.css({position:"relative"}),controlsWrapper:a.css({position:"absolute",top:"1px",right:"1px",width:o.spacingL,height:"calc(100% - 2px)",display:"flex",flexDirection:"column"}),control:a.css({display:"flex",alignItems:"center",justifyContent:"center",minHeight:0,cursor:"pointer",padding:0,margin:0,outline:"none",border:"0 solid "+o.gray300,background:"none",borderLeftWidth:"1px","&:first-of-type":{borderTopRightRadius:o.borderRadiusMedium},"&:last-of-type":{borderTopWidth:"1px",borderBottomRightRadius:o.borderRadiusMedium},svg:{fill:o.gray600},"&:hover":{backgroundColor:o.gray200},"&:active":{backgroundColor:o.gray300}}),input:a.css({paddingRight:o.spacingXl})},s=/^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/,u=/^[+-]?([0-9]*)$/,c=e=>void 0===e?"":String(e);var d;function m({disabled:e,errors:i,field:o,setValue:a,value:m}){const[p,f]=t.useState(c(m)),v=(e=>{const t=(e.validations||[]).find(e=>e.range);return t?t.range:{}})(o),b=t.useRef(null);t.useEffect(()=>{const e=c(m);e!==p&&f(e)},[m]);const g=e=>{m!==e&&a(e)},x=e=>{const t=Number.isNaN(+p)?0:+p;let n=e===d.Increment?t+1:t-1;var r,i;n=+n.toFixed((r=t,(null==(i=r.toString().split(".")[1])?void 0:i.length)??0)),f(c(n)),a(n)},y=e=>{var t;e.preventDefault(),null==(t=b.current)||t.focus()};return t.createElement("div",{"data-test-id":"number-editor",className:l.container},t.createElement(n.TextInput,{type:"text",testId:"number-editor-input",className:l.input,min:v.min,max:v.max,isRequired:o.required,isInvalid:i.length>0,isDisabled:e,value:p,ref:b,onChange:e=>{const t=e.target.value;if(!t)return f(t),void g(void 0);if(!function(e,t){return("Integer"===t?u:s).test(e)}(t,o.type))return;f(t);const n=function(e,t){if(!Number.isNaN(+e))return"Integer"===t?parseInt(e,10):parseFloat(e)}(t,o.type);o.setInvalid(void 0===n),void 0!==n&&g(n)},onKeyDown:e=>{const t={ArrowUp:()=>x(d.Increment),ArrowDown:()=>x(d.Decrement)}[e.key];t&&(e.preventDefault(),t())},role:"spinbutton","aria-valuenow":m??0,"aria-valuetext":p,"aria-valuemin":v.min,"aria-valuemax":v.max}),!e&&t.createElement("div",{className:l.controlsWrapper,"aria-hidden":"true"},t.createElement("button",{tabIndex:-1,className:l.control,onClick:()=>x(d.Increment),onPointerDown:y},t.createElement(r.ArrowUpTrimmedIcon,{size:"medium"})),t.createElement("button",{tabIndex:-1,className:l.control,onClick:()=>x(d.Decrement),onPointerDown:y},t.createElement(r.ArrowDownTrimmedIcon,{size:"medium"}))))}function p(e){const{field:n}=e;return t.createElement(i.FieldConnector,{field:n,isInitiallyDisabled:e.isInitiallyDisabled},({value:e,errors:r,disabled:i,setValue:o})=>t.createElement(m,{disabled:i,errors:r,field:n,setValue:o,value:e}))}!function(e){e.Increment="increment",e.Decrement="decrement"}(d||(d={})),p.defaultProps={isInitiallyDisabled:!0},exports.NumberEditor=p;
2
2
  //# sourceMappingURL=field-editor-number.cjs.production.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"field-editor-number.cjs.production.min.js","sources":["../src/NumberEditor.tsx","../src/NumberEditor.styles.ts","../src/parseNumber.ts","../src/utils.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { TextInput } from '@contentful/f36-components';\nimport { ArrowUpTrimmedIcon, ArrowDownTrimmedIcon } from '@contentful/f36-icons';\nimport {\n FieldAPI,\n FieldConnector,\n FieldConnectorChildProps,\n} from '@contentful/field-editor-shared';\n\nimport { styles } from './NumberEditor.styles';\nimport { isNumberInputValueValid, parseNumber } from './parseNumber';\nimport { getRangeFromField, valueToString, countDecimals } from './utils';\n\nexport interface NumberEditorProps {\n /**\n * is the field disabled initially\n */\n isInitiallyDisabled: boolean;\n\n /**\n * sdk.field\n */\n field: FieldAPI;\n}\n\ntype InnerNumberEditorProps = Pick<\n FieldConnectorChildProps<number>,\n 'disabled' | 'errors' | 'setValue' | 'value'\n> & {\n field: NumberEditorProps['field'];\n};\n\nenum StepChangeType {\n Increment = 'increment',\n Decrement = 'decrement',\n}\n\nconst NUMBER_STEP = 1;\n\nfunction InnerNumberEditor({\n disabled,\n errors,\n field,\n setValue,\n value: sdkValue,\n}: InnerNumberEditorProps) {\n const [inputValue, setInputValue] = React.useState(valueToString(sdkValue));\n const range = getRangeFromField(field);\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n React.useEffect(() => {\n const stringSdkValue = valueToString(sdkValue);\n // Update the input value if the SDK value (numeric) changes\n if (stringSdkValue !== inputValue) {\n setInputValue(stringSdkValue);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- we want to trigger it only when sdkValue has changed\n }, [sdkValue]);\n\n const updateExternalValue = (value: number | undefined) => {\n if (sdkValue !== value) {\n setValue(value);\n }\n };\n\n const changeValueByStep = (type: StepChangeType) => {\n const currentValue = Number.isNaN(+inputValue) ? 0 : +inputValue;\n let nextValue =\n type === StepChangeType.Increment ? currentValue + NUMBER_STEP : currentValue - NUMBER_STEP;\n // Floating point numbers cannot represent all decimals precisely in binary.\n // This can lead to unexpected results, such as 0.1 + 0.2 = 0.30000000000000004.\n // See more details: https://floating-point-gui.de/\n nextValue = +nextValue.toFixed(countDecimals(currentValue));\n\n setInputValue(valueToString(nextValue));\n setValue(nextValue);\n };\n\n // Keeps focus on the input\n const handleControlPointerDown: React.PointerEventHandler<HTMLButtonElement> = (event) => {\n event.preventDefault();\n inputRef.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<any>) => {\n const keyToFnMap: {\n [key: string]: () => void;\n } = {\n ArrowUp: () => changeValueByStep(StepChangeType.Increment),\n ArrowDown: () => changeValueByStep(StepChangeType.Decrement),\n };\n\n const fn = keyToFnMap[event.key];\n if (fn) {\n event.preventDefault();\n fn();\n }\n };\n\n const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {\n const value = e.target.value;\n if (!value) {\n setInputValue(value);\n updateExternalValue(undefined);\n return;\n }\n\n if (!isNumberInputValueValid(value, field.type)) {\n return;\n }\n\n setInputValue(value);\n\n const parsedNumber = parseNumber(value, field.type);\n field.setInvalid(parsedNumber === undefined);\n if (parsedNumber !== undefined) {\n updateExternalValue(parsedNumber);\n }\n };\n\n return (\n <div data-test-id=\"number-editor\" className={styles.container}>\n <TextInput\n // With type=\"number\" react doesn't call onChange for certain inputs, for example if you type `e`\n // so we use \"text\" instead and fully rely on our own validation.\n // See more details: https://github.com/facebook/react/issues/6556\n type=\"text\"\n testId=\"number-editor-input\"\n className={styles.input}\n min={range.min}\n max={range.max}\n isRequired={field.required}\n isInvalid={errors.length > 0}\n isDisabled={disabled}\n value={inputValue}\n ref={inputRef}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n // The same role that input type=\"number\" has\n // See more details: https://www.digitala11y.com/spinbutton-role/\n role=\"spinbutton\"\n aria-valuenow={sdkValue ?? 0}\n aria-valuetext={inputValue}\n aria-valuemin={range.min}\n aria-valuemax={range.max}\n />\n {/**\n * We hide this controls from screen readers and keyboard focus.\n * For those purposes we have a keyboard handler. The same way native input number works.\n */}\n {!disabled && (\n <div className={styles.controlsWrapper} aria-hidden=\"true\">\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Increment)}\n onPointerDown={handleControlPointerDown}>\n <ArrowUpTrimmedIcon size=\"medium\" />\n </button>\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Decrement)}\n onPointerDown={handleControlPointerDown}>\n <ArrowDownTrimmedIcon size=\"medium\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport function NumberEditor(props: NumberEditorProps) {\n const { field } = props;\n\n return (\n <FieldConnector<number> field={field} isInitiallyDisabled={props.isInitiallyDisabled}>\n {({\n value,\n errors,\n disabled,\n setValue,\n }: Pick<FieldConnectorChildProps<number>, 'disabled' | 'errors' | 'setValue' | 'value'>) => (\n <InnerNumberEditor\n disabled={disabled}\n errors={errors}\n field={field}\n setValue={setValue}\n value={value}\n />\n )}\n </FieldConnector>\n );\n}\n\nNumberEditor.defaultProps = {\n isInitiallyDisabled: true,\n};\n","import tokens from '@contentful/f36-tokens';\nimport { css } from 'emotion';\n\nexport const styles = {\n container: css({\n position: 'relative',\n }),\n controlsWrapper: css({\n position: 'absolute',\n top: '1px',\n right: '1px',\n width: tokens.spacingL,\n height: 'calc(100% - 2px)',\n display: 'flex',\n flexDirection: 'column',\n }),\n control: css({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 0,\n cursor: 'pointer',\n padding: 0,\n margin: 0,\n outline: 'none',\n border: `0 solid ${tokens.gray300}`,\n background: 'none',\n borderLeftWidth: '1px',\n\n '&:first-of-type': {\n borderTopRightRadius: tokens.borderRadiusMedium,\n },\n\n '&:last-of-type': {\n borderTopWidth: '1px',\n borderBottomRightRadius: tokens.borderRadiusMedium,\n },\n\n svg: {\n fill: tokens.gray600,\n },\n\n '&:hover': {\n backgroundColor: tokens.gray200,\n },\n\n '&:active': {\n backgroundColor: tokens.gray300,\n },\n }),\n input: css({\n paddingRight: tokens.spacingXl,\n }),\n};\n","export function parseNumber(value: string, type: string) {\n if (Number.isNaN(+value)) {\n return;\n }\n\n return type === 'Integer' ? parseInt(value, 10) : parseFloat(value);\n}\n\nconst FLOAT_REGEX = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/;\nconst INT_REGEX = /^[+-]?([0-9]*)$/;\n\nexport function isNumberInputValueValid(value: string, type: string) {\n const regex = type === 'Integer' ? INT_REGEX : FLOAT_REGEX;\n\n return regex.test(value);\n}\n","import { FieldAPI } from '@contentful/field-editor-shared';\n\ntype RangeValidation = { min?: number; max?: number };\n\nexport const getRangeFromField = (field: FieldAPI): RangeValidation => {\n const validations = field.validations || [];\n const result = validations.find((validation) => (validation as any).range) as\n | { range: RangeValidation }\n | undefined;\n return result ? result.range : {};\n};\n\nexport const valueToString = (value: number | null | undefined) => {\n return value === undefined ? '' : String(value);\n};\n\nexport const countDecimals = (number: number) => {\n return number.toString().split('.')[1]?.length ?? 0;\n};\n"],"names":["StepChangeType","styles","container","css","position","controlsWrapper","top","right","width","tokens","spacingL","height","display","flexDirection","control","alignItems","justifyContent","minHeight","cursor","padding","margin","outline","border","gray300","background","borderLeftWidth","borderTopRightRadius","borderRadiusMedium","borderTopWidth","borderBottomRightRadius","svg","fill","gray600","backgroundColor","gray200","input","paddingRight","spacingXl","FLOAT_REGEX","INT_REGEX","valueToString","value","undefined","String","InnerNumberEditor","disabled","errors","field","setValue","sdkValue","React","inputValue","setInputValue","range","result","validations","find","validation","getRangeFromField","inputRef","stringSdkValue","updateExternalValue","changeValueByStep","type","number","currentValue","Number","isNaN","nextValue","Increment","toFixed","toString","split","_number$toString$spli2","length","handleControlPointerDown","event","preventDefault","current","focus","className","TextInput","testId","min","max","isRequired","required","isInvalid","isDisabled","ref","onChange","e","target","test","isNumberInputValueValid","parsedNumber","parseInt","parseFloat","parseNumber","setInvalid","onKeyDown","fn","ArrowUp","ArrowDown","Decrement","key","role","tabIndex","onClick","onPointerDown","ArrowUpTrimmedIcon","size","ArrowDownTrimmedIcon","NumberEditor","props","FieldConnector","isInitiallyDisabled","defaultProps"],"mappings":"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"}
1
+ {"version":3,"file":"field-editor-number.cjs.production.min.js","sources":["../src/NumberEditor.styles.ts","../src/parseNumber.ts","../src/utils.ts","../src/NumberEditor.tsx"],"sourcesContent":["import tokens from '@contentful/f36-tokens';\nimport { css } from 'emotion';\n\nexport const styles = {\n container: css({\n position: 'relative',\n }),\n controlsWrapper: css({\n position: 'absolute',\n top: '1px',\n right: '1px',\n width: tokens.spacingL,\n height: 'calc(100% - 2px)',\n display: 'flex',\n flexDirection: 'column',\n }),\n control: css({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 0,\n cursor: 'pointer',\n padding: 0,\n margin: 0,\n outline: 'none',\n border: `0 solid ${tokens.gray300}`,\n background: 'none',\n borderLeftWidth: '1px',\n\n '&:first-of-type': {\n borderTopRightRadius: tokens.borderRadiusMedium,\n },\n\n '&:last-of-type': {\n borderTopWidth: '1px',\n borderBottomRightRadius: tokens.borderRadiusMedium,\n },\n\n svg: {\n fill: tokens.gray600,\n },\n\n '&:hover': {\n backgroundColor: tokens.gray200,\n },\n\n '&:active': {\n backgroundColor: tokens.gray300,\n },\n }),\n input: css({\n paddingRight: tokens.spacingXl,\n }),\n};\n","export function parseNumber(value: string, type: string) {\n if (Number.isNaN(+value)) {\n return;\n }\n\n return type === 'Integer' ? parseInt(value, 10) : parseFloat(value);\n}\n\nconst FLOAT_REGEX = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/;\nconst INT_REGEX = /^[+-]?([0-9]*)$/;\n\nexport function isNumberInputValueValid(value: string, type: string) {\n const regex = type === 'Integer' ? INT_REGEX : FLOAT_REGEX;\n\n return regex.test(value);\n}\n","import { FieldAPI } from '@contentful/field-editor-shared';\n\ntype RangeValidation = { min?: number; max?: number };\n\nexport const getRangeFromField = (field: FieldAPI): RangeValidation => {\n const validations = field.validations || [];\n const result = validations.find((validation) => (validation as any).range) as\n | { range: RangeValidation }\n | undefined;\n return result ? result.range : {};\n};\n\nexport const valueToString = (value: number | null | undefined) => {\n return value === undefined ? '' : String(value);\n};\n\nexport const countDecimals = (number: number) => {\n return number.toString().split('.')[1]?.length ?? 0;\n};\n","import * as React from 'react';\n\nimport { TextInput } from '@contentful/f36-components';\nimport { ArrowUpTrimmedIcon, ArrowDownTrimmedIcon } from '@contentful/f36-icons';\nimport {\n FieldAPI,\n FieldConnector,\n FieldConnectorChildProps,\n} from '@contentful/field-editor-shared';\n\nimport { styles } from './NumberEditor.styles';\nimport { isNumberInputValueValid, parseNumber } from './parseNumber';\nimport { getRangeFromField, valueToString, countDecimals } from './utils';\n\nexport interface NumberEditorProps {\n /**\n * is the field disabled initially\n */\n isInitiallyDisabled: boolean;\n\n /**\n * sdk.field\n */\n field: FieldAPI;\n}\n\ntype InnerNumberEditorProps = Pick<\n FieldConnectorChildProps<number>,\n 'disabled' | 'errors' | 'setValue' | 'value'\n> & {\n field: NumberEditorProps['field'];\n};\n\nenum StepChangeType {\n Increment = 'increment',\n Decrement = 'decrement',\n}\n\nconst NUMBER_STEP = 1;\n\nfunction InnerNumberEditor({\n disabled,\n errors,\n field,\n setValue,\n value: sdkValue,\n}: InnerNumberEditorProps) {\n const [inputValue, setInputValue] = React.useState(valueToString(sdkValue));\n const range = getRangeFromField(field);\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n React.useEffect(() => {\n const stringSdkValue = valueToString(sdkValue);\n // Update the input value if the SDK value (numeric) changes\n if (stringSdkValue !== inputValue) {\n setInputValue(stringSdkValue);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- we want to trigger it only when sdkValue has changed\n }, [sdkValue]);\n\n const updateExternalValue = (value: number | undefined) => {\n if (sdkValue !== value) {\n setValue(value);\n }\n };\n\n const changeValueByStep = (type: StepChangeType) => {\n const currentValue = Number.isNaN(+inputValue) ? 0 : +inputValue;\n let nextValue =\n type === StepChangeType.Increment ? currentValue + NUMBER_STEP : currentValue - NUMBER_STEP;\n // Floating point numbers cannot represent all decimals precisely in binary.\n // This can lead to unexpected results, such as 0.1 + 0.2 = 0.30000000000000004.\n // See more details: https://floating-point-gui.de/\n nextValue = +nextValue.toFixed(countDecimals(currentValue));\n\n setInputValue(valueToString(nextValue));\n setValue(nextValue);\n };\n\n // Keeps focus on the input\n const handleControlPointerDown: React.PointerEventHandler<HTMLButtonElement> = (event) => {\n event.preventDefault();\n inputRef.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<any>) => {\n const keyToFnMap: {\n [key: string]: () => void;\n } = {\n ArrowUp: () => changeValueByStep(StepChangeType.Increment),\n ArrowDown: () => changeValueByStep(StepChangeType.Decrement),\n };\n\n const fn = keyToFnMap[event.key];\n if (fn) {\n event.preventDefault();\n fn();\n }\n };\n\n const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {\n const value = e.target.value;\n if (!value) {\n setInputValue(value);\n updateExternalValue(undefined);\n return;\n }\n\n if (!isNumberInputValueValid(value, field.type)) {\n return;\n }\n\n setInputValue(value);\n\n const parsedNumber = parseNumber(value, field.type);\n field.setInvalid(parsedNumber === undefined);\n if (parsedNumber !== undefined) {\n updateExternalValue(parsedNumber);\n }\n };\n\n return (\n <div data-test-id=\"number-editor\" className={styles.container}>\n <TextInput\n // With type=\"number\" react doesn't call onChange for certain inputs, for example if you type `e`\n // so we use \"text\" instead and fully rely on our own validation.\n // See more details: https://github.com/facebook/react/issues/6556\n type=\"text\"\n testId=\"number-editor-input\"\n className={styles.input}\n min={range.min}\n max={range.max}\n isRequired={field.required}\n isInvalid={errors.length > 0}\n isDisabled={disabled}\n value={inputValue}\n ref={inputRef}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n // The same role that input type=\"number\" has\n // See more details: https://www.digitala11y.com/spinbutton-role/\n role=\"spinbutton\"\n aria-valuenow={sdkValue ?? 0}\n aria-valuetext={inputValue}\n aria-valuemin={range.min}\n aria-valuemax={range.max}\n />\n {/**\n * We hide this controls from screen readers and keyboard focus.\n * For those purposes we have a keyboard handler. The same way native input number works.\n */}\n {!disabled && (\n <div className={styles.controlsWrapper} aria-hidden=\"true\">\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Increment)}\n onPointerDown={handleControlPointerDown}>\n <ArrowUpTrimmedIcon size=\"medium\" />\n </button>\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Decrement)}\n onPointerDown={handleControlPointerDown}>\n <ArrowDownTrimmedIcon size=\"medium\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport function NumberEditor(props: NumberEditorProps) {\n const { field } = props;\n\n return (\n <FieldConnector<number> field={field} isInitiallyDisabled={props.isInitiallyDisabled}>\n {({\n value,\n errors,\n disabled,\n setValue,\n }: Pick<FieldConnectorChildProps<number>, 'disabled' | 'errors' | 'setValue' | 'value'>) => (\n <InnerNumberEditor\n disabled={disabled}\n errors={errors}\n field={field}\n setValue={setValue}\n value={value}\n />\n )}\n </FieldConnector>\n );\n}\n\nNumberEditor.defaultProps = {\n isInitiallyDisabled: true,\n};\n"],"names":["styles","container","css","position","controlsWrapper","top","right","width","tokens","spacingL","height","display","flexDirection","control","alignItems","justifyContent","minHeight","cursor","padding","margin","outline","border","gray300","background","borderLeftWidth","borderTopRightRadius","borderRadiusMedium","borderTopWidth","borderBottomRightRadius","svg","fill","gray600","backgroundColor","gray200","input","paddingRight","spacingXl","FLOAT_REGEX","INT_REGEX","valueToString","value","undefined","String","StepChangeType","InnerNumberEditor","disabled","errors","field","setValue","sdkValue","inputValue","setInputValue","React","range","result","validations","find","validation","getRangeFromField","inputRef","stringSdkValue","updateExternalValue","changeValueByStep","type","currentValue","Number","isNaN","nextValue","Increment","number","toFixed","toString","split","length","handleControlPointerDown","event","preventDefault","current","focus","className","TextInput","testId","min","max","isRequired","required","isInvalid","isDisabled","ref","onChange","e","target","test","isNumberInputValueValid","parsedNumber","parseInt","parseFloat","parseNumber","setInvalid","onKeyDown","fn","ArrowUp","ArrowDown","Decrement","key","role","tabIndex","onClick","onPointerDown","ArrowUpTrimmedIcon","size","ArrowDownTrimmedIcon","NumberEditor","props","FieldConnector","isInitiallyDisabled","defaultProps"],"mappings":"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"}
@@ -5,7 +5,7 @@ import { FieldConnector } from '@contentful/field-editor-shared';
5
5
  import tokens from '@contentful/f36-tokens';
6
6
  import { css } from 'emotion';
7
7
 
8
- var styles = {
8
+ const styles = {
9
9
  container: /*#__PURE__*/css({
10
10
  position: 'relative'
11
11
  }),
@@ -27,7 +27,7 @@ var styles = {
27
27
  padding: 0,
28
28
  margin: 0,
29
29
  outline: 'none',
30
- border: "0 solid " + tokens.gray300,
30
+ border: `0 solid ${tokens.gray300}`,
31
31
  background: 'none',
32
32
  borderLeftWidth: '1px',
33
33
  '&:first-of-type': {
@@ -59,27 +59,25 @@ function parseNumber(value, type) {
59
59
 
60
60
  return type === 'Integer' ? parseInt(value, 10) : parseFloat(value);
61
61
  }
62
- var FLOAT_REGEX = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/;
63
- var INT_REGEX = /^[+-]?([0-9]*)$/;
62
+ const FLOAT_REGEX = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/;
63
+ const INT_REGEX = /^[+-]?([0-9]*)$/;
64
64
  function isNumberInputValueValid(value, type) {
65
- var regex = type === 'Integer' ? INT_REGEX : FLOAT_REGEX;
65
+ const regex = type === 'Integer' ? INT_REGEX : FLOAT_REGEX;
66
66
  return regex.test(value);
67
67
  }
68
68
 
69
- var getRangeFromField = function getRangeFromField(field) {
70
- var validations = field.validations || [];
71
- var result = validations.find(function (validation) {
72
- return validation.range;
73
- });
69
+ const getRangeFromField = field => {
70
+ const validations = field.validations || [];
71
+ const result = validations.find(validation => validation.range);
74
72
  return result ? result.range : {};
75
73
  };
76
- var valueToString = function valueToString(value) {
74
+ const valueToString = value => {
77
75
  return value === undefined ? '' : String(value);
78
76
  };
79
- var countDecimals = function countDecimals(number) {
80
- var _number$toString$spli, _number$toString$spli2;
77
+ const countDecimals = number => {
78
+ var _number$toString$spli;
81
79
 
82
- return (_number$toString$spli = (_number$toString$spli2 = number.toString().split('.')[1]) == null ? void 0 : _number$toString$spli2.length) != null ? _number$toString$spli : 0;
80
+ return ((_number$toString$spli = number.toString().split('.')[1]) == null ? void 0 : _number$toString$spli.length) ?? 0;
83
81
  };
84
82
 
85
83
  var StepChangeType;
@@ -89,23 +87,20 @@ var StepChangeType;
89
87
  StepChangeType["Decrement"] = "decrement";
90
88
  })(StepChangeType || (StepChangeType = {}));
91
89
 
92
- var NUMBER_STEP = 1;
93
-
94
- function InnerNumberEditor(_ref) {
95
- var disabled = _ref.disabled,
96
- errors = _ref.errors,
97
- field = _ref.field,
98
- setValue = _ref.setValue,
99
- sdkValue = _ref.value;
100
-
101
- var _React$useState = useState(valueToString(sdkValue)),
102
- inputValue = _React$useState[0],
103
- setInputValue = _React$useState[1];
104
-
105
- var range = getRangeFromField(field);
106
- var inputRef = useRef(null);
107
- useEffect(function () {
108
- var stringSdkValue = valueToString(sdkValue); // Update the input value if the SDK value (numeric) changes
90
+ const NUMBER_STEP = 1;
91
+
92
+ function InnerNumberEditor({
93
+ disabled,
94
+ errors,
95
+ field,
96
+ setValue,
97
+ value: sdkValue
98
+ }) {
99
+ const [inputValue, setInputValue] = useState(valueToString(sdkValue));
100
+ const range = getRangeFromField(field);
101
+ const inputRef = useRef(null);
102
+ useEffect(() => {
103
+ const stringSdkValue = valueToString(sdkValue); // Update the input value if the SDK value (numeric) changes
109
104
 
110
105
  if (stringSdkValue !== inputValue) {
111
106
  setInputValue(stringSdkValue);
@@ -113,15 +108,15 @@ function InnerNumberEditor(_ref) {
113
108
 
114
109
  }, [sdkValue]);
115
110
 
116
- var updateExternalValue = function updateExternalValue(value) {
111
+ const updateExternalValue = value => {
117
112
  if (sdkValue !== value) {
118
113
  setValue(value);
119
114
  }
120
115
  };
121
116
 
122
- var changeValueByStep = function changeValueByStep(type) {
123
- var currentValue = Number.isNaN(+inputValue) ? 0 : +inputValue;
124
- var nextValue = type === StepChangeType.Increment ? currentValue + NUMBER_STEP : currentValue - NUMBER_STEP; // Floating point numbers cannot represent all decimals precisely in binary.
117
+ const changeValueByStep = type => {
118
+ const currentValue = Number.isNaN(+inputValue) ? 0 : +inputValue;
119
+ let nextValue = type === StepChangeType.Increment ? currentValue + NUMBER_STEP : currentValue - NUMBER_STEP; // Floating point numbers cannot represent all decimals precisely in binary.
125
120
  // This can lead to unexpected results, such as 0.1 + 0.2 = 0.30000000000000004.
126
121
  // See more details: https://floating-point-gui.de/
127
122
 
@@ -131,23 +126,19 @@ function InnerNumberEditor(_ref) {
131
126
  }; // Keeps focus on the input
132
127
 
133
128
 
134
- var handleControlPointerDown = function handleControlPointerDown(event) {
129
+ const handleControlPointerDown = event => {
135
130
  var _inputRef$current;
136
131
 
137
132
  event.preventDefault();
138
133
  (_inputRef$current = inputRef.current) == null ? void 0 : _inputRef$current.focus();
139
134
  };
140
135
 
141
- var handleKeyDown = function handleKeyDown(event) {
142
- var keyToFnMap = {
143
- ArrowUp: function ArrowUp() {
144
- return changeValueByStep(StepChangeType.Increment);
145
- },
146
- ArrowDown: function ArrowDown() {
147
- return changeValueByStep(StepChangeType.Decrement);
148
- }
136
+ const handleKeyDown = event => {
137
+ const keyToFnMap = {
138
+ ArrowUp: () => changeValueByStep(StepChangeType.Increment),
139
+ ArrowDown: () => changeValueByStep(StepChangeType.Decrement)
149
140
  };
150
- var fn = keyToFnMap[event.key];
141
+ const fn = keyToFnMap[event.key];
151
142
 
152
143
  if (fn) {
153
144
  event.preventDefault();
@@ -155,8 +146,8 @@ function InnerNumberEditor(_ref) {
155
146
  }
156
147
  };
157
148
 
158
- var handleInputChange = function handleInputChange(e) {
159
- var value = e.target.value;
149
+ const handleInputChange = e => {
150
+ const value = e.target.value;
160
151
 
161
152
  if (!value) {
162
153
  setInputValue(value);
@@ -169,7 +160,7 @@ function InnerNumberEditor(_ref) {
169
160
  }
170
161
 
171
162
  setInputValue(value);
172
- var parsedNumber = parseNumber(value, field.type);
163
+ const parsedNumber = parseNumber(value, field.type);
173
164
  field.setInvalid(parsedNumber === undefined);
174
165
 
175
166
  if (parsedNumber !== undefined) {
@@ -202,7 +193,7 @@ function InnerNumberEditor(_ref) {
202
193
  // The same role that input type="number" has
203
194
  // See more details: https://www.digitala11y.com/spinbutton-role/
204
195
  role: "spinbutton",
205
- "aria-valuenow": sdkValue != null ? sdkValue : 0,
196
+ "aria-valuenow": sdkValue ?? 0,
206
197
  "aria-valuetext": inputValue,
207
198
  "aria-valuemin": range.min,
208
199
  "aria-valuemax": range.max
@@ -212,18 +203,14 @@ function InnerNumberEditor(_ref) {
212
203
  }, createElement("button", {
213
204
  tabIndex: -1,
214
205
  className: styles.control,
215
- onClick: function onClick() {
216
- return changeValueByStep(StepChangeType.Increment);
217
- },
206
+ onClick: () => changeValueByStep(StepChangeType.Increment),
218
207
  onPointerDown: handleControlPointerDown
219
208
  }, createElement(ArrowUpTrimmedIcon, {
220
209
  size: "medium"
221
210
  })), createElement("button", {
222
211
  tabIndex: -1,
223
212
  className: styles.control,
224
- onClick: function onClick() {
225
- return changeValueByStep(StepChangeType.Decrement);
226
- },
213
+ onClick: () => changeValueByStep(StepChangeType.Decrement),
227
214
  onPointerDown: handleControlPointerDown
228
215
  }, createElement(ArrowDownTrimmedIcon, {
229
216
  size: "medium"
@@ -231,23 +218,24 @@ function InnerNumberEditor(_ref) {
231
218
  }
232
219
 
233
220
  function NumberEditor(props) {
234
- var field = props.field;
221
+ const {
222
+ field
223
+ } = props;
235
224
  return createElement(FieldConnector, {
236
225
  field: field,
237
226
  isInitiallyDisabled: props.isInitiallyDisabled
238
- }, function (_ref2) {
239
- var value = _ref2.value,
240
- errors = _ref2.errors,
241
- disabled = _ref2.disabled,
242
- setValue = _ref2.setValue;
243
- return createElement(InnerNumberEditor, {
244
- disabled: disabled,
245
- errors: errors,
246
- field: field,
247
- setValue: setValue,
248
- value: value
249
- });
250
- });
227
+ }, ({
228
+ value,
229
+ errors,
230
+ disabled,
231
+ setValue
232
+ }) => createElement(InnerNumberEditor, {
233
+ disabled: disabled,
234
+ errors: errors,
235
+ field: field,
236
+ setValue: setValue,
237
+ value: value
238
+ }));
251
239
  }
252
240
  NumberEditor.defaultProps = {
253
241
  isInitiallyDisabled: true
@@ -1 +1 @@
1
- {"version":3,"file":"field-editor-number.esm.js","sources":["../src/NumberEditor.styles.ts","../src/parseNumber.ts","../src/utils.ts","../src/NumberEditor.tsx"],"sourcesContent":["import tokens from '@contentful/f36-tokens';\nimport { css } from 'emotion';\n\nexport const styles = {\n container: css({\n position: 'relative',\n }),\n controlsWrapper: css({\n position: 'absolute',\n top: '1px',\n right: '1px',\n width: tokens.spacingL,\n height: 'calc(100% - 2px)',\n display: 'flex',\n flexDirection: 'column',\n }),\n control: css({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 0,\n cursor: 'pointer',\n padding: 0,\n margin: 0,\n outline: 'none',\n border: `0 solid ${tokens.gray300}`,\n background: 'none',\n borderLeftWidth: '1px',\n\n '&:first-of-type': {\n borderTopRightRadius: tokens.borderRadiusMedium,\n },\n\n '&:last-of-type': {\n borderTopWidth: '1px',\n borderBottomRightRadius: tokens.borderRadiusMedium,\n },\n\n svg: {\n fill: tokens.gray600,\n },\n\n '&:hover': {\n backgroundColor: tokens.gray200,\n },\n\n '&:active': {\n backgroundColor: tokens.gray300,\n },\n }),\n input: css({\n paddingRight: tokens.spacingXl,\n }),\n};\n","export function parseNumber(value: string, type: string) {\n if (Number.isNaN(+value)) {\n return;\n }\n\n return type === 'Integer' ? parseInt(value, 10) : parseFloat(value);\n}\n\nconst FLOAT_REGEX = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/;\nconst INT_REGEX = /^[+-]?([0-9]*)$/;\n\nexport function isNumberInputValueValid(value: string, type: string) {\n const regex = type === 'Integer' ? INT_REGEX : FLOAT_REGEX;\n\n return regex.test(value);\n}\n","import { FieldAPI } from '@contentful/field-editor-shared';\n\ntype RangeValidation = { min?: number; max?: number };\n\nexport const getRangeFromField = (field: FieldAPI): RangeValidation => {\n const validations = field.validations || [];\n const result = validations.find((validation) => (validation as any).range) as\n | { range: RangeValidation }\n | undefined;\n return result ? result.range : {};\n};\n\nexport const valueToString = (value: number | null | undefined) => {\n return value === undefined ? '' : String(value);\n};\n\nexport const countDecimals = (number: number) => {\n return number.toString().split('.')[1]?.length ?? 0;\n};\n","import * as React from 'react';\n\nimport { TextInput } from '@contentful/f36-components';\nimport { ArrowUpTrimmedIcon, ArrowDownTrimmedIcon } from '@contentful/f36-icons';\nimport {\n FieldAPI,\n FieldConnector,\n FieldConnectorChildProps,\n} from '@contentful/field-editor-shared';\n\nimport { styles } from './NumberEditor.styles';\nimport { isNumberInputValueValid, parseNumber } from './parseNumber';\nimport { getRangeFromField, valueToString, countDecimals } from './utils';\n\nexport interface NumberEditorProps {\n /**\n * is the field disabled initially\n */\n isInitiallyDisabled: boolean;\n\n /**\n * sdk.field\n */\n field: FieldAPI;\n}\n\ntype InnerNumberEditorProps = Pick<\n FieldConnectorChildProps<number>,\n 'disabled' | 'errors' | 'setValue' | 'value'\n> & {\n field: NumberEditorProps['field'];\n};\n\nenum StepChangeType {\n Increment = 'increment',\n Decrement = 'decrement',\n}\n\nconst NUMBER_STEP = 1;\n\nfunction InnerNumberEditor({\n disabled,\n errors,\n field,\n setValue,\n value: sdkValue,\n}: InnerNumberEditorProps) {\n const [inputValue, setInputValue] = React.useState(valueToString(sdkValue));\n const range = getRangeFromField(field);\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n React.useEffect(() => {\n const stringSdkValue = valueToString(sdkValue);\n // Update the input value if the SDK value (numeric) changes\n if (stringSdkValue !== inputValue) {\n setInputValue(stringSdkValue);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- we want to trigger it only when sdkValue has changed\n }, [sdkValue]);\n\n const updateExternalValue = (value: number | undefined) => {\n if (sdkValue !== value) {\n setValue(value);\n }\n };\n\n const changeValueByStep = (type: StepChangeType) => {\n const currentValue = Number.isNaN(+inputValue) ? 0 : +inputValue;\n let nextValue =\n type === StepChangeType.Increment ? currentValue + NUMBER_STEP : currentValue - NUMBER_STEP;\n // Floating point numbers cannot represent all decimals precisely in binary.\n // This can lead to unexpected results, such as 0.1 + 0.2 = 0.30000000000000004.\n // See more details: https://floating-point-gui.de/\n nextValue = +nextValue.toFixed(countDecimals(currentValue));\n\n setInputValue(valueToString(nextValue));\n setValue(nextValue);\n };\n\n // Keeps focus on the input\n const handleControlPointerDown: React.PointerEventHandler<HTMLButtonElement> = (event) => {\n event.preventDefault();\n inputRef.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<any>) => {\n const keyToFnMap: {\n [key: string]: () => void;\n } = {\n ArrowUp: () => changeValueByStep(StepChangeType.Increment),\n ArrowDown: () => changeValueByStep(StepChangeType.Decrement),\n };\n\n const fn = keyToFnMap[event.key];\n if (fn) {\n event.preventDefault();\n fn();\n }\n };\n\n const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {\n const value = e.target.value;\n if (!value) {\n setInputValue(value);\n updateExternalValue(undefined);\n return;\n }\n\n if (!isNumberInputValueValid(value, field.type)) {\n return;\n }\n\n setInputValue(value);\n\n const parsedNumber = parseNumber(value, field.type);\n field.setInvalid(parsedNumber === undefined);\n if (parsedNumber !== undefined) {\n updateExternalValue(parsedNumber);\n }\n };\n\n return (\n <div data-test-id=\"number-editor\" className={styles.container}>\n <TextInput\n // With type=\"number\" react doesn't call onChange for certain inputs, for example if you type `e`\n // so we use \"text\" instead and fully rely on our own validation.\n // See more details: https://github.com/facebook/react/issues/6556\n type=\"text\"\n testId=\"number-editor-input\"\n className={styles.input}\n min={range.min}\n max={range.max}\n isRequired={field.required}\n isInvalid={errors.length > 0}\n isDisabled={disabled}\n value={inputValue}\n ref={inputRef}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n // The same role that input type=\"number\" has\n // See more details: https://www.digitala11y.com/spinbutton-role/\n role=\"spinbutton\"\n aria-valuenow={sdkValue ?? 0}\n aria-valuetext={inputValue}\n aria-valuemin={range.min}\n aria-valuemax={range.max}\n />\n {/**\n * We hide this controls from screen readers and keyboard focus.\n * For those purposes we have a keyboard handler. The same way native input number works.\n */}\n {!disabled && (\n <div className={styles.controlsWrapper} aria-hidden=\"true\">\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Increment)}\n onPointerDown={handleControlPointerDown}>\n <ArrowUpTrimmedIcon size=\"medium\" />\n </button>\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Decrement)}\n onPointerDown={handleControlPointerDown}>\n <ArrowDownTrimmedIcon size=\"medium\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport function NumberEditor(props: NumberEditorProps) {\n const { field } = props;\n\n return (\n <FieldConnector<number> field={field} isInitiallyDisabled={props.isInitiallyDisabled}>\n {({\n value,\n errors,\n disabled,\n setValue,\n }: Pick<FieldConnectorChildProps<number>, 'disabled' | 'errors' | 'setValue' | 'value'>) => (\n <InnerNumberEditor\n disabled={disabled}\n errors={errors}\n field={field}\n setValue={setValue}\n value={value}\n />\n )}\n </FieldConnector>\n );\n}\n\nNumberEditor.defaultProps = {\n isInitiallyDisabled: true,\n};\n"],"names":["styles","container","css","position","controlsWrapper","top","right","width","tokens","spacingL","height","display","flexDirection","control","alignItems","justifyContent","minHeight","cursor","padding","margin","outline","border","gray300","background","borderLeftWidth","borderTopRightRadius","borderRadiusMedium","borderTopWidth","borderBottomRightRadius","svg","fill","gray600","backgroundColor","gray200","input","paddingRight","spacingXl","parseNumber","value","type","Number","isNaN","parseInt","parseFloat","FLOAT_REGEX","INT_REGEX","isNumberInputValueValid","regex","test","getRangeFromField","field","validations","result","find","validation","range","valueToString","undefined","String","countDecimals","number","toString","split","length","StepChangeType","NUMBER_STEP","InnerNumberEditor","disabled","errors","setValue","sdkValue","React","inputValue","setInputValue","inputRef","stringSdkValue","updateExternalValue","changeValueByStep","currentValue","nextValue","Increment","toFixed","handleControlPointerDown","event","preventDefault","current","focus","handleKeyDown","keyToFnMap","ArrowUp","ArrowDown","Decrement","fn","key","handleInputChange","e","target","parsedNumber","setInvalid","className","TextInput","testId","min","max","isRequired","required","isInvalid","isDisabled","ref","onChange","onKeyDown","role","tabIndex","onClick","onPointerDown","ArrowUpTrimmedIcon","size","ArrowDownTrimmedIcon","NumberEditor","props","FieldConnector","isInitiallyDisabled","defaultProps"],"mappings":"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"}
1
+ {"version":3,"file":"field-editor-number.esm.js","sources":["../src/NumberEditor.styles.ts","../src/parseNumber.ts","../src/utils.ts","../src/NumberEditor.tsx"],"sourcesContent":["import tokens from '@contentful/f36-tokens';\nimport { css } from 'emotion';\n\nexport const styles = {\n container: css({\n position: 'relative',\n }),\n controlsWrapper: css({\n position: 'absolute',\n top: '1px',\n right: '1px',\n width: tokens.spacingL,\n height: 'calc(100% - 2px)',\n display: 'flex',\n flexDirection: 'column',\n }),\n control: css({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 0,\n cursor: 'pointer',\n padding: 0,\n margin: 0,\n outline: 'none',\n border: `0 solid ${tokens.gray300}`,\n background: 'none',\n borderLeftWidth: '1px',\n\n '&:first-of-type': {\n borderTopRightRadius: tokens.borderRadiusMedium,\n },\n\n '&:last-of-type': {\n borderTopWidth: '1px',\n borderBottomRightRadius: tokens.borderRadiusMedium,\n },\n\n svg: {\n fill: tokens.gray600,\n },\n\n '&:hover': {\n backgroundColor: tokens.gray200,\n },\n\n '&:active': {\n backgroundColor: tokens.gray300,\n },\n }),\n input: css({\n paddingRight: tokens.spacingXl,\n }),\n};\n","export function parseNumber(value: string, type: string) {\n if (Number.isNaN(+value)) {\n return;\n }\n\n return type === 'Integer' ? parseInt(value, 10) : parseFloat(value);\n}\n\nconst FLOAT_REGEX = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/;\nconst INT_REGEX = /^[+-]?([0-9]*)$/;\n\nexport function isNumberInputValueValid(value: string, type: string) {\n const regex = type === 'Integer' ? INT_REGEX : FLOAT_REGEX;\n\n return regex.test(value);\n}\n","import { FieldAPI } from '@contentful/field-editor-shared';\n\ntype RangeValidation = { min?: number; max?: number };\n\nexport const getRangeFromField = (field: FieldAPI): RangeValidation => {\n const validations = field.validations || [];\n const result = validations.find((validation) => (validation as any).range) as\n | { range: RangeValidation }\n | undefined;\n return result ? result.range : {};\n};\n\nexport const valueToString = (value: number | null | undefined) => {\n return value === undefined ? '' : String(value);\n};\n\nexport const countDecimals = (number: number) => {\n return number.toString().split('.')[1]?.length ?? 0;\n};\n","import * as React from 'react';\n\nimport { TextInput } from '@contentful/f36-components';\nimport { ArrowUpTrimmedIcon, ArrowDownTrimmedIcon } from '@contentful/f36-icons';\nimport {\n FieldAPI,\n FieldConnector,\n FieldConnectorChildProps,\n} from '@contentful/field-editor-shared';\n\nimport { styles } from './NumberEditor.styles';\nimport { isNumberInputValueValid, parseNumber } from './parseNumber';\nimport { getRangeFromField, valueToString, countDecimals } from './utils';\n\nexport interface NumberEditorProps {\n /**\n * is the field disabled initially\n */\n isInitiallyDisabled: boolean;\n\n /**\n * sdk.field\n */\n field: FieldAPI;\n}\n\ntype InnerNumberEditorProps = Pick<\n FieldConnectorChildProps<number>,\n 'disabled' | 'errors' | 'setValue' | 'value'\n> & {\n field: NumberEditorProps['field'];\n};\n\nenum StepChangeType {\n Increment = 'increment',\n Decrement = 'decrement',\n}\n\nconst NUMBER_STEP = 1;\n\nfunction InnerNumberEditor({\n disabled,\n errors,\n field,\n setValue,\n value: sdkValue,\n}: InnerNumberEditorProps) {\n const [inputValue, setInputValue] = React.useState(valueToString(sdkValue));\n const range = getRangeFromField(field);\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n React.useEffect(() => {\n const stringSdkValue = valueToString(sdkValue);\n // Update the input value if the SDK value (numeric) changes\n if (stringSdkValue !== inputValue) {\n setInputValue(stringSdkValue);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- we want to trigger it only when sdkValue has changed\n }, [sdkValue]);\n\n const updateExternalValue = (value: number | undefined) => {\n if (sdkValue !== value) {\n setValue(value);\n }\n };\n\n const changeValueByStep = (type: StepChangeType) => {\n const currentValue = Number.isNaN(+inputValue) ? 0 : +inputValue;\n let nextValue =\n type === StepChangeType.Increment ? currentValue + NUMBER_STEP : currentValue - NUMBER_STEP;\n // Floating point numbers cannot represent all decimals precisely in binary.\n // This can lead to unexpected results, such as 0.1 + 0.2 = 0.30000000000000004.\n // See more details: https://floating-point-gui.de/\n nextValue = +nextValue.toFixed(countDecimals(currentValue));\n\n setInputValue(valueToString(nextValue));\n setValue(nextValue);\n };\n\n // Keeps focus on the input\n const handleControlPointerDown: React.PointerEventHandler<HTMLButtonElement> = (event) => {\n event.preventDefault();\n inputRef.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<any>) => {\n const keyToFnMap: {\n [key: string]: () => void;\n } = {\n ArrowUp: () => changeValueByStep(StepChangeType.Increment),\n ArrowDown: () => changeValueByStep(StepChangeType.Decrement),\n };\n\n const fn = keyToFnMap[event.key];\n if (fn) {\n event.preventDefault();\n fn();\n }\n };\n\n const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {\n const value = e.target.value;\n if (!value) {\n setInputValue(value);\n updateExternalValue(undefined);\n return;\n }\n\n if (!isNumberInputValueValid(value, field.type)) {\n return;\n }\n\n setInputValue(value);\n\n const parsedNumber = parseNumber(value, field.type);\n field.setInvalid(parsedNumber === undefined);\n if (parsedNumber !== undefined) {\n updateExternalValue(parsedNumber);\n }\n };\n\n return (\n <div data-test-id=\"number-editor\" className={styles.container}>\n <TextInput\n // With type=\"number\" react doesn't call onChange for certain inputs, for example if you type `e`\n // so we use \"text\" instead and fully rely on our own validation.\n // See more details: https://github.com/facebook/react/issues/6556\n type=\"text\"\n testId=\"number-editor-input\"\n className={styles.input}\n min={range.min}\n max={range.max}\n isRequired={field.required}\n isInvalid={errors.length > 0}\n isDisabled={disabled}\n value={inputValue}\n ref={inputRef}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n // The same role that input type=\"number\" has\n // See more details: https://www.digitala11y.com/spinbutton-role/\n role=\"spinbutton\"\n aria-valuenow={sdkValue ?? 0}\n aria-valuetext={inputValue}\n aria-valuemin={range.min}\n aria-valuemax={range.max}\n />\n {/**\n * We hide this controls from screen readers and keyboard focus.\n * For those purposes we have a keyboard handler. The same way native input number works.\n */}\n {!disabled && (\n <div className={styles.controlsWrapper} aria-hidden=\"true\">\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Increment)}\n onPointerDown={handleControlPointerDown}>\n <ArrowUpTrimmedIcon size=\"medium\" />\n </button>\n <button\n tabIndex={-1}\n className={styles.control}\n onClick={() => changeValueByStep(StepChangeType.Decrement)}\n onPointerDown={handleControlPointerDown}>\n <ArrowDownTrimmedIcon size=\"medium\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport function NumberEditor(props: NumberEditorProps) {\n const { field } = props;\n\n return (\n <FieldConnector<number> field={field} isInitiallyDisabled={props.isInitiallyDisabled}>\n {({\n value,\n errors,\n disabled,\n setValue,\n }: Pick<FieldConnectorChildProps<number>, 'disabled' | 'errors' | 'setValue' | 'value'>) => (\n <InnerNumberEditor\n disabled={disabled}\n errors={errors}\n field={field}\n setValue={setValue}\n value={value}\n />\n )}\n </FieldConnector>\n );\n}\n\nNumberEditor.defaultProps = {\n isInitiallyDisabled: true,\n};\n"],"names":["styles","container","css","position","controlsWrapper","top","right","width","tokens","spacingL","height","display","flexDirection","control","alignItems","justifyContent","minHeight","cursor","padding","margin","outline","border","gray300","background","borderLeftWidth","borderTopRightRadius","borderRadiusMedium","borderTopWidth","borderBottomRightRadius","svg","fill","gray600","backgroundColor","gray200","input","paddingRight","spacingXl","parseNumber","value","type","Number","isNaN","parseInt","parseFloat","FLOAT_REGEX","INT_REGEX","isNumberInputValueValid","regex","test","getRangeFromField","field","validations","result","find","validation","range","valueToString","undefined","String","countDecimals","number","toString","split","length","StepChangeType","NUMBER_STEP","InnerNumberEditor","disabled","errors","setValue","sdkValue","inputValue","setInputValue","React","inputRef","stringSdkValue","updateExternalValue","changeValueByStep","currentValue","nextValue","Increment","toFixed","handleControlPointerDown","event","preventDefault","current","focus","handleKeyDown","keyToFnMap","ArrowUp","ArrowDown","Decrement","fn","key","handleInputChange","e","target","parsedNumber","setInvalid","className","TextInput","testId","min","max","isRequired","required","isInvalid","isDisabled","ref","onChange","onKeyDown","role","tabIndex","onClick","onPointerDown","ArrowUpTrimmedIcon","size","ArrowDownTrimmedIcon","NumberEditor","props","FieldConnector","isInitiallyDisabled","defaultProps"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/field-editor-number",
3
- "version": "1.2.5",
3
+ "version": "1.2.6",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/field-editor-number.esm.js",
6
6
  "typings": "dist/index.d.ts",
@@ -23,11 +23,11 @@
23
23
  "dependencies": {
24
24
  "@contentful/f36-components": "^4.0.27",
25
25
  "@contentful/f36-tokens": "^4.0.0",
26
- "@contentful/field-editor-shared": "^1.1.8",
26
+ "@contentful/field-editor-shared": "^1.2.0",
27
27
  "emotion": "^10.0.17"
28
28
  },
29
29
  "devDependencies": {
30
- "@contentful/field-editor-test-utils": "^1.2.7",
30
+ "@contentful/field-editor-test-utils": "^1.3.0",
31
31
  "@testing-library/jest-dom": "^5.12.0",
32
32
  "@testing-library/react": "^11.2.6",
33
33
  "@testing-library/user-event": "^13.1.9"
@@ -35,5 +35,5 @@
35
35
  "peerDependencies": {
36
36
  "react": ">=16.8.0"
37
37
  },
38
- "gitHead": "4fff7b9534374dcc44cb477240d369fc34f46415"
38
+ "gitHead": "de7e74e3485dd69c240cfe9c545e6e50e41fb295"
39
39
  }