@contentful/field-editor-number 1.1.7-beta.0 → 1.1.7-beta.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.
@@ -56,7 +56,7 @@ var styles = {
56
56
  };
57
57
 
58
58
  function parseNumber(value, type) {
59
- if (!value || Number.isNaN(+value)) {
59
+ if (Number.isNaN(+value)) {
60
60
  return;
61
61
  }
62
62
 
@@ -173,9 +173,9 @@ function InnerNumberEditor(_ref) {
173
173
 
174
174
  setInputValue(value);
175
175
  var parsedNumber = parseNumber(value, field.type);
176
- field.setInvalid(!parsedNumber);
176
+ field.setInvalid(parsedNumber === undefined);
177
177
 
178
- if (parsedNumber) {
178
+ if (parsedNumber !== undefined) {
179
179
  updateExternalValue(parsedNumber);
180
180
  }
181
181
  };
@@ -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 '&:active': {\n background: tokens.gray300,\n },\n }),\n input: css({\n paddingRight: tokens.spacingXl,\n }),\n};\n","export function parseNumber(value: string, type: string) {\n if (!value || 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);\n if (parsedNumber) {\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 step={NUMBER_STEP}\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","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","step","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 '&:active': {\n background: 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 step={NUMBER_STEP}\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","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","step","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},"&:active":{background:a.gray300}}),input:u.css({paddingRight:a.spacingXl})},s=/^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/,c=/^[+-]?([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 I=function(e){m!==e&&f(e)},y=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,step:1,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 I(void 0);if(function(e,t){return("Integer"===t?c:s).test(e)}(t,u.type)){b(t);var n=function(e,t){if(e&&!Number.isNaN(+e))return"Integer"===t?parseInt(e,10):parseFloat(e)}(t,u.type);u.setInvalid(!n),n&&I(n)}},onKeyDown:function(e){var n={ArrowUp:function(){return y(t.Increment)},ArrowDown:function(){return y(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 y(t.Increment)},onPointerDown:h},n.createElement(i.ArrowUpTrimmedIcon,{size:"medium"})),n.createElement("button",{tabIndex:-1,className:l.control,onClick:function(){return y(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,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},"&:active":{background:a.gray300}}),input:u.css({paddingRight:a.spacingXl})},s=/^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]*)?$/,c=/^[+-]?([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 I=function(e){m!==e&&f(e)},y=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,step:1,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 I(void 0);if(function(e,t){return("Integer"===t?c:s).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&&I(n)}},onKeyDown:function(e){var n={ArrowUp:function(){return y(t.Increment)},ArrowDown:function(){return y(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 y(t.Increment)},onPointerDown:h},n.createElement(i.ArrowUpTrimmedIcon,{size:"medium"})),n.createElement("button",{tabIndex:-1,className:l.control,onClick:function(){return y(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;
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);\n if (parsedNumber) {\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 step={NUMBER_STEP}\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 '&:active': {\n background: tokens.gray300,\n },\n }),\n input: css({\n paddingRight: tokens.spacingXl,\n }),\n};\n","export function parseNumber(value: string, type: string) {\n if (!value || 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","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","step","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.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 step={NUMBER_STEP}\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 '&:active': {\n background: 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","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","step","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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"}
@@ -50,7 +50,7 @@ var styles = {
50
50
  };
51
51
 
52
52
  function parseNumber(value, type) {
53
- if (!value || Number.isNaN(+value)) {
53
+ if (Number.isNaN(+value)) {
54
54
  return;
55
55
  }
56
56
 
@@ -167,9 +167,9 @@ function InnerNumberEditor(_ref) {
167
167
 
168
168
  setInputValue(value);
169
169
  var parsedNumber = parseNumber(value, field.type);
170
- field.setInvalid(!parsedNumber);
170
+ field.setInvalid(parsedNumber === undefined);
171
171
 
172
- if (parsedNumber) {
172
+ if (parsedNumber !== undefined) {
173
173
  updateExternalValue(parsedNumber);
174
174
  }
175
175
  };
@@ -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 '&:active': {\n background: tokens.gray300,\n },\n }),\n input: css({\n paddingRight: tokens.spacingXl,\n }),\n};\n","export function parseNumber(value: string, type: string) {\n if (!value || 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);\n if (parsedNumber) {\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 step={NUMBER_STEP}\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","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","step","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 '&:active': {\n background: 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 step={NUMBER_STEP}\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","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","step","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.1.7-beta.0",
3
+ "version": "1.1.7-beta.1",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/field-editor-number.esm.js",
6
6
  "typings": "dist/index.d.ts",