@servicetitan/form 41.1.0 → 41.2.0
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/dist/color-picker/color-picker.d.ts +1 -1
- package/dist/color-picker/color-picker.d.ts.map +1 -1
- package/dist/color-picker/color-picker.js.map +1 -1
- package/dist/date-range-picker/date-range-picker.d.ts +4 -3
- package/dist/date-range-picker/date-range-picker.d.ts.map +1 -1
- package/dist/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/demo/color-picker.d.ts +1 -1
- package/dist/demo/color-picker.d.ts.map +1 -1
- package/dist/demo/color-picker.js.map +1 -1
- package/dist/demo/date-range-picker.d.ts +1 -1
- package/dist/demo/date-range-picker.d.ts.map +1 -1
- package/dist/demo/date-range-picker.js.map +1 -1
- package/dist/demo/file-uploader.d.ts +1 -1
- package/dist/demo/file-uploader.d.ts.map +1 -1
- package/dist/demo/file-uploader.js.map +1 -1
- package/dist/demo/input-date-mask.d.ts +1 -1
- package/dist/demo/input-date-mask.d.ts.map +1 -1
- package/dist/demo/input-date-mask.js.map +1 -1
- package/dist/demo/number-input.d.ts +1 -1
- package/dist/demo/number-input.d.ts.map +1 -1
- package/dist/demo/number-input.js.map +1 -1
- package/dist/demo/original-number-input.d.ts +1 -1
- package/dist/demo/original-number-input.d.ts.map +1 -1
- package/dist/demo/original-number-input.js.map +1 -1
- package/dist/demo/phone-number-input-a2.d.ts +1 -1
- package/dist/demo/phone-number-input-a2.d.ts.map +1 -1
- package/dist/demo/phone-number-input-a2.js.map +1 -1
- package/dist/demo/phone-number-input.d.ts +1 -1
- package/dist/demo/phone-number-input.d.ts.map +1 -1
- package/dist/demo/phone-number-input.js.map +1 -1
- package/dist/file-uploader/config.d.ts +1 -1
- package/dist/file-uploader/config.d.ts.map +1 -1
- package/dist/file-uploader/config.js.map +1 -1
- package/dist/file-uploader/file-uploader.d.ts.map +1 -1
- package/dist/file-uploader/file-uploader.js.map +1 -1
- package/dist/form-state-error-banner/form-state-error-banner.d.ts +1 -1
- package/dist/form-state-error-banner/form-state-error-banner.d.ts.map +1 -1
- package/dist/form-state-error-banner/form-state-error-banner.js.map +1 -1
- package/dist/input-date-mask/input-date-mask.d.ts +2 -2
- package/dist/input-date-mask/input-date-mask.d.ts.map +1 -1
- package/dist/input-date-mask/input-date-mask.js.map +1 -1
- package/dist/label/label.d.ts +1 -1
- package/dist/label/label.d.ts.map +1 -1
- package/dist/label/label.js.map +1 -1
- package/dist/masked-input.d.ts +3 -3
- package/dist/masked-input.d.ts.map +1 -1
- package/dist/masked-input.js.map +1 -1
- package/dist/number-input/get-formatted-string.d.ts +1 -1
- package/dist/number-input/get-formatted-string.d.ts.map +1 -1
- package/dist/number-input/get-formatted-string.js.map +1 -1
- package/dist/number-input/number-input.d.ts +3 -3
- package/dist/number-input/number-input.d.ts.map +1 -1
- package/dist/number-input/number-input.js.map +1 -1
- package/dist/number-input/process-value.d.ts +2 -2
- package/dist/number-input/process-value.d.ts.map +1 -1
- package/dist/number-input/process-value.js.map +1 -1
- package/dist/original-number-input/ordinal-number-input.d.ts +1 -1
- package/dist/original-number-input/ordinal-number-input.d.ts.map +1 -1
- package/dist/original-number-input/ordinal-number-input.js.map +1 -1
- package/dist/phone-number-input/phone-number-input-a2.d.ts +3 -3
- package/dist/phone-number-input/phone-number-input-a2.d.ts.map +1 -1
- package/dist/phone-number-input/phone-number-input-a2.js.map +1 -1
- package/dist/phone-number-input/phone-number-input.d.ts +1 -1
- package/dist/phone-number-input/phone-number-input.d.ts.map +1 -1
- package/dist/phone-number-input/phone-number-input.js.map +1 -1
- package/package.json +9 -9
- package/src/color-picker/color-picker.tsx +2 -1
- package/src/date-range-picker/date-range-picker.tsx +5 -4
- package/src/demo/color-picker.tsx +4 -2
- package/src/demo/date-range-picker.tsx +3 -2
- package/src/demo/file-uploader.tsx +4 -2
- package/src/demo/input-date-mask.tsx +2 -1
- package/src/demo/number-input.tsx +2 -1
- package/src/demo/original-number-input.tsx +2 -1
- package/src/demo/phone-number-input-a2.tsx +3 -2
- package/src/demo/phone-number-input.tsx +1 -1
- package/src/file-uploader/__tests__/uploader.test.ts +1 -1
- package/src/file-uploader/config.tsx +1 -1
- package/src/file-uploader/file-uploader.tsx +2 -1
- package/src/form-state-error-banner/form-state-error-banner.tsx +1 -1
- package/src/input-date-mask/input-date-mask.tsx +4 -2
- package/src/label/label.tsx +1 -1
- package/src/masked-input.tsx +5 -3
- package/src/number-input/__tests__/get-formatted-string.test.ts +1 -1
- package/src/number-input/__tests__/process-value.test.ts +1 -1
- package/src/number-input/get-formatted-string.ts +1 -1
- package/src/number-input/number-input.tsx +7 -12
- package/src/number-input/process-value.ts +2 -2
- package/src/original-number-input/ordinal-number-input.tsx +4 -2
- package/src/phone-number-input/__tests__/phone-number-input-a2.test.tsx +1 -1
- package/src/phone-number-input/phone-number-input-a2.tsx +6 -3
- package/src/phone-number-input/phone-number-input.tsx +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-date-mask.d.ts","sourceRoot":"","sources":["../../src/input-date-mask/input-date-mask.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"input-date-mask.d.ts","sourceRoot":"","sources":["../../src/input-date-mask/input-date-mask.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAoC,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAErF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAgB9D,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC;IAC9E,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAmInE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/input-date-mask/input-date-mask.tsx"],"sourcesContent":["import { FC, ChangeEvent,
|
|
1
|
+
{"version":3,"sources":["../../src/input-date-mask/input-date-mask.tsx"],"sourcesContent":["import type { FC, ChangeEvent, InputHTMLAttributes, PropsWithChildren } from 'react';\nimport { useEffect } from 'react';\nimport type { InputProps } from '@servicetitan/design-system';\nimport { Input } from '@servicetitan/design-system';\nimport { action } from 'mobx';\nimport { useLocalStore, observer } from 'mobx-react';\nimport moment from 'moment';\nimport InputMask from 'react-input-mask';\nimport classnames from 'classnames';\nimport * as Styles from './input-date-mask.module.css';\n\nconst KEY_DEL = 46;\n\ninterface InputDateMaskStore {\n maskValue: string;\n setMask(maskValue: string): void;\n}\n\nexport interface InputDateMaskProps extends Omit<InputProps, 'onChange' | 'value'> {\n value?: Date;\n ['qa-testing']?: string;\n maskChar?: string;\n alwaysShowMask?: boolean;\n dateFormat?: string;\n minDate?: Date;\n maxDate?: Date;\n onChange(value: Date | undefined): void;\n}\n\nexport const InputDateMask: FC<PropsWithChildren<InputDateMaskProps>> = observer(\n ({\n className,\n maskChar = 'X',\n alwaysShowMask,\n shortLabel,\n value,\n onChange,\n 'qa-testing': qaTestingLocator,\n error,\n disabled,\n placeholder,\n dateFormat = 'MM/DD/YYYY',\n minDate,\n maxDate,\n }: InputDateMaskProps) => {\n const state = useLocalStore(() => ({\n maskValue: '',\n setMask: action(function (this: InputDateMaskStore, mask: string) {\n this.maskValue = mask;\n }),\n }));\n\n const handleKeyDown = (evt: any) => {\n if (evt.keyCode === KEY_DEL) {\n onChange(undefined);\n\n state.setMask('');\n }\n };\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value;\n\n state.setMask(value);\n\n if (event.type === 'focus' || event.type === 'blur') {\n return;\n }\n\n if (isMaskValid(value)) {\n onChange(parseDate(value));\n } else {\n onChange(undefined);\n }\n };\n\n useEffect(() => {\n if (value === undefined && isMaskValid(state.maskValue)) {\n state.setMask('');\n }\n }, [value]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const getMaskError = () => {\n return value === undefined && state.maskValue !== '' && isMaskInvalid(state.maskValue);\n };\n\n const getValueError = () => {\n return value !== undefined && !isDateInRange(value);\n };\n\n const formatDate = (date?: Date) => {\n return date ? moment(date).format(dateFormat) : '';\n };\n\n const parseDate = (date: string) => {\n return moment(date, dateFormat).toDate();\n };\n\n const isMaskValid = (mask: string) => {\n return !mask.includes(maskChar) && isDateStringValid(mask);\n };\n\n const isMaskInvalid = (mask: string) => {\n return !mask.includes(maskChar) && !isDateStringValid(mask);\n };\n\n const isDateStringValid = (date: string) => {\n return moment(date, dateFormat).isValid() && isDateInRange(parseDate(date));\n };\n\n const isDateInRange = (date: Date) => {\n if (minDate && maxDate) {\n return date >= minDate && date <= maxDate;\n } else if (minDate) {\n return date >= minDate;\n } else if (maxDate) {\n return date <= maxDate;\n }\n\n return true;\n };\n\n const mask = dateFormat.replace(/[MDY]/g, '9');\n\n const realError = error || getMaskError() || getValueError();\n\n const realPlaceholder = placeholder || mask.replace(/9/g, maskChar);\n\n const classes = classnames(className, qaTestingLocator, Styles.input, {\n [Styles.error]: realError,\n });\n\n const renderFunction = ({ size, ...props }: InputHTMLAttributes<HTMLInputElement>) => (\n <div>\n <Input\n {...props}\n shortLabel={shortLabel}\n className={classes}\n small\n fluid\n error={realError}\n disabled={disabled}\n placeholder={realPlaceholder}\n />\n </div>\n );\n\n return (\n <InputMask\n mask={mask}\n maskChar={maskChar}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n alwaysShowMask={alwaysShowMask}\n value={formatDate(value) || state.maskValue}\n >\n {renderFunction as any}\n </InputMask>\n );\n }\n);\n"],"names":["useEffect","Input","action","useLocalStore","observer","moment","InputMask","classnames","Styles","KEY_DEL","InputDateMask","className","maskChar","alwaysShowMask","shortLabel","value","onChange","qaTestingLocator","error","disabled","placeholder","dateFormat","minDate","maxDate","state","maskValue","setMask","mask","handleKeyDown","evt","keyCode","undefined","handleChange","event","target","type","isMaskValid","parseDate","getMaskError","isMaskInvalid","getValueError","isDateInRange","formatDate","date","format","toDate","includes","isDateStringValid","isValid","replace","realError","realPlaceholder","classes","input","renderFunction","size","props","div","small","fluid","onKeyDown"],"mappings":"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"}
|
package/dist/label/label.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../src/label/label.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../src/label/label.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAKhC,KAAK,SAAS,GACR,KAAK,GACL,GAAG,GACH,OAAO,GACP,GAAG,GACH,QAAQ,GACR,GAAG,GACH,MAAM,GACN,GAAG,GACH,SAAS,GACT,IAAI,GACJ,UAAU,GACV,IAAI,GACJ,YAAY,GACZ,IAAI,GACJ,aAAa,GACb,IAAI,CAAC;AAEX,UAAU,UAAU;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC,UAAU,CAwBhC,CAAC"}
|
package/dist/label/label.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/label/label.tsx"],"sourcesContent":["import classNames from 'classnames';\nimport { FC } from 'react';\nimport { Stack, Icon, Text, Tooltip } from '@servicetitan/design-system';\n\nimport * as Styles from './label.module.css';\n\ntype Direction =\n | 'top'\n | 't'\n | 'right'\n | 'r'\n | 'bottom'\n | 'b'\n | 'left'\n | 'l'\n | 'topleft'\n | 'tl'\n | 'topright'\n | 'tr'\n | 'bottomleft'\n | 'bl'\n | 'bottomright'\n | 'br';\n\ninterface LabelProps {\n label: string;\n tooltip?: string;\n tooltipDirection?: Direction;\n hasError?: boolean;\n error?: string;\n}\n\nexport const Label: FC<LabelProps> = ({\n label,\n tooltip,\n tooltipDirection = 'r',\n hasError,\n error,\n}) => (\n <div className={classNames(Styles.label, hasError && Styles.hasError)}>\n <Stack className={Styles.text}>\n <Stack.Item>{label}</Stack.Item>\n {tooltip && (\n <Stack.Item className={Styles.tooltip}>\n <Tooltip direction={tooltipDirection} text={tooltip}>\n <Icon name=\"info\" />\n </Tooltip>\n </Stack.Item>\n )}\n </Stack>\n {hasError && (\n <Text className={Styles.error} size={1}>\n {error}\n </Text>\n )}\n </div>\n);\n"],"names":["classNames","Stack","Icon","Text","Tooltip","Styles","Label","label","tooltip","tooltipDirection","hasError","error","div","className","text","Item","direction","name","size"],"mappings":";AAAA,OAAOA,gBAAgB,aAAa;AAEpC,SAASC,KAAK,EAAEC,IAAI,EAAEC,IAAI,EAAEC,OAAO,QAAQ,8BAA8B;AAEzE,YAAYC,YAAY,qBAAqB;AA4B7C,OAAO,MAAMC,QAAwB,CAAC,EAClCC,KAAK,EACLC,OAAO,EACPC,mBAAmB,GAAG,EACtBC,QAAQ,EACRC,KAAK,EACR,iBACG,MAACC;QAAIC,WAAWb,WAAWK,OAAOE,KAAK,EAAEG,YAAYL,OAAOK,QAAQ;;0BAChE,MAACT;gBAAMY,WAAWR,OAAOS,IAAI;;kCACzB,KAACb,MAAMc,IAAI;kCAAER;;oBACZC,yBACG,KAACP,MAAMc,IAAI;wBAACF,WAAWR,OAAOG,OAAO;kCACjC,cAAA,KAACJ;4BAAQY,WAAWP;4BAAkBK,MAAMN;sCACxC,cAAA,KAACN;gCAAKe,MAAK;;;;;;YAK1BP,0BACG,KAACP;gBAAKU,WAAWR,OAAOM,KAAK;gBAAEO,MAAM;0BAChCP;;;OAIf"}
|
|
1
|
+
{"version":3,"sources":["../../src/label/label.tsx"],"sourcesContent":["import classNames from 'classnames';\nimport type { FC } from 'react';\nimport { Stack, Icon, Text, Tooltip } from '@servicetitan/design-system';\n\nimport * as Styles from './label.module.css';\n\ntype Direction =\n | 'top'\n | 't'\n | 'right'\n | 'r'\n | 'bottom'\n | 'b'\n | 'left'\n | 'l'\n | 'topleft'\n | 'tl'\n | 'topright'\n | 'tr'\n | 'bottomleft'\n | 'bl'\n | 'bottomright'\n | 'br';\n\ninterface LabelProps {\n label: string;\n tooltip?: string;\n tooltipDirection?: Direction;\n hasError?: boolean;\n error?: string;\n}\n\nexport const Label: FC<LabelProps> = ({\n label,\n tooltip,\n tooltipDirection = 'r',\n hasError,\n error,\n}) => (\n <div className={classNames(Styles.label, hasError && Styles.hasError)}>\n <Stack className={Styles.text}>\n <Stack.Item>{label}</Stack.Item>\n {tooltip && (\n <Stack.Item className={Styles.tooltip}>\n <Tooltip direction={tooltipDirection} text={tooltip}>\n <Icon name=\"info\" />\n </Tooltip>\n </Stack.Item>\n )}\n </Stack>\n {hasError && (\n <Text className={Styles.error} size={1}>\n {error}\n </Text>\n )}\n </div>\n);\n"],"names":["classNames","Stack","Icon","Text","Tooltip","Styles","Label","label","tooltip","tooltipDirection","hasError","error","div","className","text","Item","direction","name","size"],"mappings":";AAAA,OAAOA,gBAAgB,aAAa;AAEpC,SAASC,KAAK,EAAEC,IAAI,EAAEC,IAAI,EAAEC,OAAO,QAAQ,8BAA8B;AAEzE,YAAYC,YAAY,qBAAqB;AA4B7C,OAAO,MAAMC,QAAwB,CAAC,EAClCC,KAAK,EACLC,OAAO,EACPC,mBAAmB,GAAG,EACtBC,QAAQ,EACRC,KAAK,EACR,iBACG,MAACC;QAAIC,WAAWb,WAAWK,OAAOE,KAAK,EAAEG,YAAYL,OAAOK,QAAQ;;0BAChE,MAACT;gBAAMY,WAAWR,OAAOS,IAAI;;kCACzB,KAACb,MAAMc,IAAI;kCAAER;;oBACZC,yBACG,KAACP,MAAMc,IAAI;wBAACF,WAAWR,OAAOG,OAAO;kCACjC,cAAA,KAACJ;4BAAQY,WAAWP;4BAAkBK,MAAMN;sCACxC,cAAA,KAACN;gCAAKe,MAAK;;;;;;YAK1BP,0BACG,KAACP;gBAAKU,WAAWR,OAAOM,KAAK;gBAAEO,MAAM;0BAChCP;;;OAIf"}
|
package/dist/masked-input.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FC, InputHTMLAttributes } from 'react';
|
|
2
|
-
import { Props as ReactMaskedInputProps } from 'react-input-mask';
|
|
3
|
-
import { FormInputProps } from '@servicetitan/design-system';
|
|
1
|
+
import type { FC, InputHTMLAttributes } from 'react';
|
|
2
|
+
import type { Props as ReactMaskedInputProps } from 'react-input-mask';
|
|
3
|
+
import type { FormInputProps } from '@servicetitan/design-system';
|
|
4
4
|
type MaskedInputProps = FormInputProps & Omit<ReactMaskedInputProps, keyof InputHTMLAttributes<HTMLInputElement>>;
|
|
5
5
|
export declare const MaskedInput: FC<MaskedInputProps>;
|
|
6
6
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"masked-input.d.ts","sourceRoot":"","sources":["../src/masked-input.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,mBAAmB,EAAe,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"masked-input.d.ts","sourceRoot":"","sources":["../src/masked-input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,mBAAmB,EAAe,MAAM,OAAO,CAAC;AAElE,OAAO,KAAK,EAAE,KAAK,IAAI,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,KAAK,gBAAgB,GAAG,cAAc,GAClC,IAAI,CAAC,qBAAqB,EAAE,MAAM,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAE7E,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CA+B5C,CAAC"}
|
package/dist/masked-input.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/masked-input.tsx"],"sourcesContent":["import { FC, InputHTMLAttributes, ChangeEvent } from 'react';\r\n\r\nimport
|
|
1
|
+
{"version":3,"sources":["../src/masked-input.tsx"],"sourcesContent":["import type { FC, InputHTMLAttributes, ChangeEvent } from 'react';\r\n\r\nimport type { Props as ReactMaskedInputProps } from 'react-input-mask';\r\nimport ReactInputMask from 'react-input-mask';\r\nimport type { FormInputProps } from '@servicetitan/design-system';\r\nimport { Form } from '@servicetitan/design-system';\r\n\r\ntype MaskedInputProps = FormInputProps &\r\n Omit<ReactMaskedInputProps, keyof InputHTMLAttributes<HTMLInputElement>>;\r\n\r\nexport const MaskedInput: FC<MaskedInputProps> = ({\r\n mask,\r\n maskChar,\r\n value,\r\n onChange,\r\n placeholder,\r\n disabled,\r\n formatChars,\r\n ...props\r\n}) => {\r\n const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {\r\n onChange(e.target.value);\r\n };\r\n\r\n const renderFunction = (innerProps: InputHTMLAttributes<HTMLInputElement>) => (\r\n <Form.Input {...props} {...innerProps} />\r\n );\r\n\r\n return (\r\n <ReactInputMask\r\n mask={mask}\r\n maskChar={maskChar}\r\n value={value}\r\n onChange={handleInputChange}\r\n placeholder={placeholder}\r\n disabled={disabled}\r\n formatChars={formatChars}\r\n >\r\n {renderFunction as any}\r\n </ReactInputMask>\r\n );\r\n};\r\n"],"names":["ReactInputMask","Form","MaskedInput","mask","maskChar","value","onChange","placeholder","disabled","formatChars","props","handleInputChange","e","target","renderFunction","innerProps","Input"],"mappings":";AAGA,OAAOA,oBAAoB,mBAAmB;AAE9C,SAASC,IAAI,QAAQ,8BAA8B;AAKnD,OAAO,MAAMC,cAAoC,CAAC,EAC9CC,IAAI,EACJC,QAAQ,EACRC,KAAK,EACLC,QAAQ,EACRC,WAAW,EACXC,QAAQ,EACRC,WAAW,EACX,GAAGC,OACN;IACG,MAAMC,oBAAoB,CAACC;QACvBN,SAASM,EAAEC,MAAM,CAACR,KAAK;IAC3B;IAEA,MAAMS,iBAAiB,CAACC,2BACpB,KAACd,KAAKe,KAAK;YAAE,GAAGN,KAAK;YAAG,GAAGK,UAAU;;IAGzC,qBACI,KAACf;QACGG,MAAMA;QACNC,UAAUA;QACVC,OAAOA;QACPC,UAAUK;QACVJ,aAAaA;QACbC,UAAUA;QACVC,aAAaA;kBAEZK;;AAGb,EAAE"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EmptyValue, NumberValue, Separators } from './common-interfaces';
|
|
1
|
+
import type { EmptyValue, NumberValue, Separators } from './common-interfaces';
|
|
2
2
|
export type FormatNumber = (value: number, precision?: number, thousand?: string, decimal?: string) => string;
|
|
3
3
|
interface GetFormattedStringOptions<TEmpty extends EmptyValue> {
|
|
4
4
|
emptyValue: TEmpty;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-formatted-string.d.ts","sourceRoot":"","sources":["../../src/number-input/get-formatted-string.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"get-formatted-string.d.ts","sourceRoot":"","sources":["../../src/number-input/get-formatted-string.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE/E,MAAM,MAAM,YAAY,GAAG,CACvB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,KACf,MAAM,CAAC;AAEZ,UAAU,yBAAyB,CAAC,MAAM,SAAS,UAAU;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,MAAM,SAAS,UAAU,EACxD,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAC1B,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,yBAAyB,CAAC,MAAM,CAAC,EACxE,YAAY,GAAE,YAAkC,UAUnD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/number-input/get-formatted-string.ts"],"sourcesContent":["import { formatNumber as formatNumberDefault } from 'accounting';\n\nimport { EmptyValue, NumberValue, Separators } from './common-interfaces';\n\nexport type FormatNumber = (\n value: number,\n precision?: number,\n thousand?: string,\n decimal?: string\n) => string;\n\ninterface GetFormattedStringOptions<TEmpty extends EmptyValue> {\n emptyValue: TEmpty;\n precision?: number;\n separators: Separators;\n}\n\nexport function getFormattedString<TEmpty extends EmptyValue>(\n value: NumberValue<TEmpty>,\n { emptyValue, precision, separators }: GetFormattedStringOptions<TEmpty>,\n formatNumber: FormatNumber = formatNumberDefault\n) {\n return typeof value === 'number' || emptyValue === 0\n ? formatNumber(\n (typeof value === 'number' ? value : emptyValue) as number,\n precision ?? 0,\n separators.thousand,\n separators.decimal\n )\n : '';\n}\n"],"names":["formatNumber","formatNumberDefault","getFormattedString","value","emptyValue","precision","separators","thousand","decimal"],"mappings":"AAAA,SAASA,gBAAgBC,mBAAmB,QAAQ,aAAa;AAiBjE,OAAO,SAASC,mBACZC,KAA0B,EAC1B,EAAEC,UAAU,EAAEC,SAAS,EAAEC,UAAU,EAAqC,EACxEN,eAA6BC,mBAAmB;IAEhD,OAAO,OAAOE,UAAU,YAAYC,eAAe,IAC7CJ,aACK,OAAOG,UAAU,WAAWA,QAAQC,YACrCC,sBAAAA,uBAAAA,YAAa,GACbC,WAAWC,QAAQ,EACnBD,WAAWE,OAAO,IAEtB;AACV"}
|
|
1
|
+
{"version":3,"sources":["../../src/number-input/get-formatted-string.ts"],"sourcesContent":["import { formatNumber as formatNumberDefault } from 'accounting';\n\nimport type { EmptyValue, NumberValue, Separators } from './common-interfaces';\n\nexport type FormatNumber = (\n value: number,\n precision?: number,\n thousand?: string,\n decimal?: string\n) => string;\n\ninterface GetFormattedStringOptions<TEmpty extends EmptyValue> {\n emptyValue: TEmpty;\n precision?: number;\n separators: Separators;\n}\n\nexport function getFormattedString<TEmpty extends EmptyValue>(\n value: NumberValue<TEmpty>,\n { emptyValue, precision, separators }: GetFormattedStringOptions<TEmpty>,\n formatNumber: FormatNumber = formatNumberDefault\n) {\n return typeof value === 'number' || emptyValue === 0\n ? formatNumber(\n (typeof value === 'number' ? value : emptyValue) as number,\n precision ?? 0,\n separators.thousand,\n separators.decimal\n )\n : '';\n}\n"],"names":["formatNumber","formatNumberDefault","getFormattedString","value","emptyValue","precision","separators","thousand","decimal"],"mappings":"AAAA,SAASA,gBAAgBC,mBAAmB,QAAQ,aAAa;AAiBjE,OAAO,SAASC,mBACZC,KAA0B,EAC1B,EAAEC,UAAU,EAAEC,SAAS,EAAEC,UAAU,EAAqC,EACxEN,eAA6BC,mBAAmB;IAEhD,OAAO,OAAOE,UAAU,YAAYC,eAAe,IAC7CJ,aACK,OAAOG,UAAU,WAAWA,QAAQC,YACrCC,sBAAAA,uBAAAA,YAAa,GACbC,WAAWC,QAAQ,EACnBD,WAAWE,OAAO,IAEtB;AACV"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { InputProps } from '@servicetitan/design-system';
|
|
2
|
-
import { FormatNumber } from './get-formatted-string';
|
|
3
|
-
import { EmptyValue, NumberValue } from './common-interfaces';
|
|
1
|
+
import type { InputProps } from '@servicetitan/design-system';
|
|
2
|
+
import type { FormatNumber } from './get-formatted-string';
|
|
3
|
+
import type { EmptyValue, NumberValue } from './common-interfaces';
|
|
4
4
|
export interface NumberInputProps<TEmpty extends EmptyValue> extends Omit<InputProps, 'value' | 'onChange'> {
|
|
5
5
|
value: NumberValue<TEmpty>;
|
|
6
6
|
emptyValue: TEmpty;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-input.d.ts","sourceRoot":"","sources":["../../src/number-input/number-input.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"number-input.d.ts","sourceRoot":"","sources":["../../src/number-input/number-input.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,6BAA6B,CAAC;AAKjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASnE,MAAM,WAAW,gBAAgB,CAAC,MAAM,SAAS,UAAU,CAAE,SAAQ,IAAI,CACrE,UAAU,EACV,OAAO,GAAG,UAAU,CACvB;IACG,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;CAC9C;AAED,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,UAAU,EAAE,sJAapD,gBAAgB,CAAC,MAAM,CAAC,4CAuL1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/number-input/number-input.tsx"],"sourcesContent":["import {\n useCallback,\n useState,\n useEffect,\n useRef,\n SyntheticEvent,\n KeyboardEvent,\n FocusEvent,\n} from 'react';\n\nimport { useOptionalDependencies } from '@servicetitan/react-ioc';\n\nimport { Input, InputProps, InputOnChangeData } from '@servicetitan/design-system';\nimport { CULTURE_TOKEN } from '@servicetitan/culture';\n\nimport { processValue } from './process-value';\nimport { FormatNumber, getFormattedString } from './get-formatted-string';\nimport { EmptyValue, NumberValue } from './common-interfaces';\nimport { formatNumber as formatNumberDefault } from 'accounting';\n\nimport debounce from 'debounce';\n\nconst ARROW_UP_KEY = 38;\nconst ARROW_DOWN_KEY = 40;\nconst DEBOUNCE_WAIT = 300;\n\nexport interface NumberInputProps<TEmpty extends EmptyValue> extends Omit<\n InputProps,\n 'value' | 'onChange'\n> {\n value: NumberValue<TEmpty>;\n emptyValue: TEmpty;\n decimalPlaces?: number;\n useEmptyThousandsSeparator?: boolean;\n min?: number;\n max?: number;\n useKeyboardNavigation?: boolean;\n formatNumber?: FormatNumber;\n onChange(value: NumberValue<TEmpty>): void;\n}\n\nexport const NumberInput = <TEmpty extends EmptyValue>({\n value,\n onChange,\n onFocus,\n onBlur,\n emptyValue,\n decimalPlaces,\n useEmptyThousandsSeparator,\n min,\n max,\n useKeyboardNavigation,\n formatNumber = formatNumberDefault,\n ...props\n}: NumberInputProps<TEmpty>) => {\n const [\n {\n NumberFormat: {\n NumberGroupSeparator: thousandsSeparator = ',',\n NumberDecimalSeparator: decimalSeparator = '.',\n } = {},\n } = {},\n ] = useOptionalDependencies(CULTURE_TOKEN);\n\n const getFormattedValue = useCallback(\n () =>\n getFormattedString(\n value,\n {\n emptyValue,\n precision: decimalPlaces,\n separators: {\n thousand: useEmptyThousandsSeparator ? '' : thousandsSeparator,\n decimal: decimalSeparator,\n },\n },\n formatNumber\n ),\n [\n decimalPlaces,\n decimalSeparator,\n emptyValue,\n thousandsSeparator,\n useEmptyThousandsSeparator,\n value,\n formatNumber,\n ]\n );\n\n const [isFocused, setIsFocused] = useState(false);\n const [state, setState] = useState({\n numberValue: value,\n stringValue: getFormattedValue(),\n });\n\n useEffect(() => {\n if (isFocused) {\n return;\n }\n\n setState({\n numberValue: value,\n stringValue: getFormattedValue(),\n });\n }, [value, getFormattedValue, isFocused]);\n\n const handleChange = (_0: SyntheticEvent<HTMLInputElement>, { value }: InputOnChangeData) => {\n updateValue(value);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.keyCode === ARROW_UP_KEY || event.keyCode === ARROW_DOWN_KEY) {\n const newValue = (state.numberValue ?? 0) + (event.keyCode === ARROW_UP_KEY ? 1 : -1);\n\n updateValue(String(newValue));\n event.preventDefault();\n }\n };\n\n /*\n ** \"updateImmediateValue\" updates the value immediately without clamping min/max,\n ** then \"updateClampedValueDebounced\" updates applying the min/max after debounce delay\n **\n ** Example: User can type \"100\" if min is \"5\" without the \"1\" immediately being clamped\n */\n const updateImmediateValue = (value: string, silent = false) => {\n const newState = processValue(\n value,\n {\n emptyValue,\n precision: decimalPlaces,\n separators: {\n thousand: thousandsSeparator,\n decimal: decimalSeparator,\n },\n },\n formatNumber\n );\n\n setState(newState);\n\n if (!silent) {\n onChange(newState.numberValue);\n }\n };\n\n const updateClampedValueDebounced = useRef<(value: string, silent: boolean) => void>();\n\n useEffect(() => {\n let isCurrent = true;\n\n const updateClampedValue = (value: string, silent = false) => {\n if (isCurrent) {\n const newState = processValue(\n value,\n {\n emptyValue,\n precision: decimalPlaces,\n separators: {\n thousand: thousandsSeparator,\n decimal: decimalSeparator,\n },\n range: { min, max },\n },\n formatNumber\n );\n\n setState(newState);\n\n if (!silent) {\n onChange(newState.numberValue);\n }\n }\n };\n\n updateClampedValueDebounced.current = debounce(updateClampedValue, DEBOUNCE_WAIT);\n\n return () => {\n isCurrent = false;\n };\n }, [\n emptyValue,\n decimalPlaces,\n thousandsSeparator,\n decimalSeparator,\n min,\n max,\n formatNumber,\n onChange,\n ]);\n\n const updateValue = (value: string, silent = false) => {\n updateImmediateValue(value, silent);\n updateClampedValueDebounced.current?.(value, silent);\n };\n\n const handleFocus = (event: FocusEvent<HTMLInputElement>) => {\n if (state.stringValue.length) {\n updateValue(\n // prepare the value which user does see (rounded), but without trailing zeroes after decimal and separator\n decimalPlaces\n ? state.stringValue.replace(new RegExp(`[${decimalSeparator}]?0+$`), '')\n : state.stringValue,\n true\n );\n }\n\n setIsFocused(true);\n\n if (onFocus) {\n onFocus(event);\n }\n };\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n setState({\n numberValue: value,\n stringValue: getFormattedValue(),\n });\n\n setIsFocused(false);\n\n if (onBlur) {\n onBlur(event);\n }\n };\n\n return (\n <Input\n {...props}\n value={state.stringValue}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={useKeyboardNavigation ? handleKeyDown : undefined}\n />\n );\n};\n"],"names":["useCallback","useState","useEffect","useRef","useOptionalDependencies","Input","CULTURE_TOKEN","processValue","getFormattedString","formatNumber","formatNumberDefault","debounce","ARROW_UP_KEY","ARROW_DOWN_KEY","DEBOUNCE_WAIT","NumberInput","value","onChange","onFocus","onBlur","emptyValue","decimalPlaces","useEmptyThousandsSeparator","min","max","useKeyboardNavigation","props","NumberFormat","NumberGroupSeparator","thousandsSeparator","NumberDecimalSeparator","decimalSeparator","getFormattedValue","precision","separators","thousand","decimal","isFocused","setIsFocused","state","setState","numberValue","stringValue","handleChange","_0","updateValue","handleKeyDown","event","keyCode","newValue","String","preventDefault","updateImmediateValue","silent","newState","updateClampedValueDebounced","isCurrent","updateClampedValue","range","current","handleFocus","length","replace","RegExp","handleBlur","onKeyDown","undefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/number-input/number-input.tsx"],"sourcesContent":["import type { SyntheticEvent, KeyboardEvent, FocusEvent } from 'react';\nimport { useCallback, useState, useEffect, useRef } from 'react';\n\nimport { useOptionalDependencies } from '@servicetitan/react-ioc';\n\nimport type { InputProps, InputOnChangeData } from '@servicetitan/design-system';\nimport { Input } from '@servicetitan/design-system';\nimport { CULTURE_TOKEN } from '@servicetitan/culture';\n\nimport { processValue } from './process-value';\nimport type { FormatNumber } from './get-formatted-string';\nimport { getFormattedString } from './get-formatted-string';\nimport type { EmptyValue, NumberValue } from './common-interfaces';\nimport { formatNumber as formatNumberDefault } from 'accounting';\n\nimport debounce from 'debounce';\n\nconst ARROW_UP_KEY = 38;\nconst ARROW_DOWN_KEY = 40;\nconst DEBOUNCE_WAIT = 300;\n\nexport interface NumberInputProps<TEmpty extends EmptyValue> extends Omit<\n InputProps,\n 'value' | 'onChange'\n> {\n value: NumberValue<TEmpty>;\n emptyValue: TEmpty;\n decimalPlaces?: number;\n useEmptyThousandsSeparator?: boolean;\n min?: number;\n max?: number;\n useKeyboardNavigation?: boolean;\n formatNumber?: FormatNumber;\n onChange(value: NumberValue<TEmpty>): void;\n}\n\nexport const NumberInput = <TEmpty extends EmptyValue>({\n value,\n onChange,\n onFocus,\n onBlur,\n emptyValue,\n decimalPlaces,\n useEmptyThousandsSeparator,\n min,\n max,\n useKeyboardNavigation,\n formatNumber = formatNumberDefault,\n ...props\n}: NumberInputProps<TEmpty>) => {\n const [\n {\n NumberFormat: {\n NumberGroupSeparator: thousandsSeparator = ',',\n NumberDecimalSeparator: decimalSeparator = '.',\n } = {},\n } = {},\n ] = useOptionalDependencies(CULTURE_TOKEN);\n\n const getFormattedValue = useCallback(\n () =>\n getFormattedString(\n value,\n {\n emptyValue,\n precision: decimalPlaces,\n separators: {\n thousand: useEmptyThousandsSeparator ? '' : thousandsSeparator,\n decimal: decimalSeparator,\n },\n },\n formatNumber\n ),\n [\n decimalPlaces,\n decimalSeparator,\n emptyValue,\n thousandsSeparator,\n useEmptyThousandsSeparator,\n value,\n formatNumber,\n ]\n );\n\n const [isFocused, setIsFocused] = useState(false);\n const [state, setState] = useState({\n numberValue: value,\n stringValue: getFormattedValue(),\n });\n\n useEffect(() => {\n if (isFocused) {\n return;\n }\n\n setState({\n numberValue: value,\n stringValue: getFormattedValue(),\n });\n }, [value, getFormattedValue, isFocused]);\n\n const handleChange = (_0: SyntheticEvent<HTMLInputElement>, { value }: InputOnChangeData) => {\n updateValue(value);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.keyCode === ARROW_UP_KEY || event.keyCode === ARROW_DOWN_KEY) {\n const newValue = (state.numberValue ?? 0) + (event.keyCode === ARROW_UP_KEY ? 1 : -1);\n\n updateValue(String(newValue));\n event.preventDefault();\n }\n };\n\n /*\n ** \"updateImmediateValue\" updates the value immediately without clamping min/max,\n ** then \"updateClampedValueDebounced\" updates applying the min/max after debounce delay\n **\n ** Example: User can type \"100\" if min is \"5\" without the \"1\" immediately being clamped\n */\n const updateImmediateValue = (value: string, silent = false) => {\n const newState = processValue(\n value,\n {\n emptyValue,\n precision: decimalPlaces,\n separators: {\n thousand: thousandsSeparator,\n decimal: decimalSeparator,\n },\n },\n formatNumber\n );\n\n setState(newState);\n\n if (!silent) {\n onChange(newState.numberValue);\n }\n };\n\n const updateClampedValueDebounced = useRef<(value: string, silent: boolean) => void>();\n\n useEffect(() => {\n let isCurrent = true;\n\n const updateClampedValue = (value: string, silent = false) => {\n if (isCurrent) {\n const newState = processValue(\n value,\n {\n emptyValue,\n precision: decimalPlaces,\n separators: {\n thousand: thousandsSeparator,\n decimal: decimalSeparator,\n },\n range: { min, max },\n },\n formatNumber\n );\n\n setState(newState);\n\n if (!silent) {\n onChange(newState.numberValue);\n }\n }\n };\n\n updateClampedValueDebounced.current = debounce(updateClampedValue, DEBOUNCE_WAIT);\n\n return () => {\n isCurrent = false;\n };\n }, [\n emptyValue,\n decimalPlaces,\n thousandsSeparator,\n decimalSeparator,\n min,\n max,\n formatNumber,\n onChange,\n ]);\n\n const updateValue = (value: string, silent = false) => {\n updateImmediateValue(value, silent);\n updateClampedValueDebounced.current?.(value, silent);\n };\n\n const handleFocus = (event: FocusEvent<HTMLInputElement>) => {\n if (state.stringValue.length) {\n updateValue(\n // prepare the value which user does see (rounded), but without trailing zeroes after decimal and separator\n decimalPlaces\n ? state.stringValue.replace(new RegExp(`[${decimalSeparator}]?0+$`), '')\n : state.stringValue,\n true\n );\n }\n\n setIsFocused(true);\n\n if (onFocus) {\n onFocus(event);\n }\n };\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n setState({\n numberValue: value,\n stringValue: getFormattedValue(),\n });\n\n setIsFocused(false);\n\n if (onBlur) {\n onBlur(event);\n }\n };\n\n return (\n <Input\n {...props}\n value={state.stringValue}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={useKeyboardNavigation ? handleKeyDown : undefined}\n />\n );\n};\n"],"names":["useCallback","useState","useEffect","useRef","useOptionalDependencies","Input","CULTURE_TOKEN","processValue","getFormattedString","formatNumber","formatNumberDefault","debounce","ARROW_UP_KEY","ARROW_DOWN_KEY","DEBOUNCE_WAIT","NumberInput","value","onChange","onFocus","onBlur","emptyValue","decimalPlaces","useEmptyThousandsSeparator","min","max","useKeyboardNavigation","props","NumberFormat","NumberGroupSeparator","thousandsSeparator","NumberDecimalSeparator","decimalSeparator","getFormattedValue","precision","separators","thousand","decimal","isFocused","setIsFocused","state","setState","numberValue","stringValue","handleChange","_0","updateValue","handleKeyDown","event","keyCode","newValue","String","preventDefault","updateImmediateValue","silent","newState","updateClampedValueDebounced","isCurrent","updateClampedValue","range","current","handleFocus","length","replace","RegExp","handleBlur","onKeyDown","undefined"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { EmptyValue, NumberValue, Range, Separators } from './common-interfaces';
|
|
2
|
-
import { FormatNumber } from './get-formatted-string';
|
|
1
|
+
import type { EmptyValue, NumberValue, Range, Separators } from './common-interfaces';
|
|
2
|
+
import type { FormatNumber } from './get-formatted-string';
|
|
3
3
|
interface ProcessValueOptions<TEmpty extends EmptyValue> {
|
|
4
4
|
emptyValue: TEmpty;
|
|
5
5
|
precision?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-value.d.ts","sourceRoot":"","sources":["../../src/number-input/process-value.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"process-value.d.ts","sourceRoot":"","sources":["../../src/number-input/process-value.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,UAAU,mBAAmB,CAAC,MAAM,SAAS,UAAU;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,MAAM,SAAS,UAAU,EAClD,KAAK,EAAE,MAAM,EACb,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,KAAU,EAAE,EAAE,mBAAmB,CAAC,MAAM,CAAC,EAC9E,YAAY,GAAE,YAAkC;iBAkBV,WAAW,CAAC,MAAM,CAAC;;EAsB5D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/number-input/process-value.ts"],"sourcesContent":["import { formatNumber as formatNumberDefault } from 'accounting';\n\nimport { EmptyValue, NumberValue, Range, Separators } from './common-interfaces';\nimport { FormatNumber } from './get-formatted-string';\n\ninterface ProcessValueOptions<TEmpty extends EmptyValue> {\n emptyValue: TEmpty;\n precision?: number;\n separators: Separators;\n range?: Range;\n}\n\nexport function processValue<TEmpty extends EmptyValue>(\n value: string,\n { emptyValue, precision, separators, range = {} }: ProcessValueOptions<TEmpty>,\n formatNumber: FormatNumber = formatNumberDefault\n) {\n let inputValue = cleanValue(value, separators);\n\n // Handle empty string\n if (inputValue === '' || inputValue === '-') {\n let clampedNumber = emptyValue as number | undefined;\n let clampedString = inputValue;\n if (clampedNumber === 0) {\n if (range.min && clampedNumber < range.min) {\n clampedNumber = range.min;\n clampedString = formatNumber(range.min, 0, '', separators.decimal);\n } else if (range.max && clampedNumber > range.max) {\n clampedNumber = range.max;\n clampedString = formatNumber(range.max, 0, '', separators.decimal);\n }\n }\n return {\n numberValue: clampedNumber as NumberValue<TEmpty>,\n stringValue: clampedString,\n };\n }\n\n // Trim decimal places\n inputValue = trimDecimalPlace(inputValue, separators.decimal, formatNumber, precision);\n\n // Parse string to number and clamp\n const inputNumberValue = parseFloat(inputValue);\n const numberValue = clamp(inputNumberValue, range);\n\n // if not out of bound, use inputValue to preserve punctuation, otherwise use numberValue\n const stringValue =\n numberValue === inputNumberValue\n ? inputValue\n : formatNumber(numberValue, 0, '', separators.decimal);\n\n return {\n stringValue,\n numberValue: numberValue as NumberValue<TEmpty>,\n };\n}\n\nfunction trimDecimalPlace(\n value: string,\n separator: string,\n formatNumber: FormatNumber,\n precision?: number\n) {\n const decimalPosition = value.indexOf(separator);\n if (decimalPosition >= 0) {\n if (precision) {\n const isNegative = value.startsWith('-');\n const splitValue = value.split(separator);\n const intPart = (isNegative ? '-' : '') + String(Math.abs(+splitValue[0]));\n let fracPart = splitValue[1];\n if (fracPart && fracPart.length > precision) {\n fracPart = fracPart.slice(0, precision);\n }\n return `${intPart}.${fracPart}`;\n }\n\n return value.substr(0, decimalPosition);\n }\n return String(+value);\n}\n\nfunction clamp(value: number, { min = -Infinity, max = Infinity }: Range) {\n return Math.max(Math.min(value, max), min);\n}\n\nfunction cleanValue(value: string, separators: Separators) {\n const thousandsSeparatorRegEx = new RegExp(`[${separators.thousand}]{1,}`, 'g');\n const decimalSeparatorRegEx = new RegExp(`[${separators.decimal}+]{1,}`, 'g');\n const excessiveMinusSignRegEx = /(?!^)-/g;\n const cleanedValue = value\n // Remove invalid characters\n .replace(/[^0-9.,-]/g, '')\n // Remove thousand separators\n .replace(thousandsSeparatorRegEx, '')\n // Remove excessive decimal separators\n .replace(decimalSeparatorRegEx, separators.decimal)\n // Remove excessive minus signs\n .replace(excessiveMinusSignRegEx, '');\n\n return cleanedValue;\n}\n"],"names":["formatNumber","formatNumberDefault","processValue","value","emptyValue","precision","separators","range","inputValue","cleanValue","clampedNumber","clampedString","min","decimal","max","numberValue","stringValue","trimDecimalPlace","inputNumberValue","parseFloat","clamp","separator","decimalPosition","indexOf","isNegative","startsWith","splitValue","split","intPart","String","Math","abs","fracPart","length","slice","substr","Infinity","thousandsSeparatorRegEx","RegExp","thousand","decimalSeparatorRegEx","excessiveMinusSignRegEx","cleanedValue","replace"],"mappings":"AAAA,SAASA,gBAAgBC,mBAAmB,QAAQ,aAAa;AAYjE,OAAO,SAASC,aACZC,KAAa,EACb,EAAEC,UAAU,EAAEC,SAAS,EAAEC,UAAU,EAAEC,QAAQ,CAAC,CAAC,EAA+B,EAC9EP,eAA6BC,mBAAmB;IAEhD,IAAIO,aAAaC,WAAWN,OAAOG;IAEnC,sBAAsB;IACtB,IAAIE,eAAe,MAAMA,eAAe,KAAK;QACzC,IAAIE,gBAAgBN;QACpB,IAAIO,gBAAgBH;QACpB,IAAIE,kBAAkB,GAAG;YACrB,IAAIH,MAAMK,GAAG,IAAIF,gBAAgBH,MAAMK,GAAG,EAAE;gBACxCF,gBAAgBH,MAAMK,GAAG;gBACzBD,gBAAgBX,aAAaO,MAAMK,GAAG,EAAE,GAAG,IAAIN,WAAWO,OAAO;YACrE,OAAO,IAAIN,MAAMO,GAAG,IAAIJ,gBAAgBH,MAAMO,GAAG,EAAE;gBAC/CJ,gBAAgBH,MAAMO,GAAG;gBACzBH,gBAAgBX,aAAaO,MAAMO,GAAG,EAAE,GAAG,IAAIR,WAAWO,OAAO;YACrE;QACJ;QACA,OAAO;YACHE,aAAaL;YACbM,aAAaL;QACjB;IACJ;IAEA,sBAAsB;IACtBH,aAAaS,iBAAiBT,YAAYF,WAAWO,OAAO,EAAEb,cAAcK;IAE5E,mCAAmC;IACnC,MAAMa,mBAAmBC,WAAWX;IACpC,MAAMO,cAAcK,MAAMF,kBAAkBX;IAE5C,yFAAyF;IACzF,MAAMS,cACFD,gBAAgBG,mBACVV,aACAR,aAAae,aAAa,GAAG,IAAIT,WAAWO,OAAO;IAE7D,OAAO;QACHG;QACAD,aAAaA;IACjB;AACJ;AAEA,SAASE,iBACLd,KAAa,EACbkB,SAAiB,EACjBrB,YAA0B,EAC1BK,SAAkB;IAElB,MAAMiB,kBAAkBnB,MAAMoB,OAAO,CAACF;IACtC,IAAIC,mBAAmB,GAAG;QACtB,IAAIjB,WAAW;YACX,MAAMmB,aAAarB,MAAMsB,UAAU,CAAC;YACpC,MAAMC,aAAavB,MAAMwB,KAAK,CAACN;YAC/B,MAAMO,UAAU,AAACJ,CAAAA,aAAa,MAAM,EAAC,IAAKK,OAAOC,KAAKC,GAAG,CAAC,CAACL,UAAU,CAAC,EAAE;YACxE,IAAIM,WAAWN,UAAU,CAAC,EAAE;YAC5B,IAAIM,YAAYA,SAASC,MAAM,GAAG5B,WAAW;gBACzC2B,WAAWA,SAASE,KAAK,CAAC,GAAG7B;YACjC;YACA,OAAO,GAAGuB,QAAQ,CAAC,EAAEI,UAAU;QACnC;QAEA,OAAO7B,MAAMgC,MAAM,CAAC,GAAGb;IAC3B;IACA,OAAOO,OAAO,CAAC1B;AACnB;AAEA,SAASiB,MAAMjB,KAAa,EAAE,EAAES,MAAM,CAACwB,QAAQ,EAAEtB,MAAMsB,QAAQ,EAAS;IACpE,OAAON,KAAKhB,GAAG,CAACgB,KAAKlB,GAAG,CAACT,OAAOW,MAAMF;AAC1C;AAEA,SAASH,WAAWN,KAAa,EAAEG,UAAsB;IACrD,MAAM+B,0BAA0B,IAAIC,OAAO,CAAC,CAAC,EAAEhC,WAAWiC,QAAQ,CAAC,KAAK,CAAC,EAAE;IAC3E,MAAMC,wBAAwB,IAAIF,OAAO,CAAC,CAAC,EAAEhC,WAAWO,OAAO,CAAC,MAAM,CAAC,EAAE;IACzE,MAAM4B,0BAA0B;IAChC,MAAMC,eAAevC,KACjB,4BAA4B;KAC3BwC,OAAO,CAAC,cAAc,GACvB,6BAA6B;KAC5BA,OAAO,CAACN,yBAAyB,GAClC,sCAAsC;KACrCM,OAAO,CAACH,uBAAuBlC,WAAWO,OAAO,CAClD,+BAA+B;KAC9B8B,OAAO,CAACF,yBAAyB;IAEtC,OAAOC;AACX"}
|
|
1
|
+
{"version":3,"sources":["../../src/number-input/process-value.ts"],"sourcesContent":["import { formatNumber as formatNumberDefault } from 'accounting';\n\nimport type { EmptyValue, NumberValue, Range, Separators } from './common-interfaces';\nimport type { FormatNumber } from './get-formatted-string';\n\ninterface ProcessValueOptions<TEmpty extends EmptyValue> {\n emptyValue: TEmpty;\n precision?: number;\n separators: Separators;\n range?: Range;\n}\n\nexport function processValue<TEmpty extends EmptyValue>(\n value: string,\n { emptyValue, precision, separators, range = {} }: ProcessValueOptions<TEmpty>,\n formatNumber: FormatNumber = formatNumberDefault\n) {\n let inputValue = cleanValue(value, separators);\n\n // Handle empty string\n if (inputValue === '' || inputValue === '-') {\n let clampedNumber = emptyValue as number | undefined;\n let clampedString = inputValue;\n if (clampedNumber === 0) {\n if (range.min && clampedNumber < range.min) {\n clampedNumber = range.min;\n clampedString = formatNumber(range.min, 0, '', separators.decimal);\n } else if (range.max && clampedNumber > range.max) {\n clampedNumber = range.max;\n clampedString = formatNumber(range.max, 0, '', separators.decimal);\n }\n }\n return {\n numberValue: clampedNumber as NumberValue<TEmpty>,\n stringValue: clampedString,\n };\n }\n\n // Trim decimal places\n inputValue = trimDecimalPlace(inputValue, separators.decimal, formatNumber, precision);\n\n // Parse string to number and clamp\n const inputNumberValue = parseFloat(inputValue);\n const numberValue = clamp(inputNumberValue, range);\n\n // if not out of bound, use inputValue to preserve punctuation, otherwise use numberValue\n const stringValue =\n numberValue === inputNumberValue\n ? inputValue\n : formatNumber(numberValue, 0, '', separators.decimal);\n\n return {\n stringValue,\n numberValue: numberValue as NumberValue<TEmpty>,\n };\n}\n\nfunction trimDecimalPlace(\n value: string,\n separator: string,\n formatNumber: FormatNumber,\n precision?: number\n) {\n const decimalPosition = value.indexOf(separator);\n if (decimalPosition >= 0) {\n if (precision) {\n const isNegative = value.startsWith('-');\n const splitValue = value.split(separator);\n const intPart = (isNegative ? '-' : '') + String(Math.abs(+splitValue[0]));\n let fracPart = splitValue[1];\n if (fracPart && fracPart.length > precision) {\n fracPart = fracPart.slice(0, precision);\n }\n return `${intPart}.${fracPart}`;\n }\n\n return value.substr(0, decimalPosition);\n }\n return String(+value);\n}\n\nfunction clamp(value: number, { min = -Infinity, max = Infinity }: Range) {\n return Math.max(Math.min(value, max), min);\n}\n\nfunction cleanValue(value: string, separators: Separators) {\n const thousandsSeparatorRegEx = new RegExp(`[${separators.thousand}]{1,}`, 'g');\n const decimalSeparatorRegEx = new RegExp(`[${separators.decimal}+]{1,}`, 'g');\n const excessiveMinusSignRegEx = /(?!^)-/g;\n const cleanedValue = value\n // Remove invalid characters\n .replace(/[^0-9.,-]/g, '')\n // Remove thousand separators\n .replace(thousandsSeparatorRegEx, '')\n // Remove excessive decimal separators\n .replace(decimalSeparatorRegEx, separators.decimal)\n // Remove excessive minus signs\n .replace(excessiveMinusSignRegEx, '');\n\n return cleanedValue;\n}\n"],"names":["formatNumber","formatNumberDefault","processValue","value","emptyValue","precision","separators","range","inputValue","cleanValue","clampedNumber","clampedString","min","decimal","max","numberValue","stringValue","trimDecimalPlace","inputNumberValue","parseFloat","clamp","separator","decimalPosition","indexOf","isNegative","startsWith","splitValue","split","intPart","String","Math","abs","fracPart","length","slice","substr","Infinity","thousandsSeparatorRegEx","RegExp","thousand","decimalSeparatorRegEx","excessiveMinusSignRegEx","cleanedValue","replace"],"mappings":"AAAA,SAASA,gBAAgBC,mBAAmB,QAAQ,aAAa;AAYjE,OAAO,SAASC,aACZC,KAAa,EACb,EAAEC,UAAU,EAAEC,SAAS,EAAEC,UAAU,EAAEC,QAAQ,CAAC,CAAC,EAA+B,EAC9EP,eAA6BC,mBAAmB;IAEhD,IAAIO,aAAaC,WAAWN,OAAOG;IAEnC,sBAAsB;IACtB,IAAIE,eAAe,MAAMA,eAAe,KAAK;QACzC,IAAIE,gBAAgBN;QACpB,IAAIO,gBAAgBH;QACpB,IAAIE,kBAAkB,GAAG;YACrB,IAAIH,MAAMK,GAAG,IAAIF,gBAAgBH,MAAMK,GAAG,EAAE;gBACxCF,gBAAgBH,MAAMK,GAAG;gBACzBD,gBAAgBX,aAAaO,MAAMK,GAAG,EAAE,GAAG,IAAIN,WAAWO,OAAO;YACrE,OAAO,IAAIN,MAAMO,GAAG,IAAIJ,gBAAgBH,MAAMO,GAAG,EAAE;gBAC/CJ,gBAAgBH,MAAMO,GAAG;gBACzBH,gBAAgBX,aAAaO,MAAMO,GAAG,EAAE,GAAG,IAAIR,WAAWO,OAAO;YACrE;QACJ;QACA,OAAO;YACHE,aAAaL;YACbM,aAAaL;QACjB;IACJ;IAEA,sBAAsB;IACtBH,aAAaS,iBAAiBT,YAAYF,WAAWO,OAAO,EAAEb,cAAcK;IAE5E,mCAAmC;IACnC,MAAMa,mBAAmBC,WAAWX;IACpC,MAAMO,cAAcK,MAAMF,kBAAkBX;IAE5C,yFAAyF;IACzF,MAAMS,cACFD,gBAAgBG,mBACVV,aACAR,aAAae,aAAa,GAAG,IAAIT,WAAWO,OAAO;IAE7D,OAAO;QACHG;QACAD,aAAaA;IACjB;AACJ;AAEA,SAASE,iBACLd,KAAa,EACbkB,SAAiB,EACjBrB,YAA0B,EAC1BK,SAAkB;IAElB,MAAMiB,kBAAkBnB,MAAMoB,OAAO,CAACF;IACtC,IAAIC,mBAAmB,GAAG;QACtB,IAAIjB,WAAW;YACX,MAAMmB,aAAarB,MAAMsB,UAAU,CAAC;YACpC,MAAMC,aAAavB,MAAMwB,KAAK,CAACN;YAC/B,MAAMO,UAAU,AAACJ,CAAAA,aAAa,MAAM,EAAC,IAAKK,OAAOC,KAAKC,GAAG,CAAC,CAACL,UAAU,CAAC,EAAE;YACxE,IAAIM,WAAWN,UAAU,CAAC,EAAE;YAC5B,IAAIM,YAAYA,SAASC,MAAM,GAAG5B,WAAW;gBACzC2B,WAAWA,SAASE,KAAK,CAAC,GAAG7B;YACjC;YACA,OAAO,GAAGuB,QAAQ,CAAC,EAAEI,UAAU;QACnC;QAEA,OAAO7B,MAAMgC,MAAM,CAAC,GAAGb;IAC3B;IACA,OAAOO,OAAO,CAAC1B;AACnB;AAEA,SAASiB,MAAMjB,KAAa,EAAE,EAAES,MAAM,CAACwB,QAAQ,EAAEtB,MAAMsB,QAAQ,EAAS;IACpE,OAAON,KAAKhB,GAAG,CAACgB,KAAKlB,GAAG,CAACT,OAAOW,MAAMF;AAC1C;AAEA,SAASH,WAAWN,KAAa,EAAEG,UAAsB;IACrD,MAAM+B,0BAA0B,IAAIC,OAAO,CAAC,CAAC,EAAEhC,WAAWiC,QAAQ,CAAC,KAAK,CAAC,EAAE;IAC3E,MAAMC,wBAAwB,IAAIF,OAAO,CAAC,CAAC,EAAEhC,WAAWO,OAAO,CAAC,MAAM,CAAC,EAAE;IACzE,MAAM4B,0BAA0B;IAChC,MAAMC,eAAevC,KACjB,4BAA4B;KAC3BwC,OAAO,CAAC,cAAc,GACvB,6BAA6B;KAC5BA,OAAO,CAACN,yBAAyB,GAClC,sCAAsC;KACrCM,OAAO,CAACH,uBAAuBlC,WAAWO,OAAO,CAClD,+BAA+B;KAC9B8B,OAAO,CAACF,yBAAyB;IAEtC,OAAOC;AACX"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ordinal-number-input.d.ts","sourceRoot":"","sources":["../../src/original-number-input/ordinal-number-input.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ordinal-number-input.d.ts","sourceRoot":"","sources":["../../src/original-number-input/ordinal-number-input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAK9D,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,MAAM,WAAW,uBAAwB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IACzE,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,qBACa,kBAAmB,SAAQ,SAAS,CAAC,uBAAuB,CAAC;IAC1D,QAAQ,UAAS;gBAEjB,KAAK,EAAE,uBAAuB;IAK1C,MAAM;IAeE,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,UAAU,CAAiC;IAE3D,OAAO,CAAC,YAAY,CAKlB;IAEF,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,eAAe;CAO1B;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,sBAWxE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkBjD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkBjD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/original-number-input/ordinal-number-input.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../src/original-number-input/ordinal-number-input.tsx"],"sourcesContent":["import type { InputProps } from '@servicetitan/design-system';\nimport { Input } from '@servicetitan/design-system';\nimport { action, observable, makeObservable } from 'mobx';\nimport { observer } from 'mobx-react';\nimport type { ChangeEvent } from 'react';\nimport { Component } from 'react';\n\nexport interface OrdinalNumberInputProps extends Omit<InputProps, 'onChange'> {\n min: number;\n max: number;\n value?: number;\n onChange?(value?: number): void;\n}\n\n@observer\nexport class OrdinalNumberInput extends Component<OrdinalNumberInputProps> {\n @observable hasFocus = false;\n\n constructor(props: OrdinalNumberInputProps) {\n super(props);\n makeObservable(this);\n }\n\n render() {\n const { min, max, value, onChange, ...props } = this.props;\n\n return (\n <Input\n placeholder={this.getPlaceholder()}\n {...props}\n value={this.getDisplayValue()}\n onFocus={this.handleFocus}\n onBlur={this.handleBlur}\n onChange={this.handleChange}\n />\n );\n }\n\n @action private handleFocus = () => (this.hasFocus = true);\n @action private handleBlur = () => (this.hasFocus = false);\n\n private handleChange = (e: ChangeEvent<HTMLInputElement>): void => {\n const parsed = parseIntIntoRange(e.currentTarget.value, this.props.min, this.props.max);\n if (this.props.onChange) {\n this.props.onChange(parsed);\n }\n };\n\n private getPlaceholder() {\n return `${this.props.min}‒${this.props.max}`;\n }\n\n private getDisplayValue() {\n const value = this.props.value;\n if (typeof value !== 'number') {\n return '';\n }\n return this.hasFocus ? value.toString() : ordinalString(value);\n }\n}\n\nexport function parseIntIntoRange(input: string, min: number, max: number) {\n let parsed = parseInt(input, 10);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n if (parsed < min) {\n parsed = min;\n } else if (parsed > max) {\n parsed = max;\n }\n return parsed;\n}\n\nexport function ordinalString(num: number): string {\n switch (num % 100) {\n case 11:\n case 12:\n case 13:\n return num.toString() + 'th';\n default:\n switch (num % 10) {\n case 1:\n return num.toString() + 'st';\n case 2:\n return num.toString() + 'nd';\n case 3:\n return num.toString() + 'rd';\n default:\n return num.toString() + 'th';\n }\n }\n}\n\nexport function ordinalSuffix(num: number): string {\n switch (num % 100) {\n case 11:\n case 12:\n case 13:\n return 'th';\n default:\n switch (num % 10) {\n case 1:\n return 'st';\n case 2:\n return 'nd';\n case 3:\n return 'rd';\n default:\n return 'th';\n }\n }\n}\n"],"names":["Input","action","observable","makeObservable","observer","Component","OrdinalNumberInput","render","min","max","value","onChange","props","placeholder","getPlaceholder","getDisplayValue","onFocus","handleFocus","onBlur","handleBlur","handleChange","hasFocus","toString","ordinalString","e","parsed","parseIntIntoRange","currentTarget","input","parseInt","Number","isNaN","undefined","num","ordinalSuffix"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AACA,SAASA,KAAK,QAAQ,8BAA8B;AACpD,SAASC,MAAM,EAAEC,UAAU,EAAEC,cAAc,QAAQ,OAAO;AAC1D,SAASC,QAAQ,QAAQ,aAAa;AAEtC,SAASC,SAAS,QAAQ,QAAQ;AAUlC,OAAO,MAAMC,2BAA2BD;IAQpCE,SAAS;QACL,MAAM,EAAEC,GAAG,EAAEC,GAAG,EAAEC,KAAK,EAAEC,QAAQ,EAAE,GAAGC,OAAO,GAAG,IAAI,CAACA,KAAK;QAE1D,qBACI,KAACZ;YACGa,aAAa,IAAI,CAACC,cAAc;YAC/B,GAAGF,KAAK;YACTF,OAAO,IAAI,CAACK,eAAe;YAC3BC,SAAS,IAAI,CAACC,WAAW;YACzBC,QAAQ,IAAI,CAACC,UAAU;YACvBR,UAAU,IAAI,CAACS,YAAY;;IAGvC;IAYQN,iBAAiB;QACrB,OAAO,GAAG,IAAI,CAACF,KAAK,CAACJ,GAAG,CAAC,CAAC,EAAE,IAAI,CAACI,KAAK,CAACH,GAAG,EAAE;IAChD;IAEQM,kBAAkB;QACtB,MAAML,QAAQ,IAAI,CAACE,KAAK,CAACF,KAAK;QAC9B,IAAI,OAAOA,UAAU,UAAU;YAC3B,OAAO;QACX;QACA,OAAO,IAAI,CAACW,QAAQ,GAAGX,MAAMY,QAAQ,KAAKC,cAAcb;IAC5D;IAxCA,YAAYE,KAA8B,CAAE;QACxC,KAAK,CAACA,QAHV,uBAAYS,YAAW,QAsBvB,uBAAgBJ,eAAc,IAAO,IAAI,CAACI,QAAQ,GAAG,OACrD,uBAAgBF,cAAa,IAAO,IAAI,CAACE,QAAQ,GAAG,QAEpD,uBAAQD,gBAAe,CAACI;YACpB,MAAMC,SAASC,kBAAkBF,EAAEG,aAAa,CAACjB,KAAK,EAAE,IAAI,CAACE,KAAK,CAACJ,GAAG,EAAE,IAAI,CAACI,KAAK,CAACH,GAAG;YACtF,IAAI,IAAI,CAACG,KAAK,CAACD,QAAQ,EAAE;gBACrB,IAAI,CAACC,KAAK,CAACD,QAAQ,CAACc;YACxB;QACJ;QA1BItB,eAAe,IAAI;IACvB;AAsCJ;;;;;;;;;;;;;;;;;AAEA,OAAO,SAASuB,kBAAkBE,KAAa,EAAEpB,GAAW,EAAEC,GAAW;IACrE,IAAIgB,SAASI,SAASD,OAAO;IAC7B,IAAIE,OAAOC,KAAK,CAACN,SAAS;QACtB,OAAOO;IACX;IACA,IAAIP,SAASjB,KAAK;QACdiB,SAASjB;IACb,OAAO,IAAIiB,SAAShB,KAAK;QACrBgB,SAAShB;IACb;IACA,OAAOgB;AACX;AAEA,OAAO,SAASF,cAAcU,GAAW;IACrC,OAAQA,MAAM;QACV,KAAK;QACL,KAAK;QACL,KAAK;YACD,OAAOA,IAAIX,QAAQ,KAAK;QAC5B;YACI,OAAQW,MAAM;gBACV,KAAK;oBACD,OAAOA,IAAIX,QAAQ,KAAK;gBAC5B,KAAK;oBACD,OAAOW,IAAIX,QAAQ,KAAK;gBAC5B,KAAK;oBACD,OAAOW,IAAIX,QAAQ,KAAK;gBAC5B;oBACI,OAAOW,IAAIX,QAAQ,KAAK;YAChC;IACR;AACJ;AAEA,OAAO,SAASY,cAAcD,GAAW;IACrC,OAAQA,MAAM;QACV,KAAK;QACL,KAAK;QACL,KAAK;YACD,OAAO;QACX;YACI,OAAQA,MAAM;gBACV,KAAK;oBACD,OAAO;gBACX,KAAK;oBACD,OAAO;gBACX,KAAK;oBACD,OAAO;gBACX;oBACI,OAAO;YACf;IACR;AACJ"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FC } from 'react';
|
|
2
|
-
import { TextFieldProps } from '@servicetitan/anvil2';
|
|
3
|
-
import { Culture } from '@servicetitan/culture';
|
|
1
|
+
import type { FC } from 'react';
|
|
2
|
+
import type { TextFieldProps } from '@servicetitan/anvil2';
|
|
3
|
+
import type { Culture } from '@servicetitan/culture';
|
|
4
4
|
type PhoneNumberInputA2Props = TextFieldProps & {
|
|
5
5
|
sip?: boolean;
|
|
6
6
|
culture?: Culture;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phone-number-input-a2.d.ts","sourceRoot":"","sources":["../../src/phone-number-input/phone-number-input-a2.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"phone-number-input-a2.d.ts","sourceRoot":"","sources":["../../src/phone-number-input/phone-number-input-a2.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,EAAE,EAAE,MAAM,OAAO,CAAC;AAI7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAIrD,KAAK,uBAAuB,GAAG,cAAc,GAAG;IAC5C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,EAAE,CAAC,uBAAuB,CA6E1D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/phone-number-input/phone-number-input-a2.tsx"],"sourcesContent":["import { ChangeEvent, FC
|
|
1
|
+
{"version":3,"sources":["../../src/phone-number-input/phone-number-input-a2.tsx"],"sourcesContent":["import type { ChangeEvent, FC } from 'react';\nimport { useCallback } from 'react';\nimport ReactInputMask from 'react-input-mask';\n\nimport type { TextFieldProps } from '@servicetitan/anvil2';\nimport { TextField } from '@servicetitan/anvil2';\nimport type { Culture } from '@servicetitan/culture';\nimport { CULTURE_TOKEN } from '@servicetitan/culture';\nimport { useOptionalDependencies } from '@servicetitan/react-ioc';\n\ntype PhoneNumberInputA2Props = TextFieldProps & {\n sip?: boolean;\n culture?: Culture;\n};\n\nexport const PhoneNumberInputA2: FC<PhoneNumberInputA2Props> = props => {\n const {\n value,\n onChange,\n placeholder: propPlaceholder,\n culture: propCulture,\n sip,\n onFocus,\n onBlur,\n disabled,\n readOnly,\n ...restProps\n } = props;\n\n const [injectedCulture] = useOptionalDependencies(CULTURE_TOKEN);\n const culture = propCulture ?? injectedCulture;\n const { SimplePhoneMask = '?9999999999', SampleSimplePhoneNumber = '' } =\n culture?.PhoneFormat ?? {};\n\n const mask = SimplePhoneMask.replace(/\\?/g, '');\n const placeholder = propPlaceholder ?? SampleSimplePhoneNumber;\n const displayValue = String(value ?? '').replace(/\\D/g, '');\n\n // Transform output value to digits-only (unmasked)\n const handleChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n if (onChange) {\n const digitsOnly = event.target.value.replace(/\\D/g, '');\n\n const unmaskedEvent = {\n ...event,\n target: { ...event.target, value: digitsOnly },\n currentTarget: { ...event.currentTarget, value: digitsOnly },\n } as ChangeEvent<HTMLInputElement>;\n\n onChange(unmaskedEvent);\n }\n },\n [onChange]\n );\n\n if (sip) {\n return (\n <TextField\n {...restProps}\n value={value}\n onChange={onChange}\n onFocus={onFocus}\n onBlur={onBlur}\n disabled={disabled}\n readOnly={readOnly}\n type=\"text\"\n placeholder={propPlaceholder}\n />\n );\n }\n\n const renderTextField = (inputProps: Record<string, unknown>) => {\n // Exclude 'size' as it conflicts with TextField's size prop type\n const { size: UNUSED_SIZE, ...filteredProps } = inputProps;\n return <TextField {...filteredProps} {...restProps} type=\"tel\" placeholder={placeholder} />;\n };\n\n return (\n <ReactInputMask\n value={displayValue}\n onChange={handleChange}\n mask={mask}\n maskChar={null}\n onFocus={onFocus}\n onBlur={onBlur}\n disabled={disabled}\n readOnly={readOnly}\n >\n {renderTextField as any}\n </ReactInputMask>\n );\n};\n"],"names":["useCallback","ReactInputMask","TextField","CULTURE_TOKEN","useOptionalDependencies","PhoneNumberInputA2","props","value","onChange","placeholder","propPlaceholder","culture","propCulture","sip","onFocus","onBlur","disabled","readOnly","restProps","injectedCulture","SimplePhoneMask","SampleSimplePhoneNumber","PhoneFormat","mask","replace","displayValue","String","handleChange","event","digitsOnly","target","unmaskedEvent","currentTarget","type","renderTextField","inputProps","size","UNUSED_SIZE","filteredProps","maskChar"],"mappings":";AACA,SAASA,WAAW,QAAQ,QAAQ;AACpC,OAAOC,oBAAoB,mBAAmB;AAG9C,SAASC,SAAS,QAAQ,uBAAuB;AAEjD,SAASC,aAAa,QAAQ,wBAAwB;AACtD,SAASC,uBAAuB,QAAQ,0BAA0B;AAOlE,OAAO,MAAMC,qBAAkDC,CAAAA;;IAC3D,MAAM,EACFC,KAAK,EACLC,QAAQ,EACRC,aAAaC,eAAe,EAC5BC,SAASC,WAAW,EACpBC,GAAG,EACHC,OAAO,EACPC,MAAM,EACNC,QAAQ,EACRC,QAAQ,EACR,GAAGC,WACN,GAAGZ;IAEJ,MAAM,CAACa,gBAAgB,GAAGf,wBAAwBD;IAClD,MAAMQ,UAAUC,wBAAAA,yBAAAA,cAAeO;IAC/B,MAAM,EAAEC,kBAAkB,aAAa,EAAEC,0BAA0B,EAAE,EAAE,WACnEV,oBAAAA,8BAAAA,QAASW,WAAW,uCAAI,CAAC;IAE7B,MAAMC,OAAOH,gBAAgBI,OAAO,CAAC,OAAO;IAC5C,MAAMf,cAAcC,4BAAAA,6BAAAA,kBAAmBW;IACvC,MAAMI,eAAeC,OAAOnB,kBAAAA,mBAAAA,QAAS,IAAIiB,OAAO,CAAC,OAAO;IAExD,mDAAmD;IACnD,MAAMG,eAAe3B,YACjB,CAAC4B;QACG,IAAIpB,UAAU;YACV,MAAMqB,aAAaD,MAAME,MAAM,CAACvB,KAAK,CAACiB,OAAO,CAAC,OAAO;YAErD,MAAMO,gBAAgB;gBAClB,GAAGH,KAAK;gBACRE,QAAQ;oBAAE,GAAGF,MAAME,MAAM;oBAAEvB,OAAOsB;gBAAW;gBAC7CG,eAAe;oBAAE,GAAGJ,MAAMI,aAAa;oBAAEzB,OAAOsB;gBAAW;YAC/D;YAEArB,SAASuB;QACb;IACJ,GACA;QAACvB;KAAS;IAGd,IAAIK,KAAK;QACL,qBACI,KAACX;YACI,GAAGgB,SAAS;YACbX,OAAOA;YACPC,UAAUA;YACVM,SAASA;YACTC,QAAQA;YACRC,UAAUA;YACVC,UAAUA;YACVgB,MAAK;YACLxB,aAAaC;;IAGzB;IAEA,MAAMwB,kBAAkB,CAACC;QACrB,iEAAiE;QACjE,MAAM,EAAEC,MAAMC,WAAW,EAAE,GAAGC,eAAe,GAAGH;QAChD,qBAAO,KAACjC;YAAW,GAAGoC,aAAa;YAAG,GAAGpB,SAAS;YAAEe,MAAK;YAAMxB,aAAaA;;IAChF;IAEA,qBACI,KAACR;QACGM,OAAOkB;QACPjB,UAAUmB;QACVJ,MAAMA;QACNgB,UAAU;QACVzB,SAASA;QACTC,QAAQA;QACRC,UAAUA;QACVC,UAAUA;kBAETiB;;AAGb,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phone-number-input.d.ts","sourceRoot":"","sources":["../../src/phone-number-input/phone-number-input.tsx"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"phone-number-input.d.ts","sourceRoot":"","sources":["../../src/phone-number-input/phone-number-input.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IACzD,GAAG,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,gBAAgB,iIAS5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/phone-number-input/phone-number-input.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport InputMask from 'react-input-mask';\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/phone-number-input/phone-number-input.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport InputMask from 'react-input-mask';\n\nimport type { FormInputProps } from '@servicetitan/design-system';\nimport { Form } from '@servicetitan/design-system';\n\nexport interface PhoneNumberInputProps extends FormInputProps {\n sip?: boolean;\n}\n\nexport const PhoneNumberInput = forwardRef<HTMLInputElement, PhoneNumberInputProps>(\n ({ sip, ...props }, ref) =>\n sip ? (\n <Form.Input {...props} ref={ref} />\n ) : (\n <InputMask maskChar={null} mask=\"(999) 999-9999\" {...props}>\n {(() => <Form.Input ref={ref} {...props} />) as any}\n </InputMask>\n )\n);\n"],"names":["forwardRef","InputMask","Form","PhoneNumberInput","sip","props","ref","Input","maskChar","mask"],"mappings":";AAAA,SAASA,UAAU,QAAQ,QAAQ;AACnC,OAAOC,eAAe,mBAAmB;AAGzC,SAASC,IAAI,QAAQ,8BAA8B;AAMnD,OAAO,MAAMC,iCAAmBH,WAC5B,CAAC,EAAEI,GAAG,EAAE,GAAGC,OAAO,EAAEC,MAChBF,oBACI,KAACF,KAAKK,KAAK;QAAE,GAAGF,KAAK;QAAEC,KAAKA;uBAE5B,KAACL;QAAUO,UAAU;QAAMC,MAAK;QAAkB,GAAGJ,KAAK;kBACpD,kBAAM,KAACH,KAAKK,KAAK;gBAACD,KAAKA;gBAAM,GAAGD,KAAK;;QAGrD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/form",
|
|
3
|
-
"version": "41.
|
|
3
|
+
"version": "41.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"homepage": "https://docs.st.dev/docs/frontend/form",
|
|
6
6
|
"repository": {
|
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
],
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@progress/kendo-react-dateinputs": "~5.5.0",
|
|
20
|
-
"@servicetitan/anvil2": "^
|
|
21
|
-
"@servicetitan/confirm": "^41.
|
|
22
|
-
"@servicetitan/culture": "^41.
|
|
20
|
+
"@servicetitan/anvil2": "^3.8.0",
|
|
21
|
+
"@servicetitan/confirm": "^41.2.0",
|
|
22
|
+
"@servicetitan/culture": "^41.2.0",
|
|
23
23
|
"@servicetitan/design-system": "~14.5.1",
|
|
24
|
-
"@servicetitan/form-state": "^41.
|
|
24
|
+
"@servicetitan/form-state": "^41.2.0",
|
|
25
25
|
"@servicetitan/hash-browser-router": "^38.0.0",
|
|
26
26
|
"@servicetitan/react-ioc": "^38.0.0",
|
|
27
27
|
"@servicetitan/tokens": ">=12.2.1",
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@progress/kendo-react-dateinputs": "~5.5.0",
|
|
45
45
|
"@servicetitan/anvil2": ">=1.42.0",
|
|
46
|
-
"@servicetitan/confirm": "^41.
|
|
47
|
-
"@servicetitan/culture": "^41.
|
|
46
|
+
"@servicetitan/confirm": "^41.2.0",
|
|
47
|
+
"@servicetitan/culture": "^41.2.0",
|
|
48
48
|
"@servicetitan/design-system": ">=13.2.1",
|
|
49
|
-
"@servicetitan/form-state": "^41.
|
|
49
|
+
"@servicetitan/form-state": "^41.2.0",
|
|
50
50
|
"@servicetitan/react-ioc": ">21.0.0",
|
|
51
51
|
"@servicetitan/tokens": ">=12.2.1",
|
|
52
52
|
"accounting": "~0.4.1",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"less": true,
|
|
72
72
|
"webpack": false
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "a27c08d5c4a695eb24110ec1477fa23ccf28a148"
|
|
75
75
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { ComponentType,
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import type { ComponentType, SyntheticEvent } from 'react';
|
|
2
|
+
import { Component } from 'react';
|
|
3
|
+
import type {
|
|
4
4
|
DateRangePickerChangeEvent,
|
|
5
5
|
CalendarHeaderTitleProps,
|
|
6
6
|
MultiViewCalendarProps,
|
|
7
7
|
CalendarCellProps,
|
|
8
8
|
ActiveView,
|
|
9
9
|
} from '@progress/kendo-react-dateinputs';
|
|
10
|
+
import { DateRangePicker as DateRangePickerKendo } from '@progress/kendo-react-dateinputs';
|
|
10
11
|
import { Icon, InputDateMask, Stack } from '@servicetitan/design-system';
|
|
11
|
-
import { DateRange } from '@servicetitan/form-state';
|
|
12
|
+
import type { DateRange } from '@servicetitan/form-state';
|
|
12
13
|
import { observable, action, makeObservable } from 'mobx';
|
|
13
14
|
import { observer } from 'mobx-react';
|
|
14
15
|
import classnames from 'classnames';
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FC } from 'react';
|
|
2
|
+
import { Fragment, useRef, useMemo } from 'react';
|
|
2
3
|
|
|
3
4
|
import { observer } from 'mobx-react';
|
|
4
5
|
|
|
5
6
|
import { Text, Card, Tag } from '@servicetitan/design-system';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
+
import type { ColorPickerPreviewProps } from '..';
|
|
9
|
+
import { ColorPicker } from '..';
|
|
8
10
|
|
|
9
11
|
import { FieldState } from 'formstate';
|
|
10
12
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FC } from 'react';
|
|
2
|
+
import { Fragment, useRef } from 'react';
|
|
2
3
|
|
|
3
4
|
import { observer } from 'mobx-react';
|
|
4
5
|
|
|
5
6
|
import { Text } from '@servicetitan/design-system';
|
|
6
|
-
import { DateRange } from '@servicetitan/form-state';
|
|
7
|
+
import type { DateRange } from '@servicetitan/form-state';
|
|
7
8
|
|
|
8
9
|
import { DateRangePicker } from '..';
|
|
9
10
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FC } from 'react';
|
|
2
|
+
import { useRef, Fragment } from 'react';
|
|
2
3
|
import { observer } from 'mobx-react';
|
|
3
4
|
import { BodyText } from '@servicetitan/design-system';
|
|
4
|
-
import {
|
|
5
|
+
import type { FileDescriptor } from '..';
|
|
6
|
+
import { FileUploader, FileUploaderConfigurationProvider } from '..';
|
|
5
7
|
|
|
6
8
|
import { FieldState } from 'formstate';
|
|
7
9
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { ChangeEvent, FC
|
|
1
|
+
import type { ChangeEvent, FC } from 'react';
|
|
2
|
+
import { useState } from 'react';
|
|
2
3
|
|
|
3
4
|
import { observer } from 'mobx-react';
|
|
4
5
|
|
|
5
|
-
import { Culture } from '@servicetitan/culture';
|
|
6
|
+
import type { Culture } from '@servicetitan/culture';
|
|
6
7
|
|
|
7
8
|
import { PhoneNumberInputA2 } from '..';
|
|
8
9
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Banner } from '@servicetitan/design-system';
|
|
2
2
|
import { traverseFormState } from '@servicetitan/form-state';
|
|
3
3
|
import { observer } from 'mobx-react';
|
|
4
|
-
import { FormState, ValidatableMapOrArray } from 'formstate';
|
|
4
|
+
import type { FormState, ValidatableMapOrArray } from 'formstate';
|
|
5
5
|
|
|
6
6
|
export interface FormStateErrorBannerProps<T extends ValidatableMapOrArray> {
|
|
7
7
|
form: FormState<T>;
|