@elliemae/ds-controlled-form 2.3.0-next.16 → 2.3.0-next.17

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.
Files changed (66) hide show
  1. package/cjs/controlled-mask-hook/hooks/index.js +10 -0
  2. package/cjs/controlled-mask-hook/hooks/usePhoneMask.js +72 -0
  3. package/cjs/controlled-mask-hook/index.js +10 -0
  4. package/cjs/controlled-mask-hook/react-desc-prop-types.js +19 -0
  5. package/cjs/controlled-mask-hook/utils/addSpecialCharacters.js +50 -0
  6. package/cjs/controlled-mask-hook/utils/getPartialMaskedPos.js +15 -0
  7. package/cjs/controlled-mask-hook/utils/index.js +13 -0
  8. package/cjs/controlled-mask-hook/utils/setCursorPosition.js +9 -0
  9. package/cjs/controlled-text-input/DSInputText.js +89 -0
  10. package/cjs/controlled-text-input/config/useInputText.js +54 -0
  11. package/cjs/controlled-text-input/exported-related/data-test-ids.js +10 -0
  12. package/cjs/controlled-text-input/exported-related/index.js +12 -0
  13. package/cjs/controlled-text-input/exported-related/theming.js +13 -0
  14. package/cjs/controlled-text-input/index.js +15 -0
  15. package/cjs/controlled-text-input/react-desc-prop-types.js +45 -0
  16. package/cjs/controlled-text-input/styled/borders.js +33 -0
  17. package/cjs/controlled-text-input/styled/components.js +38 -0
  18. package/cjs/index.js +17 -6
  19. package/esm/controlled-mask-hook/hooks/index.js +1 -0
  20. package/esm/controlled-mask-hook/hooks/usePhoneMask.js +67 -0
  21. package/esm/controlled-mask-hook/index.js +1 -0
  22. package/esm/controlled-mask-hook/react-desc-prop-types.js +14 -0
  23. package/esm/controlled-mask-hook/utils/addSpecialCharacters.js +46 -0
  24. package/esm/controlled-mask-hook/utils/getPartialMaskedPos.js +11 -0
  25. package/esm/controlled-mask-hook/utils/index.js +3 -0
  26. package/esm/controlled-mask-hook/utils/setCursorPosition.js +5 -0
  27. package/esm/controlled-text-input/DSInputText.js +78 -0
  28. package/esm/controlled-text-input/config/useInputText.js +50 -0
  29. package/esm/controlled-text-input/exported-related/data-test-ids.js +6 -0
  30. package/esm/controlled-text-input/exported-related/index.js +2 -0
  31. package/esm/controlled-text-input/exported-related/theming.js +8 -0
  32. package/esm/controlled-text-input/index.js +3 -0
  33. package/esm/controlled-text-input/react-desc-prop-types.js +36 -0
  34. package/esm/controlled-text-input/styled/borders.js +24 -0
  35. package/esm/controlled-text-input/styled/components.js +28 -0
  36. package/esm/index.js +6 -2
  37. package/package.json +79 -10
  38. package/types/controlled-autocomplete/parts/controls/styled.d.ts +1 -1
  39. package/types/controlled-combobox/parts/controls/styled.d.ts +2 -2
  40. package/types/controlled-combobox/parts/dropdown-indicator/styled.d.ts +1 -1
  41. package/types/controlled-date-time-picker/parts/Pickers/Calendar/Styleds.d.ts +4 -4
  42. package/types/controlled-date-time-picker/parts/Pickers/CalendarWithTimeWheel/Styleds.d.ts +1 -1
  43. package/types/controlled-date-time-picker/parts/Pickers/TimeWheel/Styleds.d.ts +4 -4
  44. package/types/controlled-date-time-picker/parts/Styleds.d.ts +6 -6
  45. package/types/controlled-mask-hook/hooks/index.d.ts +1 -0
  46. package/types/controlled-mask-hook/hooks/usePhoneMask.d.ts +3 -0
  47. package/types/controlled-mask-hook/index.d.ts +2 -0
  48. package/types/controlled-mask-hook/react-desc-prop-types.d.ts +17 -0
  49. package/types/controlled-mask-hook/tests/usePhoneMask.test.d.ts +1 -0
  50. package/types/controlled-mask-hook/utils/addSpecialCharacters.d.ts +9 -0
  51. package/types/controlled-mask-hook/utils/getPartialMaskedPos.d.ts +1 -0
  52. package/types/controlled-mask-hook/utils/index.d.ts +3 -0
  53. package/types/controlled-mask-hook/utils/setCursorPosition.d.ts +1 -0
  54. package/types/controlled-text-input/DSInputText.d.ts +4 -0
  55. package/types/controlled-text-input/config/useInputText.d.ts +434 -0
  56. package/types/controlled-text-input/exported-related/data-test-ids.d.ts +4 -0
  57. package/types/controlled-text-input/exported-related/index.d.ts +2 -0
  58. package/types/controlled-text-input/exported-related/theming.d.ts +6 -0
  59. package/types/controlled-text-input/index.d.ts +2 -0
  60. package/types/controlled-text-input/react-desc-prop-types.d.ts +20 -0
  61. package/types/controlled-text-input/styled/borders.d.ts +10 -0
  62. package/types/controlled-text-input/styled/components.d.ts +3 -0
  63. package/types/controlled-text-input/tests/DSInput.events.test.d.ts +1 -0
  64. package/types/controlled-text-input/tests/DSInput.keyboard.test.d.ts +1 -0
  65. package/types/controlled-text-input/tests/DSInput.test.d.ts +1 -0
  66. package/types/index.d.ts +4 -2
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var usePhoneMask = require('./usePhoneMask.js');
6
+
7
+
8
+
9
+ exports.UsePhoneMaskWithSchema = usePhoneMask.UsePhoneMaskWithSchema;
10
+ exports.usePhoneMask = usePhoneMask.usePhoneMask;
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ require('core-js/modules/esnext.async-iterator.filter.js');
6
+ require('core-js/modules/esnext.iterator.constructor.js');
7
+ require('core-js/modules/esnext.iterator.filter.js');
8
+ require('core-js/modules/web.dom-collections.iterator.js');
9
+ var React = require('react');
10
+ var dsPropsHelpers = require('@elliemae/ds-props-helpers');
11
+ var dsUtilities = require('@elliemae/ds-utilities');
12
+ var addSpecialCharacters = require('../utils/addSpecialCharacters.js');
13
+ var getPartialMaskedPos = require('../utils/getPartialMaskedPos.js');
14
+ var setCursorPosition = require('../utils/setCursorPosition.js');
15
+ var reactDescPropTypes = require('../react-desc-prop-types.js');
16
+
17
+ const phoneSpecialChars = [['(', 0], [') ', 4], ['-', 9]];
18
+
19
+ const conformValue = (rawValue, cursorPos, lastKeyCode) => {
20
+ // Work with digits only
21
+ let maskedValue = rawValue.split('').filter(char => char >= '0' && char <= '9'); // We can't have zeros at the start of the array
22
+
23
+ while (maskedValue.length && maskedValue[0] === '0') maskedValue.splice(0, 1); // We only consider first 10 digits
24
+
25
+
26
+ maskedValue = maskedValue.slice(0, 10);
27
+ const maskedPos = getPartialMaskedPos.getPartialMaskedPos(rawValue, maskedValue, cursorPos);
28
+ return addSpecialCharacters.addSpecialCharacters(maskedValue, phoneSpecialChars, maskedPos, lastKeyCode);
29
+ };
30
+
31
+ const usePhoneMask = props => {
32
+ const propsWithDefault = dsPropsHelpers.useMemoMergePropsWithDefault(props, reactDescPropTypes.DSMaskHookDefaultProps);
33
+ dsPropsHelpers.useValidateTypescriptPropTypes(propsWithDefault, reactDescPropTypes.DSMaskHookPropsTypes);
34
+ const {
35
+ valueSetter,
36
+ onChange: userOnChange,
37
+ onKeyDown: userOnKeyDown
38
+ } = propsWithDefault;
39
+ const lastKeyCode = React.useRef('Unidentified');
40
+ const scheduleAfterRender = dsUtilities.useCallbackAfterRender(); // Some times, the value of the mask is not gonna change (user types invalid char for example)
41
+ // This makes the input to go from "correct" -> "incorrect" -> "correct"
42
+ // But since the input is controlled, the input does not re-render
43
+ // This makes the input go mumbo-jumbo and places the cursor in the end, because we kinda changed the value async
44
+ // Solution for this is to trigger a re-render, we do this with a set state call in the on change event
45
+
46
+ const [, setKey] = React.useState(0);
47
+ const onKeyDown = React.useCallback(e => {
48
+ lastKeyCode.current = e.code;
49
+ if (userOnKeyDown) userOnKeyDown(e);
50
+ }, [userOnKeyDown]);
51
+ const onChange = React.useCallback(e => {
52
+ var _e$target$selectionEn;
53
+
54
+ const [mask, cursorPos] = conformValue(e.target.value, (_e$target$selectionEn = e.target.selectionEnd) !== null && _e$target$selectionEn !== void 0 ? _e$target$selectionEn : 0, lastKeyCode.current);
55
+ valueSetter(prevMask => {
56
+ // Here we need to update the key
57
+ if (mask === prevMask) setKey(key => key + 1);
58
+ return mask;
59
+ });
60
+ if (userOnChange) userOnChange(e, mask);
61
+ scheduleAfterRender(() => setCursorPosition.setCursorPosition(e.target, cursorPos));
62
+ }, [valueSetter, scheduleAfterRender, userOnChange]);
63
+ return {
64
+ onKeyDown,
65
+ onChange
66
+ };
67
+ };
68
+ const UsePhoneMaskWithSchema = dsPropsHelpers.describe(usePhoneMask);
69
+ UsePhoneMaskWithSchema.propTypes = reactDescPropTypes.DSMaskHookPropsTypes;
70
+
71
+ exports.UsePhoneMaskWithSchema = UsePhoneMaskWithSchema;
72
+ exports.usePhoneMask = usePhoneMask;
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var usePhoneMask = require('./hooks/usePhoneMask.js');
6
+
7
+
8
+
9
+ exports.UsePhoneMaskWithSchema = usePhoneMask.UsePhoneMaskWithSchema;
10
+ exports.usePhoneMask = usePhoneMask.usePhoneMask;
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var dsPropsHelpers = require('@elliemae/ds-props-helpers');
6
+
7
+ const DSMaskHookDefaultProps = {
8
+ onChange: () => null,
9
+ onKeyDown: () => null,
10
+ onBlur: () => null
11
+ };
12
+ const DSMaskHookPropsTypes = {
13
+ valueSetter: dsPropsHelpers.PropTypes.func.description('React set state function for the value').isRequired,
14
+ onChange: dsPropsHelpers.PropTypes.func.description('Callback for onChange'),
15
+ onKeyDown: dsPropsHelpers.PropTypes.func.description('Callback for onKeyDown')
16
+ };
17
+
18
+ exports.DSMaskHookDefaultProps = DSMaskHookDefaultProps;
19
+ exports.DSMaskHookPropsTypes = DSMaskHookPropsTypes;
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ require('core-js/modules/esnext.async-iterator.for-each.js');
6
+ require('core-js/modules/esnext.iterator.constructor.js');
7
+ require('core-js/modules/esnext.iterator.for-each.js');
8
+ require('core-js/modules/web.dom-collections.iterator.js');
9
+
10
+ /* eslint-disable max-params */
11
+
12
+ /**
13
+ *
14
+ * @param {string[]} maskWithoutSpecialChars An array of characters with the unfinished mask
15
+ * @param {[string, number][]} specialCharsDescr An array of tuples. Each tuple contains a string and a position (What string to add in a particular position)
16
+ * @param {number} maskedPos Current masked position
17
+ * @param {string} lastKeyCode Last key code of the user
18
+ * @returns {[string, number]} A tuple containing the final mask and the final masked position
19
+ */
20
+ const addSpecialCharacters = (maskWithoutSpecialChars, specialCharsDescr, maskedPos, lastKeyCode) => {
21
+ const finalMask = maskWithoutSpecialChars;
22
+ let finalMaskedPos = maskedPos; // We insert the special chars in the respective positions, tweaking the masked pos
23
+
24
+ specialCharsDescr.forEach(_ref => {
25
+ let [chars, pos] = _ref;
26
+
27
+ if (finalMask.length > pos) {
28
+ finalMask.splice(pos, 0, ...chars);
29
+ if (finalMaskedPos >= pos) finalMaskedPos += chars.length;
30
+ }
31
+ });
32
+
33
+ if (lastKeyCode !== 'Backspace' && finalMaskedPos < finalMask.length) {
34
+ // If not erasing, move the cursor forward if we are in a special chars area
35
+ specialCharsDescr.forEach(_ref2 => {
36
+ let [chars, pos] = _ref2;
37
+ if (finalMaskedPos === pos) finalMaskedPos += chars.length;
38
+ });
39
+ } else if (lastKeyCode === 'Backspace' && finalMaskedPos) {
40
+ // If erasing, move the cursor back if we are in a special chars area
41
+ specialCharsDescr.forEach(_ref3 => {
42
+ let [chars, pos] = _ref3;
43
+ if (pos + 1 <= finalMaskedPos && finalMaskedPos <= pos + chars.length) finalMaskedPos = pos;
44
+ });
45
+ }
46
+
47
+ return [finalMask.join(''), finalMaskedPos];
48
+ };
49
+
50
+ exports.addSpecialCharacters = addSpecialCharacters;
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const getPartialMaskedPos = (rawValue, maskWithoutSpecialChars, cursorPos) => {
6
+ let maskedPos = 0;
7
+
8
+ for (let i = 0; i < cursorPos; i += 1) {
9
+ if (maskWithoutSpecialChars[maskedPos] === rawValue[i]) maskedPos += 1;
10
+ }
11
+
12
+ return maskedPos;
13
+ };
14
+
15
+ exports.getPartialMaskedPos = getPartialMaskedPos;
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var addSpecialCharacters = require('./addSpecialCharacters.js');
6
+ var getPartialMaskedPos = require('./getPartialMaskedPos.js');
7
+ var setCursorPosition = require('./setCursorPosition.js');
8
+
9
+
10
+
11
+ exports.addSpecialCharacters = addSpecialCharacters.addSpecialCharacters;
12
+ exports.getPartialMaskedPos = getPartialMaskedPos.getPartialMaskedPos;
13
+ exports.setCursorPosition = setCursorPosition.setCursorPosition;
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const setCursorPosition = (input, position) => {
6
+ input.setSelectionRange(position, position, 'forward');
7
+ };
8
+
9
+ exports.setCursorPosition = setCursorPosition;
@@ -0,0 +1,89 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ require('core-js/modules/esnext.async-iterator.filter.js');
6
+ require('core-js/modules/esnext.iterator.constructor.js');
7
+ require('core-js/modules/esnext.iterator.filter.js');
8
+ require('core-js/modules/esnext.async-iterator.for-each.js');
9
+ require('core-js/modules/esnext.iterator.for-each.js');
10
+ var _jsx = require('@babel/runtime/helpers/jsx');
11
+ var _defineProperty = require('@babel/runtime/helpers/defineProperty');
12
+ var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
13
+ require('react');
14
+ var dsIcons = require('@elliemae/ds-icons');
15
+ var dsIcon = require('@elliemae/ds-icon');
16
+ var dsPropsHelpers = require('@elliemae/ds-props-helpers');
17
+ var useInputText = require('./config/useInputText.js');
18
+ var dataTestIds = require('./exported-related/data-test-ids.js');
19
+ var reactDescPropTypes = require('./react-desc-prop-types.js');
20
+ var components = require('./styled/components.js');
21
+ var jsxRuntime = require('react/jsx-runtime');
22
+
23
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
24
+
25
+ var _jsx__default = /*#__PURE__*/_interopDefaultLegacy(_jsx);
26
+ var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
27
+ var _objectWithoutProperties__default = /*#__PURE__*/_interopDefaultLegacy(_objectWithoutProperties);
28
+
29
+ const _excluded = ["className"];
30
+
31
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
32
+
33
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
34
+ const DSInputText = props => {
35
+ const _useInputText = useInputText.useInputText(props),
36
+ {
37
+ globalAttributes: {
38
+ className
39
+ },
40
+ hasFocus,
41
+ handlers,
42
+ propsWithDefault,
43
+ xstyledProps
44
+ } = _useInputText,
45
+ otherGlobalAttributes = _objectWithoutProperties__default["default"](_useInputText.globalAttributes, _excluded);
46
+
47
+ const {
48
+ clearable,
49
+ disabled,
50
+ hasError,
51
+ innerRef,
52
+ placeholder,
53
+ readOnly,
54
+ inputSize,
55
+ onClear,
56
+ value
57
+ } = propsWithDefault;
58
+ const shouldDisplayClearButton = clearable && value !== '';
59
+ return /*#__PURE__*/jsxRuntime.jsxs(components.StyledInputWrapper, _objectSpread(_objectSpread({
60
+ className: className,
61
+ cols: shouldDisplayClearButton ? ['auto', 'min-content'] : ['auto'],
62
+ isDisabled: disabled,
63
+ isReadOnly: readOnly,
64
+ hasError: hasError,
65
+ hasFocus: hasFocus,
66
+ inputSize: inputSize
67
+ }, xstyledProps), {}, {
68
+ children: [/*#__PURE__*/jsxRuntime.jsx(components.StyledInput, _objectSpread(_objectSpread({
69
+ "data-testid": dataTestIds.DSInputTextDataTestIds.INPUT,
70
+ disabled: disabled,
71
+ placeholder: placeholder,
72
+ readOnly: readOnly,
73
+ ref: innerRef,
74
+ value: value
75
+ }, handlers), otherGlobalAttributes)), shouldDisplayClearButton && /*#__PURE__*/_jsx__default["default"](components.StyledClearButton, {
76
+ "aria-label": "Clear input value",
77
+ buttonType: "icon",
78
+ "data-testid": dataTestIds.DSInputTextDataTestIds.CLEAR_BUTTON,
79
+ onClick: onClear
80
+ }, void 0, /*#__PURE__*/_jsx__default["default"](dsIcons.CloseMedium, {
81
+ color: dsIcon.DSIconColors.PRIMARY
82
+ }))]
83
+ }));
84
+ };
85
+ const DSInputTextWithSchema = dsPropsHelpers.describe(DSInputText);
86
+ DSInputTextWithSchema.propTypes = reactDescPropTypes.DSInputTextPropTypes;
87
+
88
+ exports.DSInputText = DSInputText;
89
+ exports.DSInputTextWithSchema = DSInputTextWithSchema;
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ require('core-js/modules/web.dom-collections.iterator.js');
6
+ var dsPropsHelpers = require('@elliemae/ds-props-helpers');
7
+ var React = require('react');
8
+ var reactDescPropTypes = require('../react-desc-prop-types.js');
9
+
10
+ const useInputText = props => {
11
+ const propsWithDefault = dsPropsHelpers.useMemoMergePropsWithDefault(props, reactDescPropTypes.defaultProps);
12
+ dsPropsHelpers.useValidateTypescriptPropTypes(props, reactDescPropTypes.DSInputTextPropTypes);
13
+ const {
14
+ onValueChange
15
+ } = propsWithDefault; // =============================================================================
16
+ // INTERNAL STATE
17
+ // =============================================================================
18
+
19
+ const [hasFocus, setHasFocus] = React.useState(false); // ===========================================================================
20
+ // INTERNAL HANDLERS
21
+ // ===========================================================================
22
+
23
+ const handleOnChange = React.useCallback(e => {
24
+ onValueChange(e.target.value, e);
25
+ }, [onValueChange]);
26
+ const handleOnFocus = React.useCallback(() => {
27
+ setHasFocus(true);
28
+ }, []);
29
+ const handleOnBlur = React.useCallback(() => {
30
+ setHasFocus(false);
31
+ }, []); // =============================================================================
32
+ // GLOBAL ATTRIBUTES & XSTYLED PROPS
33
+ // =============================================================================
34
+
35
+ const globalAttributes = dsPropsHelpers.useGetGlobalAttributes(propsWithDefault, {
36
+ onChange: handleOnChange,
37
+ onFocus: handleOnFocus,
38
+ onBlur: handleOnBlur
39
+ });
40
+ const xstyledProps = dsPropsHelpers.useGetXstyledProps(propsWithDefault);
41
+ return React.useMemo(() => ({
42
+ globalAttributes,
43
+ hasFocus,
44
+ handlers: {
45
+ onChange: handleOnChange,
46
+ onFocus: handleOnFocus,
47
+ onBlur: handleOnBlur
48
+ },
49
+ propsWithDefault,
50
+ xstyledProps
51
+ }), [globalAttributes, handleOnBlur, handleOnChange, handleOnFocus, hasFocus, propsWithDefault, xstyledProps]);
52
+ };
53
+
54
+ exports.useInputText = useInputText;
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const DSInputTextDataTestIds = {
6
+ INPUT: 'ds-input-text-input',
7
+ CLEAR_BUTTON: 'ds-input-text-clear-button'
8
+ };
9
+
10
+ exports.DSInputTextDataTestIds = DSInputTextDataTestIds;
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var dataTestIds = require('./data-test-ids.js');
6
+ var theming = require('./theming.js');
7
+
8
+
9
+
10
+ exports.DSInputTextDataTestIds = dataTestIds.DSInputTextDataTestIds;
11
+ exports.DSInputTextName = theming.DSInputTextName;
12
+ exports.DSInputTextSlots = theming.DSInputTextSlots;
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const DSInputTextName = 'ds-input-text';
6
+ const DSInputTextSlots = {
7
+ INPUT_WRAPPER: 'root',
8
+ INPUT: 'input',
9
+ CLEAR_BUTTON: 'input-clear-button'
10
+ };
11
+
12
+ exports.DSInputTextName = DSInputTextName;
13
+ exports.DSInputTextSlots = DSInputTextSlots;
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var DSInputText = require('./DSInputText.js');
6
+ var dataTestIds = require('./exported-related/data-test-ids.js');
7
+ var theming = require('./exported-related/theming.js');
8
+
9
+
10
+
11
+ exports.DSInputText = DSInputText.DSInputText;
12
+ exports.DSInputTextWithSchema = DSInputText.DSInputTextWithSchema;
13
+ exports.DSInputTextDataTestIds = dataTestIds.DSInputTextDataTestIds;
14
+ exports.DSInputTextName = theming.DSInputTextName;
15
+ exports.DSInputTextSlots = theming.DSInputTextSlots;
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ require('core-js/modules/esnext.async-iterator.filter.js');
6
+ require('core-js/modules/esnext.iterator.constructor.js');
7
+ require('core-js/modules/esnext.iterator.filter.js');
8
+ require('core-js/modules/esnext.async-iterator.for-each.js');
9
+ require('core-js/modules/esnext.iterator.for-each.js');
10
+ var _defineProperty = require('@babel/runtime/helpers/defineProperty');
11
+ var dsPropsHelpers = require('@elliemae/ds-props-helpers');
12
+
13
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
14
+
15
+ var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
16
+
17
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
18
+
19
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
20
+ const defaultProps = {
21
+ value: '',
22
+ onValueChange: () => null,
23
+ onClear: () => null,
24
+ placeholder: 'Hint Text',
25
+ disabled: false,
26
+ readOnly: false,
27
+ hasError: false,
28
+ innerRef: () => null,
29
+ inputSize: 'm',
30
+ clearable: false
31
+ };
32
+ const DSInputTextPropTypes = _objectSpread(_objectSpread(_objectSpread({}, dsPropsHelpers.globalAttributesPropTypes), dsPropsHelpers.xstyledPropTypes), {}, {
33
+ value: dsPropsHelpers.PropTypes.oneOfType([dsPropsHelpers.PropTypes.string, dsPropsHelpers.PropTypes.number, dsPropsHelpers.PropTypes.arrayOf(dsPropsHelpers.PropTypes.string)]).description('Value of the input').defaultValue(''),
34
+ onChange: dsPropsHelpers.PropTypes.func.description('onChange event handler').defaultValue(() => null),
35
+ placeholder: dsPropsHelpers.PropTypes.string.description('Value of the placeholder').defaultValue(''),
36
+ innerRef: dsPropsHelpers.PropTypes.oneOfType([dsPropsHelpers.PropTypes.object, dsPropsHelpers.PropTypes.func]).description('Reference to the input').defaultValue(null),
37
+ disabled: dsPropsHelpers.PropTypes.bool.description('Whether the input is disabled').defaultValue(false),
38
+ readOnly: dsPropsHelpers.PropTypes.bool.description('Whether the input is readonly').defaultValue(false),
39
+ hasError: dsPropsHelpers.PropTypes.bool.description('Whether the input has error').defaultValue(false),
40
+ inputSize: dsPropsHelpers.PropTypes.oneOf(['s', 'm']).description('Size of the input').defaultValue('m'),
41
+ clearable: dsPropsHelpers.PropTypes.bool.description('Whether the input is clearable').defaultValue(false)
42
+ });
43
+
44
+ exports.DSInputTextPropTypes = DSInputTextPropTypes;
45
+ exports.defaultProps = defaultProps;
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _taggedTemplateLiteral = require('@babel/runtime/helpers/taggedTemplateLiteral');
6
+ var dsSystem = require('@elliemae/ds-system');
7
+
8
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
+
10
+ var _taggedTemplateLiteral__default = /*#__PURE__*/_interopDefaultLegacy(_taggedTemplateLiteral);
11
+
12
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5;
13
+ const commonBorderCss = dsSystem.css(_templateObject || (_templateObject = _taggedTemplateLiteral__default["default"](["\n border: 1px solid ", ";\n"])), dsSystem.th.color('neutral-400'));
14
+ const readOnlyBorderCss = dsSystem.css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral__default["default"](["\n border: 1px solid transparent;\n border-top-color: ", ";\n"])), dsSystem.th.color('neutral-400'));
15
+ const disabledBorderCss = commonBorderCss;
16
+ const hasErrorBorderCss = dsSystem.css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral__default["default"](["\n border: 1px solid ", ";\n"])), dsSystem.th.color('danger-900'));
17
+ const hoverBorderCss = dsSystem.css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral__default["default"](["\n border: 1px solid ", ";\n"])), dsSystem.th.color('brand-700'));
18
+ const focusBorderCss = dsSystem.css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral__default["default"](["\n border: 1px solid transparent;\n outline: 2px solid ", ";\n outline-offset: -1px;\n"])), dsSystem.th.color('brand-700'));
19
+ const getBorderCss = props => {
20
+ if (props.isDisabled) return disabledBorderCss;
21
+ if (props.hasFocus) return focusBorderCss;
22
+ if (props.hasError) return hasErrorBorderCss;
23
+ if (props.isReadOnly) return readOnlyBorderCss;
24
+ return commonBorderCss;
25
+ };
26
+ const getHoverBorderCss = props => {
27
+ if (props.isDisabled) return disabledBorderCss;
28
+ if (props.hasFocus) return focusBorderCss;
29
+ return hoverBorderCss;
30
+ };
31
+
32
+ exports.getBorderCss = getBorderCss;
33
+ exports.getHoverBorderCss = getHoverBorderCss;
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _taggedTemplateLiteral = require('@babel/runtime/helpers/taggedTemplateLiteral');
6
+ var DSButton = require('@elliemae/ds-button');
7
+ var dsGrid = require('@elliemae/ds-grid');
8
+ var dsSystem = require('@elliemae/ds-system');
9
+ var styledComponents = require('@xstyled/styled-components');
10
+ var theming = require('../exported-related/theming.js');
11
+ var borders = require('./borders.js');
12
+
13
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
14
+
15
+ var _taggedTemplateLiteral__default = /*#__PURE__*/_interopDefaultLegacy(_taggedTemplateLiteral);
16
+
17
+ var _templateObject, _templateObject2, _templateObject3;
18
+ const StyledInputWrapper = dsSystem.styled(dsGrid.Grid, {
19
+ name: theming.DSInputTextName,
20
+ slot: theming.DSInputTextSlots.INPUT_WRAPPER
21
+ })(_templateObject || (_templateObject = _taggedTemplateLiteral__default["default"](["\n height: ", ";\n\n ", "\n border-radius: 2px;\n\n :hover {\n ", "\n }\n\n ", "\n ", "\n ", "\n"])), _ref => {
22
+ let {
23
+ inputSize
24
+ } = _ref;
25
+ return inputSize === 'm' ? '28px' : '24px';
26
+ }, borders.getBorderCss, borders.getHoverBorderCss, styledComponents.layout, styledComponents.space, styledComponents.sizing);
27
+ const StyledInput = dsSystem.styled('input', {
28
+ name: theming.DSInputTextName,
29
+ slot: theming.DSInputTextSlots.INPUT
30
+ })(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral__default["default"](["\n padding: 0 ", ";\n border: none;\n outline: none;\n border-radius: 2px;\n\n width: 100%;\n height: 100%;\n font-size: 13px;\n\n ::placeholder {\n font-weight: ", ";\n font-style: italic;\n color: ", ";\n }\n\n :disabled {\n background-color: ", ";\n color: #616b7f;\n cursor: not-allowed;\n }\n"])), dsSystem.th.space('xxs'), dsSystem.th.fontWeight('regular'), dsSystem.th.color('neutral-500'), dsSystem.th.color('neutral-080'));
31
+ const StyledClearButton = dsSystem.styled(DSButton.DSButtonV2, {
32
+ name: theming.DSInputTextName,
33
+ slot: theming.DSInputTextSlots.CLEAR_BUTTON
34
+ })(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral__default["default"](["\n height: 100%;\n min-width: 20px;\n width: 20px;\n &:after {\n border-top-left-radius: 0px !important;\n border-bottom-left-radius: 0px !important;\n }\n :focus {\n border-width: 0px;\n }\n"])));
35
+
36
+ exports.StyledClearButton = StyledClearButton;
37
+ exports.StyledInput = StyledInput;
38
+ exports.StyledInputWrapper = StyledInputWrapper;
package/cjs/index.js CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var Autocomplete = require('./controlled-autocomplete/Autocomplete.js');
5
6
  var ControlledCheckbox = require('./controlled-checkbox/ControlledCheckbox.js');
7
+ var ComboBox = require('./controlled-combobox/ComboBox.js');
6
8
  var ControlledDateRangePicker = require('./controlled-date-range-picker/ControlledDateRangePicker.js');
7
9
  var ControlledDateRangePickerDatatestid = require('./controlled-date-range-picker/ControlledDateRangePickerDatatestid.js');
8
10
  var ControlledDateRangePickerTypes = require('./controlled-date-range-picker/ControlledDateRangePickerTypes.js');
@@ -13,14 +15,20 @@ var stringHelpers = require('./controlled-date-time-picker/utils/stringHelpers.j
13
15
  var dateTimeHelpers = require('./controlled-date-time-picker/utils/dateTimeHelpers.js');
14
16
  var dateHelpers = require('./controlled-date-time-picker/utils/dateHelpers.js');
15
17
  var timeHelpers = require('./controlled-date-time-picker/utils/timeHelpers.js');
18
+ var usePhoneMask = require('./controlled-mask-hook/hooks/usePhoneMask.js');
19
+ var DSInputText = require('./controlled-text-input/DSInputText.js');
20
+ var dataTestIds = require('./controlled-text-input/exported-related/data-test-ids.js');
21
+ var theming = require('./controlled-text-input/exported-related/theming.js');
16
22
  var ControlledToggle = require('./controlled-toggle/ControlledToggle.js');
17
- var Autocomplete = require('./controlled-autocomplete/Autocomplete.js');
18
- var ComboBox = require('./controlled-combobox/ComboBox.js');
19
23
 
20
24
 
21
25
 
26
+ exports.DSAutocomplete = Autocomplete.DSAutocomplete;
27
+ exports.DSAutocompleteWithSchema = Autocomplete.DSAutocompleteWithSchema;
22
28
  exports.DSControlledCheckbox = ControlledCheckbox.DSControlledCheckbox;
23
29
  exports.DSControlledCheckboxWithSchema = ControlledCheckbox.DSControlledCheckboxWithSchema;
30
+ exports.DSComboBox = ComboBox.DSComboBox;
31
+ exports.DSComboBoxWithSchema = ComboBox.DSComboBoxWithSchema;
24
32
  exports.DSControlledDateRangePicker = ControlledDateRangePicker.DSControlledDateRangePicker;
25
33
  exports.DSControlledDateRangePickerWithSchema = ControlledDateRangePicker.DSControlledDateRangePickerWithSchema;
26
34
  exports.ControlledDateRangePickerDatatestid = ControlledDateRangePickerDatatestid.ControlledDateRangePickerDatatestid;
@@ -37,9 +45,12 @@ exports.getDateValuesFromDate = dateHelpers.getDateValuesFromDate;
37
45
  exports.getDayFromDateString = dateHelpers.getDayFromDateString;
38
46
  exports.getValidationDateStringMetaInfo = dateHelpers.getValidationDateStringMetaInfo;
39
47
  exports.getValidationTimeStringMetaInfo = timeHelpers.getValidationTimeStringMetaInfo;
48
+ exports.UsePhoneMaskWithSchema = usePhoneMask.UsePhoneMaskWithSchema;
49
+ exports.usePhoneMask = usePhoneMask.usePhoneMask;
50
+ exports.DSInputText = DSInputText.DSInputText;
51
+ exports.DSInputTextWithSchema = DSInputText.DSInputTextWithSchema;
52
+ exports.DSInputTextDataTestIds = dataTestIds.DSInputTextDataTestIds;
53
+ exports.DSInputTextName = theming.DSInputTextName;
54
+ exports.DSInputTextSlots = theming.DSInputTextSlots;
40
55
  exports.DSControlledToggle = ControlledToggle.DSControlledToggle;
41
56
  exports.DSControlledToggleWithSchema = ControlledToggle.DSControlledToggleWithSchema;
42
- exports.DSAutocomplete = Autocomplete.DSAutocomplete;
43
- exports.DSAutocompleteWithSchema = Autocomplete.DSAutocompleteWithSchema;
44
- exports.DSComboBox = ComboBox.DSComboBox;
45
- exports.DSComboBoxWithSchema = ComboBox.DSComboBoxWithSchema;
@@ -0,0 +1 @@
1
+ export { UsePhoneMaskWithSchema, usePhoneMask } from './usePhoneMask.js';
@@ -0,0 +1,67 @@
1
+ import 'core-js/modules/esnext.async-iterator.filter.js';
2
+ import 'core-js/modules/esnext.iterator.constructor.js';
3
+ import 'core-js/modules/esnext.iterator.filter.js';
4
+ import 'core-js/modules/web.dom-collections.iterator.js';
5
+ import { useRef, useState, useCallback } from 'react';
6
+ import { describe, useMemoMergePropsWithDefault, useValidateTypescriptPropTypes } from '@elliemae/ds-props-helpers';
7
+ import { useCallbackAfterRender } from '@elliemae/ds-utilities';
8
+ import { addSpecialCharacters } from '../utils/addSpecialCharacters.js';
9
+ import { getPartialMaskedPos } from '../utils/getPartialMaskedPos.js';
10
+ import { setCursorPosition } from '../utils/setCursorPosition.js';
11
+ import { DSMaskHookPropsTypes, DSMaskHookDefaultProps } from '../react-desc-prop-types.js';
12
+
13
+ const phoneSpecialChars = [['(', 0], [') ', 4], ['-', 9]];
14
+
15
+ const conformValue = (rawValue, cursorPos, lastKeyCode) => {
16
+ // Work with digits only
17
+ let maskedValue = rawValue.split('').filter(char => char >= '0' && char <= '9'); // We can't have zeros at the start of the array
18
+
19
+ while (maskedValue.length && maskedValue[0] === '0') maskedValue.splice(0, 1); // We only consider first 10 digits
20
+
21
+
22
+ maskedValue = maskedValue.slice(0, 10);
23
+ const maskedPos = getPartialMaskedPos(rawValue, maskedValue, cursorPos);
24
+ return addSpecialCharacters(maskedValue, phoneSpecialChars, maskedPos, lastKeyCode);
25
+ };
26
+
27
+ const usePhoneMask = props => {
28
+ const propsWithDefault = useMemoMergePropsWithDefault(props, DSMaskHookDefaultProps);
29
+ useValidateTypescriptPropTypes(propsWithDefault, DSMaskHookPropsTypes);
30
+ const {
31
+ valueSetter,
32
+ onChange: userOnChange,
33
+ onKeyDown: userOnKeyDown
34
+ } = propsWithDefault;
35
+ const lastKeyCode = useRef('Unidentified');
36
+ const scheduleAfterRender = useCallbackAfterRender(); // Some times, the value of the mask is not gonna change (user types invalid char for example)
37
+ // This makes the input to go from "correct" -> "incorrect" -> "correct"
38
+ // But since the input is controlled, the input does not re-render
39
+ // This makes the input go mumbo-jumbo and places the cursor in the end, because we kinda changed the value async
40
+ // Solution for this is to trigger a re-render, we do this with a set state call in the on change event
41
+
42
+ const [, setKey] = useState(0);
43
+ const onKeyDown = useCallback(e => {
44
+ lastKeyCode.current = e.code;
45
+ if (userOnKeyDown) userOnKeyDown(e);
46
+ }, [userOnKeyDown]);
47
+ const onChange = useCallback(e => {
48
+ var _e$target$selectionEn;
49
+
50
+ const [mask, cursorPos] = conformValue(e.target.value, (_e$target$selectionEn = e.target.selectionEnd) !== null && _e$target$selectionEn !== void 0 ? _e$target$selectionEn : 0, lastKeyCode.current);
51
+ valueSetter(prevMask => {
52
+ // Here we need to update the key
53
+ if (mask === prevMask) setKey(key => key + 1);
54
+ return mask;
55
+ });
56
+ if (userOnChange) userOnChange(e, mask);
57
+ scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));
58
+ }, [valueSetter, scheduleAfterRender, userOnChange]);
59
+ return {
60
+ onKeyDown,
61
+ onChange
62
+ };
63
+ };
64
+ const UsePhoneMaskWithSchema = describe(usePhoneMask);
65
+ UsePhoneMaskWithSchema.propTypes = DSMaskHookPropsTypes;
66
+
67
+ export { UsePhoneMaskWithSchema, usePhoneMask };