@pingux/astro 2.208.4-alpha.0 → 2.209.0-alpha.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.
Files changed (29) hide show
  1. package/lib/cjs/components/PhoneNumberField/PhoneNumberField.d.ts +4 -0
  2. package/lib/cjs/components/PhoneNumberField/PhoneNumberField.js +299 -0
  3. package/lib/cjs/components/PhoneNumberField/PhoneNumberField.mdx +32 -0
  4. package/lib/cjs/components/PhoneNumberField/PhoneNumberField.stories.js +136 -0
  5. package/lib/cjs/components/PhoneNumberField/PhoneNumberField.test.js +158 -0
  6. package/lib/cjs/components/PhoneNumberField/index.d.ts +1 -0
  7. package/lib/cjs/components/PhoneNumberField/index.js +14 -0
  8. package/lib/cjs/index.d.ts +2 -0
  9. package/lib/cjs/index.js +56 -37
  10. package/lib/cjs/styles/themes/next-gen/convertedComponentList.js +1 -1
  11. package/lib/cjs/types/index.d.ts +1 -0
  12. package/lib/cjs/types/index.js +32 -21
  13. package/lib/cjs/types/phoneNumberField.d.ts +45 -0
  14. package/lib/cjs/types/phoneNumberField.js +6 -0
  15. package/lib/cjs/utils/designUtils/figmaLinks.d.ts +3 -0
  16. package/lib/cjs/utils/designUtils/figmaLinks.js +3 -0
  17. package/lib/cjs/utils/testUtils/universalFormSubmitTest.js +25 -11
  18. package/lib/components/PhoneNumberField/PhoneNumberField.js +288 -0
  19. package/lib/components/PhoneNumberField/PhoneNumberField.mdx +32 -0
  20. package/lib/components/PhoneNumberField/PhoneNumberField.stories.js +126 -0
  21. package/lib/components/PhoneNumberField/PhoneNumberField.test.js +155 -0
  22. package/lib/components/PhoneNumberField/index.js +1 -0
  23. package/lib/index.js +2 -0
  24. package/lib/styles/themes/next-gen/convertedComponentList.js +1 -1
  25. package/lib/types/index.js +1 -0
  26. package/lib/types/phoneNumberField.js +1 -0
  27. package/lib/utils/designUtils/figmaLinks.js +3 -0
  28. package/lib/utils/testUtils/universalFormSubmitTest.js +25 -11
  29. package/package.json +1 -1
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { PhoneNumberFieldProps } from '../../types';
3
+ declare const PhoneNumberField: React.ForwardRefExoticComponent<PhoneNumberFieldProps & React.RefAttributes<HTMLInputElement>>;
4
+ export default PhoneNumberField;
@@ -0,0 +1,299 @@
1
+ "use strict";
2
+
3
+ var _typeof = require("@babel/runtime-corejs3/helpers/typeof");
4
+ var _Object$keys = require("@babel/runtime-corejs3/core-js-stable/object/keys");
5
+ var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols");
6
+ var _filterInstanceProperty2 = require("@babel/runtime-corejs3/core-js-stable/instance/filter");
7
+ var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor");
8
+ var _forEachInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/for-each");
9
+ var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors");
10
+ var _Object$defineProperties = require("@babel/runtime-corejs3/core-js-stable/object/define-properties");
11
+ var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
12
+ var _WeakMap = require("@babel/runtime-corejs3/core-js-stable/weak-map");
13
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
14
+ _Object$defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ exports["default"] = void 0;
18
+ var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/extends"));
19
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
20
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/objectWithoutProperties"));
21
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray"));
22
+ var _entries = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/entries"));
23
+ var _startsWith = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/starts-with"));
24
+ var _trimStart = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/trim-start"));
25
+ var _find = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/find"));
26
+ var _slice = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/slice"));
27
+ var _filter = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/filter"));
28
+ var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat"));
29
+ var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));
30
+ var _react = _interopRequireWildcard(require("react"));
31
+ var _i18n = require("@react-aria/i18n");
32
+ var _countriesList = require("countries-list");
33
+ var _uuid = require("uuid");
34
+ var _ = require("../..");
35
+ var _hooks = require("../../hooks");
36
+ var _pendoID = require("../../utils/devUtils/constants/pendoID");
37
+ var _react2 = require("@emotion/react");
38
+ var _excluded = ["countryValue", "defaultCountryValue", "helperText", "isReadOnly", "labelMode", "onCountryChange", "status"];
39
+ function _interopRequireWildcard(e, t) { if ("function" == typeof _WeakMap) var r = new _WeakMap(), n = new _WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = _Object$defineProperty) && _Object$getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
40
+ function ownKeys(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty2(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
41
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context6, _context7; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context6 = ownKeys(Object(t), !0)).call(_context6, function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context7 = ownKeys(Object(t))).call(_context7, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
42
+ var displayName = 'PhoneNumberField';
43
+ var validatePhoneNumber = function validatePhoneNumber(str) {
44
+ return /^$|^\+\d*$|^\d+$/.test(str);
45
+ };
46
+ var allCountries = (0, _entries["default"])(_countriesList.countries);
47
+ var getCountry = function getCountry(key) {
48
+ return _countriesList.countries[key];
49
+ };
50
+ var primaryDial = function primaryDial(key) {
51
+ var _getCountry$phone$spl, _getCountry;
52
+ return (_getCountry$phone$spl = (_getCountry = getCountry(key)) === null || _getCountry === void 0 ? void 0 : _getCountry.phone.split(',')[0]) !== null && _getCountry$phone$spl !== void 0 ? _getCountry$phone$spl : '';
53
+ };
54
+ var toDialCode = function toDialCode(key) {
55
+ var dial = primaryDial(key);
56
+ return dial ? "+".concat(dial) : '';
57
+ };
58
+ var parsePaste = function parsePaste(raw) {
59
+ var _context;
60
+ var digitsOnly = raw.replace(/\D/g, '');
61
+ if ((0, _startsWith["default"])(_context = (0, _trimStart["default"])(raw).call(raw)).call(_context, '+')) {
62
+ var match = (0, _find["default"])(allCountries).call(allCountries, function (_ref) {
63
+ var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
64
+ c = _ref2[1];
65
+ return (0, _startsWith["default"])(digitsOnly).call(digitsOnly, c.phone.split(',')[0]);
66
+ });
67
+ if (match) {
68
+ var dialLen = match[1].phone.split(',')[0].length;
69
+ return {
70
+ countryKey: match[0],
71
+ localNumber: (0, _slice["default"])(digitsOnly).call(digitsOnly, dialLen)
72
+ };
73
+ }
74
+ }
75
+ return {
76
+ countryKey: null,
77
+ localNumber: digitsOnly
78
+ };
79
+ };
80
+ var closedState = function closedState(selectedKey) {
81
+ var dialCode = selectedKey ? toDialCode(selectedKey) : '';
82
+ return {
83
+ isOpen: false,
84
+ inputValue: dialCode,
85
+ searchValue: dialCode,
86
+ items: allCountries
87
+ };
88
+ };
89
+ var PhoneNumberField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
90
+ var countryValue = props.countryValue,
91
+ defaultCountryValue = props.defaultCountryValue,
92
+ helperText = props.helperText,
93
+ isReadOnly = props.isReadOnly,
94
+ labelMode = props.labelMode,
95
+ onCountryChange = props.onCountryChange,
96
+ status = props.status,
97
+ others = (0, _objectWithoutProperties2["default"])(props, _excluded);
98
+ var _useField = (0, _hooks.useField)(_objectSpread({
99
+ status: status,
100
+ isReadOnly: isReadOnly,
101
+ labelMode: labelMode
102
+ }, others)),
103
+ fieldContainerProps = _useField.fieldContainerProps,
104
+ fieldControlInputProps = _useField.fieldControlInputProps,
105
+ fieldControlWrapperProps = _useField.fieldControlWrapperProps,
106
+ fieldLabelProps = _useField.fieldLabelProps;
107
+ var onChange = fieldControlInputProps.onChange;
108
+ var inputRef = (0, _hooks.useLocalOrForwardRef)(ref);
109
+ var helperTextId = (0, _uuid.v4)();
110
+ (0, _hooks.usePropWarning)(props, 'disabled', 'isDisabled');
111
+ var _useFilter = (0, _i18n.useFilter)({
112
+ sensitivity: 'base'
113
+ }),
114
+ contains = _useFilter.contains;
115
+ var _useState = (0, _react.useState)(function () {
116
+ var key = countryValue !== null && countryValue !== void 0 ? countryValue : defaultCountryValue;
117
+ if (key && getCountry(key)) {
118
+ var dialCode = toDialCode(key);
119
+ return {
120
+ inputValue: dialCode,
121
+ selectedKey: key,
122
+ searchValue: dialCode,
123
+ items: allCountries,
124
+ isOpen: false
125
+ };
126
+ }
127
+ return {
128
+ inputValue: '',
129
+ selectedKey: null,
130
+ searchValue: '',
131
+ items: allCountries,
132
+ isOpen: false
133
+ };
134
+ }),
135
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
136
+ fieldState = _useState2[0],
137
+ setFieldState = _useState2[1];
138
+ var isControlledCountry = countryValue !== undefined;
139
+ var currentSelectedKey = isControlledCountry ? countryValue !== null && countryValue !== void 0 ? countryValue : null : fieldState.selectedKey;
140
+ var closedDisplayValue = isControlledCountry ? toDialCode(countryValue !== null && countryValue !== void 0 ? countryValue : '') : fieldState.inputValue;
141
+ var currentCountryInputValue = fieldState.isOpen ? fieldState.searchValue : closedDisplayValue;
142
+ var inputHandler = (0, _react.useCallback)(function (value) {
143
+ var search = value.toLowerCase();
144
+ var newItems = value ? (0, _filter["default"])(allCountries).call(allCountries, function (_ref3) {
145
+ var _context2;
146
+ var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2),
147
+ c = _ref4[1];
148
+ var nameStr = (0, _concat["default"])(_context2 = "".concat(c.name)).call(_context2, c.name !== c["native"] ? " (".concat(c["native"], ")") : '');
149
+ var dialStr = "+".concat(c.phone.split(',')[0]).toLowerCase();
150
+ return contains(nameStr, value) || (0, _includes["default"])(dialStr).call(dialStr, search);
151
+ }) : allCountries;
152
+ setFieldState(function (prev) {
153
+ return _objectSpread(_objectSpread({}, prev), {}, {
154
+ inputValue: value,
155
+ selectedKey: null,
156
+ searchValue: value,
157
+ items: newItems
158
+ });
159
+ });
160
+ }, [contains]);
161
+ var selectionHandler = (0, _react.useCallback)(function (key) {
162
+ if (!key) return;
163
+ var dialCode = toDialCode(key);
164
+ setFieldState({
165
+ inputValue: dialCode,
166
+ selectedKey: key,
167
+ searchValue: dialCode,
168
+ items: allCountries,
169
+ isOpen: false
170
+ });
171
+ if (onCountryChange) onCountryChange(key);
172
+ }, [onCountryChange]);
173
+ var onOpenChangeHandler = (0, _react.useCallback)(function (open) {
174
+ if (!open || isReadOnly) {
175
+ setFieldState(function (prev) {
176
+ return _objectSpread(_objectSpread({}, prev), closedState(prev.selectedKey));
177
+ });
178
+ } else {
179
+ setFieldState(function (prev) {
180
+ return _objectSpread(_objectSpread({}, prev), {}, {
181
+ isOpen: true,
182
+ items: allCountries
183
+ });
184
+ });
185
+ }
186
+ }, [isReadOnly]);
187
+ var handlePhoneChange = (0, _react.useCallback)(function (e) {
188
+ if (!onChange) return;
189
+ if (validatePhoneNumber(e.target.value)) {
190
+ onChange(e);
191
+ } else if (inputRef.current) {
192
+ inputRef.current.value = '';
193
+ }
194
+ }, [inputRef, onChange]);
195
+ var commitPaste = (0, _react.useCallback)(function (raw) {
196
+ if (!inputRef.current || !onChange) return;
197
+ var _parsePaste = parsePaste(raw),
198
+ countryKey = _parsePaste.countryKey,
199
+ localNumber = _parsePaste.localNumber;
200
+ if (countryKey) selectionHandler(countryKey);
201
+ inputRef.current.value = localNumber;
202
+ var event = {
203
+ target: inputRef.current,
204
+ currentTarget: inputRef.current
205
+ };
206
+ onChange(event);
207
+ }, [inputRef, onChange, selectionHandler]);
208
+ var handlePhonePaste = (0, _react.useCallback)(function (e) {
209
+ if (isReadOnly) return;
210
+ e.preventDefault();
211
+ commitPaste(e.clipboardData.getData('text'));
212
+ }, [isReadOnly, commitPaste]);
213
+ var handleComboBoxPaste = (0, _react.useCallback)(function (e) {
214
+ var _context3;
215
+ if (isReadOnly) return;
216
+ var raw = e.clipboardData.getData('text');
217
+ if (!(0, _startsWith["default"])(_context3 = (0, _trimStart["default"])(raw).call(raw)).call(_context3, '+')) return;
218
+ e.preventDefault();
219
+ commitPaste(raw);
220
+ }, [isReadOnly, commitPaste]);
221
+ var comboBoxWrapperSx = _objectSpread({
222
+ position: 'absolute',
223
+ zIndex: 1
224
+ }, fieldState.isOpen ? {
225
+ width: '100%'
226
+ } : {
227
+ transition: '0.2s width ease',
228
+ width: '110px'
229
+ });
230
+ var countryLabel = function countryLabel(c) {
231
+ var _context4, _context5;
232
+ return (0, _concat["default"])(_context4 = (0, _concat["default"])(_context5 = "".concat(c.name)).call(_context5, c.name !== c["native"] ? " (".concat(c["native"], ")") : '', " +")).call(_context4, c.phone.split(',')[0]);
233
+ };
234
+ return (0, _react2.jsx)(_.Box, (0, _extends2["default"])({
235
+ variant: "forms.input.fieldContainer"
236
+ }, (0, _pendoID.getPendoID)(displayName), fieldContainerProps), (0, _react2.jsx)(_.Label, fieldLabelProps), (0, _react2.jsx)(_.Box, (0, _extends2["default"])({
237
+ variant: "forms.input.fieldControlWrapper",
238
+ isRow: true
239
+ }, fieldControlWrapperProps, {
240
+ sx: {
241
+ position: 'relative'
242
+ }
243
+ }), (0, _react2.jsx)(_.ComboBoxField, {
244
+ width: "100%",
245
+ status: status,
246
+ isReadOnly: isReadOnly,
247
+ isOpen: fieldState.isOpen,
248
+ onOpenChange: onOpenChangeHandler,
249
+ wrapperProps: {
250
+ sx: comboBoxWrapperSx
251
+ },
252
+ controlProps: {
253
+ 'aria-label': 'Country Picker',
254
+ onPaste: handleComboBoxPaste
255
+ },
256
+ containerProps: {
257
+ sx: {
258
+ '> label': {
259
+ mb: 0
260
+ }
261
+ }
262
+ },
263
+ scrollBoxProps: {
264
+ maxHeight: '215px',
265
+ sx: {
266
+ minWidth: '280px'
267
+ }
268
+ },
269
+ items: fieldState.items,
270
+ inputValue: currentCountryInputValue,
271
+ selectedKey: currentSelectedKey,
272
+ onInputChange: inputHandler,
273
+ onSelectionChange: selectionHandler,
274
+ menuTrigger: "focus",
275
+ isDisabled: fieldControlInputProps.disabled
276
+ }, function (item) {
277
+ return (0, _react2.jsx)(_.Item, {
278
+ key: item[0],
279
+ textValue: "+".concat(item[1].phone.split(',')[0])
280
+ }, countryLabel(item[1]));
281
+ }), (0, _react2.jsx)(_.Box, {
282
+ sx: {
283
+ ml: '110px',
284
+ width: '100%',
285
+ visibility: fieldState.isOpen ? 'hidden' : undefined
286
+ }
287
+ }, (0, _react2.jsx)(_.Input, (0, _extends2["default"])({
288
+ ref: inputRef
289
+ }, fieldControlInputProps, {
290
+ "aria-describedby": [helperText && helperTextId, fieldControlInputProps['aria-describedby']].join(fieldControlInputProps['aria-describedby'] ? ' ' : '') || undefined,
291
+ onChange: handlePhoneChange,
292
+ onPaste: handlePhonePaste
293
+ })))), helperText && (0, _react2.jsx)(_.FieldHelperText, {
294
+ status: status,
295
+ id: helperTextId
296
+ }, helperText));
297
+ });
298
+ PhoneNumberField.displayName = displayName;
299
+ var _default = exports["default"] = PhoneNumberField;
@@ -0,0 +1,32 @@
1
+ import { Meta } from '@storybook/addon-docs/blocks';
2
+ import * as PhoneNumberFieldStories from './PhoneNumberField.stories';
3
+ import AccessibilityTable from '../../utils/docUtils/AccessibilityTable';
4
+ import { KeyboardRows } from '../../utils/docUtils/accessibilityTableConstants';
5
+
6
+ <Meta of={PhoneNumberFieldStories} isTemplate />
7
+
8
+ # PhoneNumberField
9
+
10
+ The PhoneNumberField component combines a country selector with a phone number input, providing a complete, form-ready solution for collecting international phone numbers. The country selector is an accessible combo box that filters all countries from the `countries-list` package, and the phone input validates that only numeric characters (with an optional leading `+`) are entered.
11
+
12
+ ### Required components
13
+
14
+ This component requires the following dependency to be present in the project:
15
+
16
+ - **`countries-list ^2.6.1`** — provides the full list of countries and their dial codes used to populate the country selector dropdown.
17
+
18
+ The `ComboBoxField` component (from the Astro design system) is used internally for the country selector. No additional external setup is needed beyond having `countries-list` installed.
19
+
20
+ ### Accessibility
21
+
22
+ <AccessibilityTable keyboardRows={[
23
+ { key: 'Tab', description: 'Moves focus between the country selector trigger and the phone number input, following the page tab sequence.' },
24
+ KeyboardRows.shiftTabFocusPrevious,
25
+ { key: 'Arrow Down / Arrow Up', description: 'When the country selector dropdown is open, moves focus through the list of countries.' },
26
+ { key: 'Enter', description: 'Selects the currently focused country in the dropdown and closes the selector.' },
27
+ { key: 'Escape', description: 'Closes the country selector dropdown without changing the selection.' },
28
+ ]} screenReaderRows={[
29
+ 'The phone number input uses the **`aria-labelledby`** attribute to reference the field label ID, associating the visible label with the input.',
30
+ 'The country selector combo box uses the **`aria-label`** attribute (value: `"Country Picker"`) to provide an accessible name for the combo box trigger, since its visible content is the dial code rather than a descriptive label.',
31
+ 'The **`aria-invalid`** attribute is set on the phone input when the field has an error status.',
32
+ ]} />
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+
3
+ var _typeof = require("@babel/runtime-corejs3/helpers/typeof");
4
+ var _Object$keys = require("@babel/runtime-corejs3/core-js-stable/object/keys");
5
+ var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols");
6
+ var _filterInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/filter");
7
+ var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor");
8
+ var _forEachInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/for-each");
9
+ var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors");
10
+ var _Object$defineProperties = require("@babel/runtime-corejs3/core-js-stable/object/define-properties");
11
+ var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
12
+ var _WeakMap = require("@babel/runtime-corejs3/core-js-stable/weak-map");
13
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
14
+ _Object$defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ exports["default"] = exports.WithHelpHint = exports.Warning = exports.Success = exports.Required = exports.ReadOnly = exports.Error = exports.Disabled = exports.Default = exports.Controlled = void 0;
18
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray"));
19
+ var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/extends"));
20
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
21
+ var _react = _interopRequireWildcard(require("react"));
22
+ var _storybookDocsLayout = _interopRequireDefault(require("../../../.storybook/storybookDocsLayout"));
23
+ var _index = require("../../index");
24
+ var _figmaLinks = require("../../utils/designUtils/figmaLinks");
25
+ var _ariaAttributes = require("../../utils/docUtils/ariaAttributes");
26
+ var _fieldAttributes = require("../../utils/docUtils/fieldAttributes");
27
+ var _statusProp = require("../../utils/docUtils/statusProp");
28
+ var _PhoneNumberField = _interopRequireDefault(require("./PhoneNumberField.mdx"));
29
+ var _react2 = require("@emotion/react");
30
+ function _interopRequireWildcard(e, t) { if ("function" == typeof _WeakMap) var r = new _WeakMap(), n = new _WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = _Object$defineProperty) && _Object$getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
31
+ function ownKeys(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
32
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context = ownKeys(Object(t), !0)).call(_context, function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context2 = ownKeys(Object(t))).call(_context2, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
33
+ var _default = exports["default"] = {
34
+ title: 'Form/PhoneNumberField',
35
+ component: _index.PhoneNumberField,
36
+ parameters: {
37
+ docs: {
38
+ page: function page() {
39
+ return (0, _react2.jsx)(_react["default"].Fragment, null, (0, _react2.jsx)(_PhoneNumberField["default"], null), (0, _react2.jsx)(_storybookDocsLayout["default"], null));
40
+ }
41
+ }
42
+ },
43
+ argTypes: _objectSpread(_objectSpread(_objectSpread({}, _statusProp.statusArgTypes), _ariaAttributes.ariaAttributeBaseArgTypes), _fieldAttributes.inputFieldAttributeBaseArgTypes)
44
+ };
45
+ var Default = exports.Default = function Default(args) {
46
+ return (0, _react2.jsx)(_index.PhoneNumberField, (0, _extends2["default"])({
47
+ label: "Phone Number"
48
+ }, args));
49
+ };
50
+ Default.parameters = {
51
+ design: {
52
+ type: 'figma',
53
+ url: _figmaLinks.FIGMA_LINKS.phoneNumberField["default"]
54
+ }
55
+ };
56
+ var Controlled = exports.Controlled = function Controlled() {
57
+ var _useState = (0, _react.useState)(''),
58
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
59
+ value = _useState2[0],
60
+ setValue = _useState2[1];
61
+ var _useState3 = (0, _react.useState)(undefined),
62
+ _useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
63
+ countryValue = _useState4[0],
64
+ setCountryValue = _useState4[1];
65
+ return (0, _react2.jsx)(_index.PhoneNumberField, {
66
+ label: "Phone Number",
67
+ value: value,
68
+ onChange: function onChange(e) {
69
+ return setValue(e.target.value);
70
+ },
71
+ countryValue: countryValue,
72
+ onCountryChange: function onCountryChange(key) {
73
+ return setCountryValue(key);
74
+ }
75
+ });
76
+ };
77
+ var Disabled = exports.Disabled = function Disabled(args) {
78
+ return (0, _react2.jsx)(_index.PhoneNumberField, (0, _extends2["default"])({
79
+ label: "Phone Number",
80
+ isDisabled: true
81
+ }, args));
82
+ };
83
+ var ReadOnly = exports.ReadOnly = function ReadOnly(args) {
84
+ return (0, _react2.jsx)(_index.PhoneNumberField, (0, _extends2["default"])({
85
+ label: "Phone Number",
86
+ isReadOnly: true,
87
+ defaultCountryValue: "US",
88
+ value: "2025550177"
89
+ }, args));
90
+ };
91
+ var Required = exports.Required = function Required(args) {
92
+ return (0, _react2.jsx)(_index.PhoneNumberField, (0, _extends2["default"])({
93
+ label: "Phone Number",
94
+ isRequired: true
95
+ }, args));
96
+ };
97
+ var Error = exports.Error = function Error(args) {
98
+ return (0, _react2.jsx)(_index.PhoneNumberField, (0, _extends2["default"])({
99
+ label: "Phone Number",
100
+ status: "error",
101
+ helperText: "Please enter a valid phone number."
102
+ }, args));
103
+ };
104
+ var Warning = exports.Warning = function Warning(args) {
105
+ return (0, _react2.jsx)(_index.PhoneNumberField, (0, _extends2["default"])({
106
+ label: "Phone Number",
107
+ status: "warning",
108
+ helperText: "Double-check the country code."
109
+ }, args));
110
+ };
111
+ Warning.parameters = {
112
+ a11y: {
113
+ config: {
114
+ rules: [{
115
+ id: 'color-contrast',
116
+ enabled: false
117
+ }]
118
+ }
119
+ }
120
+ };
121
+ var Success = exports.Success = function Success(args) {
122
+ return (0, _react2.jsx)(_index.PhoneNumberField, (0, _extends2["default"])({
123
+ label: "Phone Number",
124
+ status: "success",
125
+ helperText: "Phone number verified."
126
+ }, args));
127
+ };
128
+ var WithHelpHint = exports.WithHelpHint = function WithHelpHint(args) {
129
+ return (0, _react2.jsx)(_index.PhoneNumberField, (0, _extends2["default"])({
130
+ label: "Phone Number",
131
+ hintText: "Include country code for international numbers.",
132
+ helpHintProps: {
133
+ direction: 'right'
134
+ }
135
+ }, args));
136
+ };
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
4
+ var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/extends"));
5
+ var _react = _interopRequireDefault(require("react"));
6
+ var _react2 = require("@testing-library/react");
7
+ var _universalComponentTest = require("../../utils/testUtils/universalComponentTest");
8
+ var _universalFormSubmitTest = require("../../utils/testUtils/universalFormSubmitTest");
9
+ var _ = _interopRequireDefault(require("."));
10
+ var _react3 = require("@emotion/react");
11
+ var testId = 'test-phone-number-field';
12
+ var testLabel = 'Test Label';
13
+ var defaultProps = {
14
+ 'data-testid': testId,
15
+ label: testLabel
16
+ };
17
+ var getComponent = function getComponent() {
18
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
19
+ return (0, _react2.render)((0, _react3.jsx)(_["default"], (0, _extends2["default"])({}, defaultProps, props)));
20
+ };
21
+ (0, _universalFormSubmitTest.universalFieldComponentTests)({
22
+ renderComponent: function renderComponent(props) {
23
+ return (0, _react3.jsx)(_["default"], (0, _extends2["default"])({}, defaultProps, props));
24
+ },
25
+ testValue: '+12345678',
26
+ testLabel: testLabel,
27
+ componentType: 'PhoneNumberField'
28
+ });
29
+ (0, _universalComponentTest.universalComponentTests)({
30
+ renderComponent: function renderComponent(props) {
31
+ return (0, _react3.jsx)(_["default"], (0, _extends2["default"])({}, defaultProps, props));
32
+ }
33
+ });
34
+ afterEach(function () {
35
+ jest.clearAllMocks();
36
+ });
37
+ test('default render has label, phone input, and country combobox', function () {
38
+ getComponent();
39
+ expect(_react2.screen.getByTestId(testId)).toBeInTheDocument();
40
+ expect(_react2.screen.getByText(testLabel)).toBeInstanceOf(HTMLLabelElement);
41
+ expect(_react2.screen.getByRole('textbox')).toBeInTheDocument();
42
+ expect(_react2.screen.getByRole('combobox')).toBeInTheDocument();
43
+ });
44
+ test('typing a non-numeric character does not update phone input value', function () {
45
+ getComponent();
46
+ var phoneInput = _react2.screen.getByRole('textbox');
47
+ _react2.fireEvent.change(phoneInput, {
48
+ target: {
49
+ value: 'a'
50
+ }
51
+ });
52
+ expect(phoneInput).toHaveValue('');
53
+ });
54
+ test('typing a "+" character is accepted', function () {
55
+ getComponent();
56
+ var phoneInput = _react2.screen.getByRole('textbox');
57
+ _react2.fireEvent.change(phoneInput, {
58
+ target: {
59
+ value: '+'
60
+ }
61
+ });
62
+ expect(phoneInput).toHaveValue('+');
63
+ });
64
+ test('typing "+" followed by digits is valid', function () {
65
+ getComponent();
66
+ var phoneInput = _react2.screen.getByRole('textbox');
67
+ _react2.fireEvent.change(phoneInput, {
68
+ target: {
69
+ value: '+123'
70
+ }
71
+ });
72
+ expect(phoneInput).toHaveValue('+123');
73
+ });
74
+ test('typing "+" followed by a letter is not accepted', function () {
75
+ getComponent();
76
+ var phoneInput = _react2.screen.getByRole('textbox');
77
+ _react2.fireEvent.change(phoneInput, {
78
+ target: {
79
+ value: '+a'
80
+ }
81
+ });
82
+ expect(phoneInput).toHaveValue('');
83
+ });
84
+ test('pasting a string with spaces and dashes strips non-numeric characters and dial code', function () {
85
+ getComponent();
86
+ var phoneInput = _react2.screen.getByRole('textbox');
87
+ var pasteEvent = _react2.createEvent.paste(phoneInput, {
88
+ clipboardData: {
89
+ getData: function getData() {
90
+ return '+1 (800) 555-1234';
91
+ }
92
+ }
93
+ });
94
+ (0, _react2.fireEvent)(phoneInput, pasteEvent);
95
+ expect(phoneInput).toHaveValue('8005551234');
96
+ });
97
+ test('pasting a string without leading "+" strips all non-numeric characters', function () {
98
+ getComponent();
99
+ var phoneInput = _react2.screen.getByRole('textbox');
100
+ var pasteEvent = _react2.createEvent.paste(phoneInput, {
101
+ clipboardData: {
102
+ getData: function getData() {
103
+ return '800-555-1234';
104
+ }
105
+ }
106
+ });
107
+ (0, _react2.fireEvent)(phoneInput, pasteEvent);
108
+ expect(phoneInput).toHaveValue('8005551234');
109
+ });
110
+ test('onChange callback is called with a valid phone number change', function () {
111
+ var onChange = jest.fn();
112
+ getComponent({
113
+ onChange: onChange
114
+ });
115
+ var phoneInput = _react2.screen.getByRole('textbox');
116
+ _react2.fireEvent.change(phoneInput, {
117
+ target: {
118
+ value: '+12345678'
119
+ }
120
+ });
121
+ expect(onChange).toHaveBeenCalled();
122
+ });
123
+ test('onChange callback is not called when an invalid character is typed', function () {
124
+ var onChange = jest.fn();
125
+ getComponent({
126
+ onChange: onChange
127
+ });
128
+ var phoneInput = _react2.screen.getByRole('textbox');
129
+ _react2.fireEvent.change(phoneInput, {
130
+ target: {
131
+ value: 'abc'
132
+ }
133
+ });
134
+ expect(onChange).not.toHaveBeenCalled();
135
+ });
136
+ test('isDisabled disables the phone input', function () {
137
+ getComponent({
138
+ isDisabled: true
139
+ });
140
+ var phoneInput = _react2.screen.getByRole('textbox');
141
+ expect(phoneInput).toBeDisabled();
142
+ });
143
+ test('helperText renders FieldHelperText content', function () {
144
+ var helperText = 'Enter your phone number';
145
+ getComponent({
146
+ helperText: helperText
147
+ });
148
+ expect(_react2.screen.getByText(helperText)).toBeInTheDocument();
149
+ });
150
+ test('controlled countryValue sets initial selected country', function () {
151
+ getComponent({
152
+ countryValue: 'US'
153
+ });
154
+ var phoneInput = _react2.screen.getByRole('textbox');
155
+ expect(phoneInput).toBeInTheDocument();
156
+ // The combobox should be present and the phone input available
157
+ expect(_react2.screen.getByRole('combobox')).toBeInTheDocument();
158
+ });
@@ -0,0 +1 @@
1
+ export { default } from './PhoneNumberField';
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
4
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
5
+ _Object$defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ _Object$defineProperty(exports, "default", {
9
+ enumerable: true,
10
+ get: function get() {
11
+ return _PhoneNumberField["default"];
12
+ }
13
+ });
14
+ var _PhoneNumberField = _interopRequireDefault(require("./PhoneNumberField"));
@@ -148,6 +148,8 @@ export { default as PanelHeaderMenu } from './components/PanelHeader/controls/Pa
148
148
  export { default as PanelHeaderSwitchField } from './components/PanelHeader/controls/PanelHeaderSwitchField';
149
149
  export { default as PasswordField } from './components/PasswordField';
150
150
  export * from './components/PasswordField';
151
+ export { default as PhoneNumberField } from './components/PhoneNumberField';
152
+ export * from './components/PhoneNumberField';
151
153
  export { default as PopoverContainer } from './components/PopoverContainer';
152
154
  export * from './components/PopoverContainer';
153
155
  export { default as PopoverMenu } from './components/PopoverMenu';