@financial-times/n-conversion-forms 40.0.2 → 41.0.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/.toolkitstate/ci.json +3 -3
- package/.toolkitstate/install.json +1 -1
- package/README.md +29 -2
- package/components/index.js +1 -2
- package/components/region-selector.jsx +99 -0
- package/components/region-selector.spec.js +121 -0
- package/components/region-selector.stories.js +84 -0
- package/dist/index.js +3 -10
- package/dist/{province.jsx → region-selector.jsx} +39 -31
- package/package.json +2 -2
- package/utils/region-selector.js +54 -0
- package/components/__snapshots__/province.spec.js.snap +0 -354
- package/components/__snapshots__/state.spec.js.snap +0 -924
- package/components/province.jsx +0 -84
- package/components/province.spec.js +0 -96
- package/components/province.stories.js +0 -21
- package/components/state.jsx +0 -83
- package/components/state.spec.js +0 -96
- package/components/state.stories.js +0 -25
- package/dist/state.jsx +0 -80
- package/utils/province.js +0 -9
- package/utils/state.js +0 -9
package/.toolkitstate/ci.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
".toolkitrc.yml": "XiiIocllEaT8xqKRCTpTbJ+yUyduDo5aEHARUQ3vJFfSe187Ci13PEs3bWL272GFJyNz2QgRQhdov2/+LFRKuw==",
|
|
3
|
-
"package.json": "
|
|
3
|
+
"package.json": "Q++D0RhTdwacN2+LL5eQZaV5Ck5QP637EEpW6f9Mu8Jk/PXaa11O1cCs+/TUvXxCrvDVSbepecfSkDoRv/oXzg==",
|
|
4
4
|
".circleci/config.yml": "eph42EF3EsL7jvhiiC7D7vG3vGBAGBFVC+Ncmy4Dj4rUNzK8Rls0/cr+bEF/ttMN3J6iSL1xtCXKIJVrtZ4OSQ=="
|
|
5
5
|
}
|
package/README.md
CHANGED
|
@@ -57,8 +57,9 @@ import MyModule from 'n-conversion-forms/utils/my-module';
|
|
|
57
57
|
- [Event Notifier](#event-notifier)
|
|
58
58
|
- [Loader](#loader)
|
|
59
59
|
- [Password](#password)
|
|
60
|
-
- [Payment Term](#
|
|
61
|
-
- [Payment Type](#
|
|
60
|
+
- [Payment Term](#paymentTerm)
|
|
61
|
+
- [Payment Type](#paymentType)
|
|
62
|
+
- [Region Selector](#regionSelector)
|
|
62
63
|
- [Salesforce](#salesforce)
|
|
63
64
|
- [Submit](#submit)
|
|
64
65
|
- [Tracking](#tracking)
|
|
@@ -262,6 +263,32 @@ PaymentType.PAYPAL;
|
|
|
262
263
|
PaymentType.APPLEPAY;
|
|
263
264
|
```
|
|
264
265
|
|
|
266
|
+
### RegionSelector
|
|
267
|
+
|
|
268
|
+
The `RegionSelector` utility provides a form element for selecting regions (states, provinces, etc.) based on the selected country. It supports dynamic naming and labeling based on the provided options.
|
|
269
|
+
|
|
270
|
+
> **Note**: Ensure that the `country`, `regionType`, and `fieldId` used here match what is used in the props for the `RegionSelector` component in `region-selector.jsx`.
|
|
271
|
+
|
|
272
|
+
#### Usage
|
|
273
|
+
|
|
274
|
+
```js
|
|
275
|
+
// Using default options
|
|
276
|
+
const regionSelector = new RegionSelector(document, { country: 'CAN' });
|
|
277
|
+
|
|
278
|
+
// Using custom options
|
|
279
|
+
const customRegionSelector = new RegionSelector(document, {
|
|
280
|
+
country: 'IND',
|
|
281
|
+
regionType: 'customRegionType',
|
|
282
|
+
fieldId: 'customFieldId',
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Example of util functions
|
|
286
|
+
regionSelector.hide();
|
|
287
|
+
regionSelector.show();
|
|
288
|
+
regionSelector.disable();
|
|
289
|
+
regionSelector.enable();
|
|
290
|
+
```
|
|
291
|
+
|
|
265
292
|
### Salesforce
|
|
266
293
|
|
|
267
294
|
Utility for converting salesforce country names to ISO country codes.
|
package/components/index.js
CHANGED
|
@@ -46,11 +46,10 @@ export { PaymentType } from './payment-type';
|
|
|
46
46
|
export { Phone } from './phone';
|
|
47
47
|
export { Position } from './position';
|
|
48
48
|
export { ProgressIndicator } from './progress-indicator';
|
|
49
|
-
export {
|
|
49
|
+
export { RegionSelector } from './region-selector';
|
|
50
50
|
export { RegistrationConfirmation } from './registration-confirmation';
|
|
51
51
|
export { Responsibility } from './responsibility';
|
|
52
52
|
export { Section } from './section';
|
|
53
|
-
export { State } from './state';
|
|
54
53
|
export { Submit } from './submit';
|
|
55
54
|
export { TrialBanner } from './trial-banner';
|
|
56
55
|
export { EducationJobTitle } from './education-job-title';
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
|
|
5
|
+
import { configByCountry } from '../utils/region-selector';
|
|
6
|
+
|
|
7
|
+
export function RegionSelector({
|
|
8
|
+
country = 'USA',
|
|
9
|
+
fieldId,
|
|
10
|
+
hasError = false,
|
|
11
|
+
isBillingSelector = false,
|
|
12
|
+
isDisabled = false,
|
|
13
|
+
isHidden = false,
|
|
14
|
+
label,
|
|
15
|
+
regionType,
|
|
16
|
+
selectId,
|
|
17
|
+
value,
|
|
18
|
+
}) {
|
|
19
|
+
const {
|
|
20
|
+
regions = [],
|
|
21
|
+
defaultRegionType,
|
|
22
|
+
label: defaultLabel,
|
|
23
|
+
} = configByCountry[country];
|
|
24
|
+
|
|
25
|
+
const dynamicRegionType = regionType || defaultRegionType;
|
|
26
|
+
const dynamicLabel = isBillingSelector
|
|
27
|
+
? `Billing ${label || defaultLabel}`
|
|
28
|
+
: label || defaultLabel;
|
|
29
|
+
const dynamicFieldId = fieldId || `${dynamicRegionType}Field`;
|
|
30
|
+
const dynamicSelectId = selectId || dynamicRegionType;
|
|
31
|
+
|
|
32
|
+
const dynamicName = isBillingSelector
|
|
33
|
+
? `billing${
|
|
34
|
+
dynamicRegionType.charAt(0).toUpperCase() + dynamicRegionType.slice(1)
|
|
35
|
+
}`
|
|
36
|
+
: dynamicRegionType;
|
|
37
|
+
|
|
38
|
+
const fieldClassNames = classNames([
|
|
39
|
+
'o-forms-field',
|
|
40
|
+
{ ncf__hidden: isHidden },
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
const inputWrapperClassNames = classNames([
|
|
44
|
+
'o-forms-input',
|
|
45
|
+
'o-forms-input--select',
|
|
46
|
+
{ 'o-forms-input--invalid': hasError },
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<label
|
|
51
|
+
id={dynamicFieldId}
|
|
52
|
+
className={fieldClassNames}
|
|
53
|
+
data-validate="required"
|
|
54
|
+
htmlFor={dynamicSelectId}
|
|
55
|
+
>
|
|
56
|
+
<span className="o-forms-title">
|
|
57
|
+
<span className="o-forms-title__main">{dynamicLabel}</span>
|
|
58
|
+
</span>
|
|
59
|
+
<span className={inputWrapperClassNames}>
|
|
60
|
+
<select
|
|
61
|
+
id={selectId}
|
|
62
|
+
aria-required="true"
|
|
63
|
+
required
|
|
64
|
+
name={dynamicName}
|
|
65
|
+
data-trackable={`field-${dynamicRegionType}`}
|
|
66
|
+
disabled={isDisabled}
|
|
67
|
+
defaultValue={value}
|
|
68
|
+
>
|
|
69
|
+
<option disabled value="">
|
|
70
|
+
Please select a {defaultLabel.toLowerCase()}
|
|
71
|
+
</option>
|
|
72
|
+
{regions.map(({ code, name }) => {
|
|
73
|
+
return (
|
|
74
|
+
<option key={code} value={code}>
|
|
75
|
+
{name}
|
|
76
|
+
</option>
|
|
77
|
+
);
|
|
78
|
+
})}
|
|
79
|
+
</select>
|
|
80
|
+
<span className="o-forms-input__error">
|
|
81
|
+
Please select your {defaultLabel.toLowerCase()}
|
|
82
|
+
</span>
|
|
83
|
+
</span>
|
|
84
|
+
</label>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
RegionSelector.propTypes = {
|
|
89
|
+
country: PropTypes.oneOf(['USA', 'CAN', 'IND']),
|
|
90
|
+
fieldId: PropTypes.string,
|
|
91
|
+
hasError: PropTypes.bool,
|
|
92
|
+
isBillingSelector: PropTypes.bool,
|
|
93
|
+
isDisabled: PropTypes.bool,
|
|
94
|
+
isHidden: PropTypes.bool,
|
|
95
|
+
label: PropTypes.string,
|
|
96
|
+
regionType: PropTypes.string,
|
|
97
|
+
selectId: PropTypes.string,
|
|
98
|
+
value: PropTypes.string,
|
|
99
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { RegionSelector } from './region-selector';
|
|
3
|
+
import Enzyme, { mount } from 'enzyme';
|
|
4
|
+
import Adapter from 'enzyme-adapter-react-16';
|
|
5
|
+
Enzyme.configure({ adapter: new Adapter() });
|
|
6
|
+
|
|
7
|
+
describe('RegionSelector', () => {
|
|
8
|
+
it('renders a select with a label', () => {
|
|
9
|
+
const props = {
|
|
10
|
+
country: 'USA',
|
|
11
|
+
};
|
|
12
|
+
const component = mount(<RegionSelector {...props} />);
|
|
13
|
+
expect(component.find('label').exists()).toBe(true);
|
|
14
|
+
expect(component.find('select').exists()).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('renders the correct label based on country and isBillingSelector', () => {
|
|
18
|
+
const props = {
|
|
19
|
+
country: 'CAN',
|
|
20
|
+
isBillingSelector: true,
|
|
21
|
+
};
|
|
22
|
+
const component = mount(<RegionSelector {...props} />);
|
|
23
|
+
expect(component.find('label').text()).toContain('Billing Province');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('can render an initial selected value', () => {
|
|
27
|
+
const props = {
|
|
28
|
+
country: 'USA',
|
|
29
|
+
value: 'AR',
|
|
30
|
+
};
|
|
31
|
+
const component = mount(<RegionSelector {...props} />);
|
|
32
|
+
expect(component.find('select').prop('defaultValue')).toBe('AR');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('can render a disabled select', () => {
|
|
36
|
+
const props = {
|
|
37
|
+
country: 'USA',
|
|
38
|
+
isDisabled: true,
|
|
39
|
+
};
|
|
40
|
+
const component = mount(<RegionSelector {...props} />);
|
|
41
|
+
expect(component.find('select').prop('disabled')).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('can render an error state', () => {
|
|
45
|
+
const props = {
|
|
46
|
+
country: 'USA',
|
|
47
|
+
hasError: true,
|
|
48
|
+
};
|
|
49
|
+
const component = mount(<RegionSelector {...props} />);
|
|
50
|
+
expect(component.find('.o-forms-input--invalid').exists()).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('can hide the component', () => {
|
|
54
|
+
const props = {
|
|
55
|
+
country: 'USA',
|
|
56
|
+
isHidden: true,
|
|
57
|
+
};
|
|
58
|
+
const component = mount(<RegionSelector {...props} />);
|
|
59
|
+
expect(component.find('.ncf__hidden').exists()).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('can override id for field', () => {
|
|
63
|
+
const props = {
|
|
64
|
+
country: 'USA',
|
|
65
|
+
fieldId: 'customFieldId',
|
|
66
|
+
};
|
|
67
|
+
const component = mount(<RegionSelector {...props} />);
|
|
68
|
+
expect(component.find('#customFieldId').exists()).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('can override id for select', () => {
|
|
72
|
+
const props = {
|
|
73
|
+
country: 'USA',
|
|
74
|
+
selectId: 'customSelectId',
|
|
75
|
+
};
|
|
76
|
+
const component = mount(<RegionSelector {...props} />);
|
|
77
|
+
expect(component.find('select#customSelectId').exists()).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('applies context-specific name if is billing state', () => {
|
|
81
|
+
const props = {
|
|
82
|
+
country: 'USA',
|
|
83
|
+
isBillingSelector: true,
|
|
84
|
+
};
|
|
85
|
+
const component = mount(<RegionSelector {...props} />);
|
|
86
|
+
expect(component.find('select').prop('name')).toBe('billingState');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('applies context-specific name if is not billing state', () => {
|
|
90
|
+
const props = {
|
|
91
|
+
country: 'USA',
|
|
92
|
+
isBillingSelector: false,
|
|
93
|
+
};
|
|
94
|
+
const component = mount(<RegionSelector {...props} />);
|
|
95
|
+
expect(component.find('select').prop('name')).toBe('state');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('renders the correct label for USA', () => {
|
|
99
|
+
const props = {
|
|
100
|
+
country: 'USA',
|
|
101
|
+
};
|
|
102
|
+
const component = mount(<RegionSelector {...props} />);
|
|
103
|
+
expect(component.find('label').text()).toContain('State');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('renders the correct label for CAN', () => {
|
|
107
|
+
const props = {
|
|
108
|
+
country: 'CAN',
|
|
109
|
+
};
|
|
110
|
+
const component = mount(<RegionSelector {...props} />);
|
|
111
|
+
expect(component.find('label').text()).toContain('Province');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('renders the correct label for IND', () => {
|
|
115
|
+
const props = {
|
|
116
|
+
country: 'IND',
|
|
117
|
+
};
|
|
118
|
+
const component = mount(<RegionSelector {...props} />);
|
|
119
|
+
expect(component.find('label').text()).toContain('State/Union Territory');
|
|
120
|
+
});
|
|
121
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { RegionSelector } from './region-selector';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Region Selector',
|
|
6
|
+
component: RegionSelector,
|
|
7
|
+
argTypes: {
|
|
8
|
+
country: { control: 'radio', options: ['USA', 'CAN', 'IND'] },
|
|
9
|
+
hasError: { control: 'boolean' },
|
|
10
|
+
isHidden: { control: 'boolean' },
|
|
11
|
+
isBillingSelector: { control: 'boolean' },
|
|
12
|
+
isDisabled: { control: 'boolean' },
|
|
13
|
+
region: { control: 'text' },
|
|
14
|
+
fieldId: { control: 'text' },
|
|
15
|
+
selectId: { control: 'text' },
|
|
16
|
+
label: { control: 'text' },
|
|
17
|
+
value: { control: 'text' },
|
|
18
|
+
},
|
|
19
|
+
parameters: {
|
|
20
|
+
docs: {
|
|
21
|
+
description: {
|
|
22
|
+
component: `
|
|
23
|
+
The \`RegionSelector\` component is used to select regions (states, provinces, etc.) based on the selected country. It supports dynamic naming and labeling based on the provided props.
|
|
24
|
+
|
|
25
|
+
### Props
|
|
26
|
+
- **country**: The country code (e.g., 'USA', 'CAN', 'IND') to determine the list of regions.
|
|
27
|
+
- **value**: The selected value for the region.
|
|
28
|
+
- **fieldId**: Custom ID for the field label. If not provided, it defaults to \`\${region}Field\`.
|
|
29
|
+
- **selectId**: Custom ID for the select element. If not provided, it defaults to \`region\`.
|
|
30
|
+
- **label**: Custom label for the field. If not provided, it defaults to the region label based on the country.
|
|
31
|
+
- **hasError**: Boolean to indicate if the field has an error.
|
|
32
|
+
- **isHidden**: Boolean to indicate if the field should be hidden.
|
|
33
|
+
- **isBillingState**: Boolean to indicate if the field is for billing purposes. Adds 'Billing' prefix to the label.
|
|
34
|
+
- **isDisabled**: Boolean to indicate if the field should be disabled.
|
|
35
|
+
- **region**: Custom region name (e.g., 'state', 'province'). If not provided, it defaults to the country's default region.
|
|
36
|
+
|
|
37
|
+
### Dynamic Logic
|
|
38
|
+
- **Dynamic Label**: The label is constructed based on the \`label\` prop, the country's default label, and whether it is a billing field.
|
|
39
|
+
- **Dynamic IDs and Names**: The \`fieldId\`, \`selectId\`, and \`name\` attributes are dynamically generated based on the \`region\` prop or the country's default region. If \`fieldId\` and \`selectId\` are provided, they are used directly.
|
|
40
|
+
|
|
41
|
+
`,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const Basic = (args) => <RegionSelector {...args} />;
|
|
48
|
+
Basic.args = {
|
|
49
|
+
country: 'USA',
|
|
50
|
+
value: '',
|
|
51
|
+
hasError: false,
|
|
52
|
+
isHidden: false,
|
|
53
|
+
isBillingSelector: false,
|
|
54
|
+
isDisabled: false,
|
|
55
|
+
region: '',
|
|
56
|
+
fieldId: '',
|
|
57
|
+
selectId: '',
|
|
58
|
+
label: '',
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const BillingState = Basic.bind({});
|
|
62
|
+
BillingState.args = {
|
|
63
|
+
...Basic.args,
|
|
64
|
+
isBillingSelector: true,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const CustomRegion = Basic.bind({});
|
|
68
|
+
CustomRegion.args = {
|
|
69
|
+
...Basic.args,
|
|
70
|
+
region: 'province',
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const CustomFieldIdAndSelectId = Basic.bind({});
|
|
74
|
+
CustomFieldIdAndSelectId.args = {
|
|
75
|
+
...Basic.args,
|
|
76
|
+
fieldId: 'customFieldId',
|
|
77
|
+
selectId: 'customSelectId',
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const CustomLabel = Basic.bind({});
|
|
81
|
+
CustomLabel.args = {
|
|
82
|
+
...Basic.args,
|
|
83
|
+
label: 'Custom Label',
|
|
84
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -315,10 +315,10 @@ Object.defineProperty(exports, "ProgressIndicator", {
|
|
|
315
315
|
return _progressIndicator.ProgressIndicator;
|
|
316
316
|
}
|
|
317
317
|
});
|
|
318
|
-
Object.defineProperty(exports, "
|
|
318
|
+
Object.defineProperty(exports, "RegionSelector", {
|
|
319
319
|
enumerable: true,
|
|
320
320
|
get: function get() {
|
|
321
|
-
return
|
|
321
|
+
return _regionSelector.RegionSelector;
|
|
322
322
|
}
|
|
323
323
|
});
|
|
324
324
|
Object.defineProperty(exports, "RegistrationConfirmation", {
|
|
@@ -339,12 +339,6 @@ Object.defineProperty(exports, "Section", {
|
|
|
339
339
|
return _section.Section;
|
|
340
340
|
}
|
|
341
341
|
});
|
|
342
|
-
Object.defineProperty(exports, "State", {
|
|
343
|
-
enumerable: true,
|
|
344
|
-
get: function get() {
|
|
345
|
-
return _state.State;
|
|
346
|
-
}
|
|
347
|
-
});
|
|
348
342
|
Object.defineProperty(exports, "Submit", {
|
|
349
343
|
enumerable: true,
|
|
350
344
|
get: function get() {
|
|
@@ -411,11 +405,10 @@ var _paymentType = require("./payment-type");
|
|
|
411
405
|
var _phone = require("./phone");
|
|
412
406
|
var _position = require("./position");
|
|
413
407
|
var _progressIndicator = require("./progress-indicator");
|
|
414
|
-
var
|
|
408
|
+
var _regionSelector = require("./region-selector");
|
|
415
409
|
var _registrationConfirmation = require("./registration-confirmation");
|
|
416
410
|
var _responsibility = require("./responsibility");
|
|
417
411
|
var _section = require("./section");
|
|
418
|
-
var _state = require("./state");
|
|
419
412
|
var _submit = require("./submit");
|
|
420
413
|
var _trialBanner = require("./trial-banner");
|
|
421
414
|
var _educationJobTitle = require("./education-job-title");
|
|
@@ -4,28 +4,37 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.
|
|
7
|
+
exports.RegionSelector = RegionSelector;
|
|
8
8
|
var _react = _interopRequireDefault(require("react"));
|
|
9
9
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
10
10
|
var _classnames = _interopRequireDefault(require("classnames"));
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
fieldId = _ref$fieldId === void 0 ? 'provinceField' : _ref$fieldId,
|
|
17
|
-
_ref$selectId = _ref.selectId,
|
|
18
|
-
selectId = _ref$selectId === void 0 ? 'province' : _ref$selectId,
|
|
11
|
+
var _regionSelector = require("../utils/region-selector");
|
|
12
|
+
function RegionSelector(_ref) {
|
|
13
|
+
var _ref$country = _ref.country,
|
|
14
|
+
country = _ref$country === void 0 ? 'USA' : _ref$country,
|
|
15
|
+
fieldId = _ref.fieldId,
|
|
19
16
|
_ref$hasError = _ref.hasError,
|
|
20
17
|
hasError = _ref$hasError === void 0 ? false : _ref$hasError,
|
|
21
|
-
_ref$
|
|
22
|
-
|
|
23
|
-
_ref$isBillingProvinc = _ref.isBillingProvince,
|
|
24
|
-
isBillingProvince = _ref$isBillingProvinc === void 0 ? false : _ref$isBillingProvinc,
|
|
18
|
+
_ref$isBillingSelecto = _ref.isBillingSelector,
|
|
19
|
+
isBillingSelector = _ref$isBillingSelecto === void 0 ? false : _ref$isBillingSelecto,
|
|
25
20
|
_ref$isDisabled = _ref.isDisabled,
|
|
26
21
|
isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
|
|
27
|
-
_ref$
|
|
28
|
-
|
|
22
|
+
_ref$isHidden = _ref.isHidden,
|
|
23
|
+
isHidden = _ref$isHidden === void 0 ? false : _ref$isHidden,
|
|
24
|
+
label = _ref.label,
|
|
25
|
+
regionType = _ref.regionType,
|
|
26
|
+
selectId = _ref.selectId,
|
|
27
|
+
value = _ref.value;
|
|
28
|
+
var _configByCountry$coun = _regionSelector.configByCountry[country],
|
|
29
|
+
_configByCountry$coun2 = _configByCountry$coun.regions,
|
|
30
|
+
regions = _configByCountry$coun2 === void 0 ? [] : _configByCountry$coun2,
|
|
31
|
+
defaultRegionType = _configByCountry$coun.defaultRegionType,
|
|
32
|
+
defaultLabel = _configByCountry$coun.label;
|
|
33
|
+
var dynamicRegionType = regionType || defaultRegionType;
|
|
34
|
+
var dynamicLabel = isBillingSelector ? "Billing ".concat(label || defaultLabel) : label || defaultLabel;
|
|
35
|
+
var dynamicFieldId = fieldId || "".concat(dynamicRegionType, "Field");
|
|
36
|
+
var dynamicSelectId = selectId || dynamicRegionType;
|
|
37
|
+
var dynamicName = isBillingSelector ? "billing".concat(dynamicRegionType.charAt(0).toUpperCase() + dynamicRegionType.slice(1)) : dynamicRegionType;
|
|
29
38
|
var fieldClassNames = (0, _classnames["default"])(['o-forms-field', {
|
|
30
39
|
ncf__hidden: isHidden
|
|
31
40
|
}]);
|
|
@@ -33,28 +42,28 @@ function Province(_ref) {
|
|
|
33
42
|
'o-forms-input--invalid': hasError
|
|
34
43
|
}]);
|
|
35
44
|
return /*#__PURE__*/_react["default"].createElement("label", {
|
|
36
|
-
id:
|
|
45
|
+
id: dynamicFieldId,
|
|
37
46
|
className: fieldClassNames,
|
|
38
47
|
"data-validate": "required",
|
|
39
|
-
htmlFor:
|
|
48
|
+
htmlFor: dynamicSelectId
|
|
40
49
|
}, /*#__PURE__*/_react["default"].createElement("span", {
|
|
41
50
|
className: "o-forms-title"
|
|
42
51
|
}, /*#__PURE__*/_react["default"].createElement("span", {
|
|
43
52
|
className: "o-forms-title__main"
|
|
44
|
-
},
|
|
53
|
+
}, dynamicLabel)), /*#__PURE__*/_react["default"].createElement("span", {
|
|
45
54
|
className: inputWrapperClassNames
|
|
46
55
|
}, /*#__PURE__*/_react["default"].createElement("select", {
|
|
47
56
|
id: selectId,
|
|
48
57
|
"aria-required": "true",
|
|
49
58
|
required: true,
|
|
50
|
-
name:
|
|
51
|
-
"data-trackable": "field-
|
|
59
|
+
name: dynamicName,
|
|
60
|
+
"data-trackable": "field-".concat(dynamicRegionType),
|
|
52
61
|
disabled: isDisabled,
|
|
53
62
|
defaultValue: value
|
|
54
63
|
}, /*#__PURE__*/_react["default"].createElement("option", {
|
|
55
64
|
disabled: true,
|
|
56
65
|
value: ""
|
|
57
|
-
}, "Please select a
|
|
66
|
+
}, "Please select a ", defaultLabel.toLowerCase()), regions.map(function (_ref2) {
|
|
58
67
|
var code = _ref2.code,
|
|
59
68
|
name = _ref2.name;
|
|
60
69
|
return /*#__PURE__*/_react["default"].createElement("option", {
|
|
@@ -63,18 +72,17 @@ function Province(_ref) {
|
|
|
63
72
|
}, name);
|
|
64
73
|
})), /*#__PURE__*/_react["default"].createElement("span", {
|
|
65
74
|
className: "o-forms-input__error"
|
|
66
|
-
}, "Please select your
|
|
75
|
+
}, "Please select your ", defaultLabel.toLowerCase())));
|
|
67
76
|
}
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
RegionSelector.propTypes = {
|
|
78
|
+
country: _propTypes["default"].oneOf(['USA', 'CAN', 'IND']),
|
|
70
79
|
fieldId: _propTypes["default"].string,
|
|
71
|
-
selectId: _propTypes["default"].string,
|
|
72
80
|
hasError: _propTypes["default"].bool,
|
|
73
|
-
|
|
74
|
-
isBillingProvince: _propTypes["default"].bool,
|
|
81
|
+
isBillingSelector: _propTypes["default"].bool,
|
|
75
82
|
isDisabled: _propTypes["default"].bool,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
isHidden: _propTypes["default"].bool,
|
|
84
|
+
label: _propTypes["default"].string,
|
|
85
|
+
regionType: _propTypes["default"].string,
|
|
86
|
+
selectId: _propTypes["default"].string,
|
|
87
|
+
value: _propTypes["default"].string
|
|
80
88
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/n-conversion-forms",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "41.0.0",
|
|
4
4
|
"description": "Containing jsx components and styles for forms included on Accounts and Acquisition apps (next-signup, next-profile, next-retention, etc).",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"classnames": "2.5.1",
|
|
31
31
|
"fetchres": "1.7.2",
|
|
32
32
|
"lodash.get": "4.4.2",
|
|
33
|
-
"n-common-static-data": "github:Financial-Times/n-common-static-data#v3.
|
|
33
|
+
"n-common-static-data": "github:Financial-Times/n-common-static-data#v3.1.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@babel/core": "^7.23.9",
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
americanStates,
|
|
3
|
+
canadianProvinces,
|
|
4
|
+
indianStatesAndUnionTerritories,
|
|
5
|
+
} from 'n-common-static-data';
|
|
6
|
+
import FormElement from './form-element';
|
|
7
|
+
|
|
8
|
+
export const configByCountry = {
|
|
9
|
+
USA: {
|
|
10
|
+
regions: americanStates.states,
|
|
11
|
+
defaultRegionType: 'state',
|
|
12
|
+
label: 'State',
|
|
13
|
+
},
|
|
14
|
+
CAN: {
|
|
15
|
+
regions: canadianProvinces.provinces,
|
|
16
|
+
defaultRegionType: 'province',
|
|
17
|
+
label: 'Province',
|
|
18
|
+
},
|
|
19
|
+
IND: {
|
|
20
|
+
regions: indianStatesAndUnionTerritories.states,
|
|
21
|
+
defaultRegionType: 'state',
|
|
22
|
+
label: 'State/Union Territory',
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Class representing a region selector form element.
|
|
28
|
+
* @extends FormElement
|
|
29
|
+
*/
|
|
30
|
+
class RegionSelector extends FormElement {
|
|
31
|
+
/**
|
|
32
|
+
* Create a region selector.
|
|
33
|
+
*
|
|
34
|
+
* @param {Document} document - The document object.
|
|
35
|
+
* @param {Object} [options] - Options for the region selector.
|
|
36
|
+
* @param {string} [options.country='USA'] - The country code (e.g., 'USA', 'CAN', 'IND'). Defaults to 'USA'.
|
|
37
|
+
* @param {string} [options.regionType] - The type of region (e.g., 'state', 'province'). Defaults to the default region type for the country.
|
|
38
|
+
* @param {string} [options.fieldId] - The ID of the field element. Defaults to the default field ID for the region type.
|
|
39
|
+
*
|
|
40
|
+
* @note Ensure that the `country`, `regionType` and `fieldId` used here matches what is used in the props for the `RegionSelector` component.
|
|
41
|
+
*/
|
|
42
|
+
constructor(document, { country = 'USA', regionType, fieldId } = {}) {
|
|
43
|
+
const defaultRegionType =
|
|
44
|
+
regionType || configByCountry[country].defaultRegionType;
|
|
45
|
+
|
|
46
|
+
const selector = fieldId
|
|
47
|
+
? `.ncf #${fieldId}`
|
|
48
|
+
: `.ncf #${defaultRegionType}Field`;
|
|
49
|
+
|
|
50
|
+
super(document, selector);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default RegionSelector;
|