@pega/custom-dx-components 0.25.53 → 0.25.55

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 (43) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -2
  3. package/src/tasks/create/templates/Launchpad/Field/Text-Phone/config.json.mustache +146 -0
  4. package/src/tasks/create/templates/Launchpad/Field/Text-Phone/demo.stories.tsx.mustache +61 -0
  5. package/src/tasks/create/templates/Launchpad/Field/Text-Phone/demo.test.tsx.mustache +23 -0
  6. package/src/tasks/create/templates/Launchpad/Field/Text-Phone/event-utils.ts.mustache +18 -0
  7. package/src/tasks/create/templates/Launchpad/Field/Text-Phone/index.tsx.mustache +246 -0
  8. package/src/tasks/create/templates/Launchpad/Field/Text-Phone/mock.ts.mustache +40 -0
  9. package/src/tasks/create/templates/Launchpad/Field/Text-Phone/styles.ts.mustache +8 -0
  10. package/src/tasks/create/templates/Launchpad/Template/FORM/DefaultForm.svg +29 -0
  11. package/src/tasks/create/templates/Launchpad/Template/FORM/DetailsRender.tsx.mustache +59 -0
  12. package/src/tasks/create/templates/Launchpad/Template/FORM/config.json.mustache +45 -0
  13. package/src/tasks/create/templates/Launchpad/Template/FORM/demo.stories.tsx.mustache +255 -0
  14. package/src/tasks/create/templates/Launchpad/Template/FORM/demo.test.tsx.mustache +40 -0
  15. package/src/tasks/create/templates/Launchpad/Template/FORM/index.tsx.mustache +75 -0
  16. package/src/tasks/create/templates/Launchpad/Template/FORM/mock.ts.mustache +135 -0
  17. package/src/tasks/create/templates/Launchpad/Template/FORM/styles.ts.mustache +8 -0
  18. package/src/tasks/create/templates/Launchpad/Template/FORM-region/DetailsRender.tsx.mustache +59 -0
  19. package/src/tasks/create/templates/Launchpad/Template/FORM-region/TwoColumn.svg +38 -0
  20. package/src/tasks/create/templates/Launchpad/Template/FORM-region/config.json.mustache +27 -0
  21. package/src/tasks/create/templates/Launchpad/Template/FORM-region/demo.stories.tsx.mustache +272 -0
  22. package/src/tasks/create/templates/Launchpad/Template/FORM-region/demo.test.tsx.mustache +56 -0
  23. package/src/tasks/create/templates/Launchpad/Template/FORM-region/index.tsx.mustache +80 -0
  24. package/src/tasks/create/templates/Launchpad/Template/FORM-region/mock.ts.mustache +141 -0
  25. package/src/tasks/create/templates/Launchpad/Template/FORM-region/styles.ts.mustache +8 -0
  26. package/src/tasks/delete-lib/index.js +6 -0
  27. package/src/tasks/init/template/README.md +18 -0
  28. package/src/tasks/init/template/package.json.mustache +2 -2
  29. package/src/tasks/restore/index.js +35 -14
  30. package/src/tasks/store/index.js +34 -13
  31. package/tests/assets/original/components/createAll/Launchpad/Pega_DXIL_MyForm/mock.ts +0 -4
  32. package/tests/assets/original/components/createAll/Launchpad/Pega_DXIL_MyPhone/config.json +1 -6
  33. package/tests/assets/original/components/createAll/Launchpad/Pega_DXIL_MyPhone/mock.ts +1 -6
  34. package/tests/assets/original/components/createAll/Launchpad/Pega_DXIL_MyTwoColumnForm/mock.ts +0 -4
  35. package/tests/assets/original/components/createAll/Constellation/shared/suggestions-handler.ts +0 -9
  36. package/tests/assets/original/components/createAll/Launchpad/shared/suggestions-handler.ts +0 -9
  37. /package/{tests/assets/original/components/create/shared/PConnProps.d.ts → src/tasks/create/templates/Launchpad/Field/Text-Phone/PConnProps.d.ts.mustache} +0 -0
  38. /package/{tests/assets/original/components/create/shared/create-nonce.ts → src/tasks/create/templates/Launchpad/Field/Text-Phone/create-nonce.ts.mustache} +0 -0
  39. /package/{tests/assets/original/components/create/shared/suggestions-handler.ts → src/tasks/create/templates/Launchpad/Field/Text-Phone/suggestions-handler.ts.mustache} +0 -0
  40. /package/{tests/assets/original/components/createAll/Launchpad/shared/PConnProps.d.ts → src/tasks/create/templates/Launchpad/Template/FORM/PConnProps.d.ts.mustache} +0 -0
  41. /package/{tests/assets/original/components/createAll/Launchpad/shared/create-nonce.ts → src/tasks/create/templates/Launchpad/Template/FORM/create-nonce.ts.mustache} +0 -0
  42. /package/{tests/assets/original/components/createAll/Constellation/shared/PConnProps.d.ts → src/tasks/create/templates/Launchpad/Template/FORM-region/PConnProps.d.ts.mustache} +0 -0
  43. /package/{tests/assets/original/components/createAll/Constellation/shared/create-nonce.ts → src/tasks/create/templates/Launchpad/Template/FORM-region/create-nonce.ts.mustache} +0 -0
package/README.md CHANGED
@@ -4,6 +4,24 @@
4
4
 
5
5
  This project provides you with an environment to extend Constellation by giving you tools to create and publish custom components that are not available from the Constellation installation.
6
6
 
7
+ ## Before you begin
8
+ Review the following checklist before you create a Constellation DX component:
9
+
10
+ ## Design considerations
11
+ Involve an Experience Designer in your process. This will help you determine the exact issue to be resolved. For more information on the role of an Experience Designer, see **Experience Designer**[here](https://community.pega.com/roles/experience-designer).
12
+
13
+ ## The Experience Designer must meet the following requirements:
14
+ Must have a background in UI and UX design.
15
+ Must understand Pega's best practices for design. For more information, see **Best practices for designing with the Constellation design system**[here](https://design.pega.com/design/getting-started/).
16
+
17
+ ## Functionality considerations
18
+ Check if an existing component in App Studio contains the features you need. If not, check for existing components that contain similar features.
19
+ Connect with Pega Support to find out if a component containing a similar feature will be included in the next release. If yes, assess if you can wait for the next release.
20
+
21
+ ## Maintenance considerations
22
+ Ensure you have the bandwidth to maintain the Constellation DX component and keep it up-to-date with every release of Pega Infinity. Evaluate if doing this might prevent you from upgrading to future releases of Pega Infinity.
23
+ Evaluate if you are able to meet the compliance standards for data privacy and accessibility for Constellation DX components. Note that not meeting these standards might lead to legal compliance issues.
24
+
7
25
  ## Prerequisites
8
26
 
9
27
  Ensure you have access to the following in your system:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pega/custom-dx-components",
3
- "version": "0.25.53",
3
+ "version": "0.25.55",
4
4
  "description": "Utility for building custom UI components",
5
5
  "bin": "./bin/index.js",
6
6
  "keywords": [
@@ -25,7 +25,7 @@
25
25
  "@babel/plugin-transform-class-properties": "^7.27.1",
26
26
  "@babel/preset-react": "^7.27.1",
27
27
  "@pega/auth": "^0.2.27",
28
- "@pega/constellation-dx-components-build-utils": "^2.0.7",
28
+ "@pega/constellation-dx-components-build-utils": "^2.0.8",
29
29
  "@pega/inquirer-fuzzy-path": "^3.0.0",
30
30
  "ajv": "^8.17.1",
31
31
  "ajv-keywords": "^5.1.0",
@@ -0,0 +1,146 @@
1
+ {
2
+ "name": "{{COMPONENT_KEY}}",
3
+ "label": "{{COMPONENT_LABEL}}",
4
+ "description": "{{DESCRIPTION}}",
5
+ "organization": "{{ORGANIZATION}}",
6
+ "version": "{{VERSION}}",
7
+ "library": "{{LIBRARY}}",
8
+ "componentKey": "{{COMPONENT_KEY}}",
9
+ "type": "{{TYPE}}",
10
+ "subtype": {{{SUB_TYPE}}},
11
+ "subtypeLabel": "{{SUB_TYPE_LABEL}}",
12
+ "icon": "images/pz-phone-active.svg",
13
+ "properties": [
14
+ {
15
+ "name": "label",
16
+ "label": "Field label",
17
+ "format": "TEXT",
18
+ "required": true
19
+ },
20
+ {
21
+ "name": "labelOption",
22
+ "label": "Field label",
23
+ "format": "SELECT",
24
+ "defaultValue": "custom",
25
+ "visibility": "@PLATFORMNAME != 'launchpad'",
26
+ "source": [
27
+ {
28
+ "key": "default",
29
+ "value": "Default"
30
+ },
31
+ {
32
+ "key": "custom",
33
+ "value": "Custom"
34
+ }
35
+ ]
36
+ },
37
+ {
38
+ "name": "label",
39
+ "label": "Custom field label",
40
+ "format": "VALUEINPUT",
41
+ "required": true,
42
+ "ruleType": "Paragraph",
43
+ "visibility": "@PLATFORMNAME != 'launchpad'"
44
+ },
45
+ {
46
+ "name": "readOnly",
47
+ "label": "Edit mode",
48
+ "format": "READONLY"
49
+ },
50
+ {
51
+ "name": "showCountryCode",
52
+ "label": "Show Country Code",
53
+ "format": "BOOLEAN",
54
+ "defaultValue": true
55
+ },
56
+ {
57
+ "label": "Column settings",
58
+ "format": "GROUP",
59
+ "visibility": "@VIEWTYPE == 'MultiRecordDisplayAsTable'",
60
+ "properties": [
61
+ {
62
+ "name": "columnWidth",
63
+ "label": "Column width",
64
+ "format": "SELECT",
65
+ "source": [
66
+ {
67
+ "key": "auto",
68
+ "value": "Auto"
69
+ },
70
+ {
71
+ "key": "custom",
72
+ "value": "Custom"
73
+ }
74
+ ]
75
+ },
76
+ {
77
+ "name": "width",
78
+ "label": "Width (px)",
79
+ "format": "NUMBER",
80
+ "visibility": "$this.columnWidth == 'custom'"
81
+ }
82
+ ]
83
+ },
84
+ {
85
+ "label": "Input settings",
86
+ "format": "GROUP",
87
+ "visibility": "(!readOnly = true)",
88
+ "properties": [
89
+ {
90
+ "name": "placeholder",
91
+ "label": "Placeholder",
92
+ "format": "TEXT"
93
+ },
94
+ {
95
+ "name": "helperText",
96
+ "label": "Helper text",
97
+ "format": "TEXT"
98
+ }
99
+ ]
100
+ },
101
+ {
102
+ "label": "Conditions",
103
+ "format": "GROUP",
104
+ "properties": [
105
+ {
106
+ "name": "required",
107
+ "label": "Required",
108
+ "format": "REQUIRED",
109
+ "visibility": "(!readOnly = true)"
110
+ },
111
+ {
112
+ "name": "disabled",
113
+ "label": "Disabled",
114
+ "format": "DISABLED",
115
+ "visibility": "(!readOnly = true)"
116
+ },
117
+ {
118
+ "name": "visibility",
119
+ "label": "Visibility",
120
+ "format": "VISIBILITY"
121
+ }
122
+ ]
123
+ },
124
+ {
125
+ "label": "Advanced",
126
+ "format": "GROUP",
127
+ "collapsible": true,
128
+ "properties": [
129
+ {
130
+ "name": "testId",
131
+ "label": "Test ID",
132
+ "format": "TEXT",
133
+ "ignorePattern": "[^-_\\p{N}\\p{L}]",
134
+ "includeAnnotations": false
135
+ }
136
+ ]
137
+ }
138
+ ],
139
+ "defaultConfig": {
140
+ "label": "@L $this.label",
141
+ "datasource": {},
142
+ "detailFVLItem": true,
143
+ "isFormWidth" : false,
144
+ "isContainerWidth" : false
145
+ }
146
+ }
@@ -0,0 +1,61 @@
1
+ /* eslint-disable react/jsx-no-useless-fragment */
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+
4
+ import {{COMPONENT_CLASS_NAME}} from './index';
5
+ import { stateProps, configProps } from './mock';
6
+
7
+ const meta: Meta<typeof {{COMPONENT_CLASS_NAME}}> = {
8
+ title: '{{COMPONENT_CLASS_NAME}}',
9
+ component: {{COMPONENT_CLASS_NAME}},
10
+ excludeStories: /.*Data$/
11
+ };
12
+
13
+ export default meta;
14
+ type Story = StoryObj<typeof {{COMPONENT_CLASS_NAME}}>;
15
+
16
+ export const Base{{COMPONENT_CLASS_NAME}}: Story = (args: any) => {
17
+
18
+ const props = {
19
+ value: configProps.value,
20
+ hasSuggestions: configProps.hasSuggestions,
21
+ getPConnect: () => {
22
+ return {
23
+ getStateProps: () => {
24
+ return stateProps;
25
+ },
26
+ getActionsApi: () => {
27
+ return {
28
+ updateFieldValue: () => {/* nothing */},
29
+ triggerFieldChange: () => {/* nothing */}
30
+ };
31
+ },
32
+ ignoreSuggestion: () => {/* nothing */},
33
+ acceptSuggestion: () => {/* nothing */},
34
+ setInheritedProps: () => {/* nothing */},
35
+ resolveConfigProps: () => {/* nothing */}
36
+ };
37
+ }
38
+ };
39
+
40
+ return (
41
+ <>
42
+ <{{COMPONENT_CLASS_NAME}} {...props} {...args} />
43
+ </>
44
+ );
45
+ };
46
+
47
+ Base{{COMPONENT_CLASS_NAME}}.args = {
48
+ datasource: configProps.datasource,
49
+ label: configProps.label,
50
+ helperText: configProps.helperText,
51
+ placeholder: configProps.placeholder,
52
+ testId: configProps.testId,
53
+ readOnly: configProps.readOnly,
54
+ disabled: configProps.disabled,
55
+ required: configProps.required,
56
+ status: configProps.status,
57
+ hideLabel: configProps.hideLabel,
58
+ displayMode: configProps.displayMode,
59
+ variant: configProps.variant,
60
+ validatemessage: configProps.validatemessage
61
+ };
@@ -0,0 +1,23 @@
1
+ // import { expect, test } from '@jest/globals';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { composeStories } from '@storybook/react';
4
+ import '@testing-library/jest-dom';
5
+
6
+ import * as DemoStories from './demo.stories';
7
+
8
+ const { Base{{COMPONENT_CLASS_NAME}} } = composeStories(DemoStories);
9
+
10
+ test('renders {{COMPONENT_CLASS_NAME}}', async () => {
11
+ render(<Base{{COMPONENT_CLASS_NAME}} />);
12
+ expect(await screen.findByText('Phone Sample')).toBeVisible();
13
+ expect(await screen.findByText('Phone Helper Text')).toBeVisible();
14
+
15
+
16
+ const phoneElement = (screen.getByTestId('phone-12345678') as HTMLInputElement);
17
+ expect(phoneElement.value).toBe('');
18
+
19
+ expect(phoneElement).toHaveAttribute('placeholder', 'Phone Placeholder');
20
+
21
+ const countryElement = (screen.getByTestId(":phone-input:country-code") as HTMLSelectElement);
22
+ expect(countryElement.value).toContain("+1");
23
+ });
@@ -0,0 +1,18 @@
1
+ const handleEvent = (actions: any, eventType: string, propName: string, value: string | number) => {
2
+ switch (eventType) {
3
+ case 'change':
4
+ actions.updateFieldValue(propName, value);
5
+ break;
6
+ case 'blur':
7
+ actions.triggerFieldChange(propName, value);
8
+ break;
9
+ case 'changeNblur':
10
+ actions.updateFieldValue(propName, value);
11
+ actions.triggerFieldChange(propName, value);
12
+ break;
13
+ default:
14
+ break;
15
+ }
16
+ };
17
+
18
+ export default handleEvent;
@@ -0,0 +1,246 @@
1
+ import { useState, useEffect, useRef } from 'react';
2
+ import {
3
+ PhoneInput as CosmosPhone,
4
+ getPhoneNumberParts,
5
+ PhoneDisplay,
6
+ FieldValueList,
7
+ Text,
8
+ EmailDisplay,
9
+ URLDisplay,
10
+ withConfiguration
11
+ } from '@pega/cosmos-react-core';
12
+ import type { PConnFieldProps } from './PConnProps';
13
+ import './create-nonce';
14
+
15
+ // includes in bundle
16
+ import handleEvent from "./event-utils";
17
+ import { suggestionsHandler } from './suggestions-handler';
18
+
19
+ import Styled{{COMPONENT_CLASS_NAME}}Wrapper from './styles';
20
+
21
+ // interface for props
22
+ interface {{COMPONENT_CLASS_NAME}}Props extends PConnFieldProps {
23
+ // If any, enter additional props that only exist on TextInput here
24
+ displayAsStatus?: boolean;
25
+ isTableFormatter?: boolean;
26
+ hasSuggestions?: boolean;
27
+ variant?: any;
28
+ formatter: string;
29
+ datasource: any;
30
+ showCountryCode: boolean;
31
+ }
32
+
33
+ // interface for StateProps object
34
+ interface StateProps {
35
+ value: string;
36
+ hasSuggestions: boolean;
37
+ }
38
+
39
+ export const formatExists = (formatterVal: string) => {
40
+ const formatterValues = [
41
+ "TextInput",
42
+ "WorkStatus",
43
+ "RichText",
44
+ "Email",
45
+ "Phone",
46
+ "URL",
47
+ "Operator"
48
+ ];
49
+ let isformatter = false;
50
+ if (formatterValues.includes(formatterVal)) {
51
+ isformatter = true;
52
+ }
53
+ return isformatter;
54
+ };
55
+
56
+
57
+ export const textFormatter = (formatter: string, value: any) => {
58
+ let displayComponent:any = null;
59
+ switch(formatter){
60
+ case "TextInput" : {
61
+ displayComponent = value;
62
+ break;
63
+ }
64
+ case "Email" : {
65
+ displayComponent = (<EmailDisplay value={value} displayText={value} variant="link" />);
66
+ break;
67
+ }
68
+ case "Phone" : {
69
+ displayComponent = (<PhoneDisplay value={value} variant="link" />);
70
+ break;
71
+ }
72
+ case "URL" : {
73
+ displayComponent = (<URLDisplay target="_blank" value={value} displayText={value} variant="link" />);
74
+ break;
75
+ }
76
+ // no default
77
+ }
78
+ return displayComponent;
79
+ };
80
+
81
+
82
+
83
+ // Duplicated runtime code from Constellation Design System Component
84
+
85
+ // props passed in combination of props from property panel (config.json) and run time props from Constellation
86
+ // any default values in config.pros should be set in defaultProps at bottom of this file
87
+ function {{COMPONENT_CLASS_NAME}}(props: {{COMPONENT_CLASS_NAME}}Props) {
88
+ const {
89
+ getPConnect,
90
+ value,
91
+ showCountryCode = true,
92
+ placeholder,
93
+ validatemessage,
94
+ label,
95
+ hideLabel = false,
96
+ helperText,
97
+ datasource = [],
98
+ testId,
99
+ displayMode,
100
+ additionalProps = {},
101
+ variant = 'inline',
102
+ isTableFormatter = false,
103
+ hasSuggestions = false
104
+ } = props;
105
+ const { formatter } = props;
106
+ const pConn = getPConnect();
107
+ const actions = pConn.getActionsApi();
108
+ const stateProps = pConn.getStateProps() as StateProps;
109
+ const propName: string = stateProps.value;
110
+ const hasValueChange = useRef(false);
111
+
112
+ let callingCodesList: Array<any> = [];
113
+ if (datasource?.source?.length > 0) {
114
+ datasource.source.forEach((element: { value: any; }) => {
115
+ callingCodesList.push(element.value);
116
+ });
117
+ } else {
118
+ callingCodesList = ['+1']; // if no datasource is present we default to show only US country code
119
+ }
120
+
121
+ // BUG-547602: Temporary type coercion for 8.5 until DXAPIs are enhanced to pass original pxViewMetadata JSON, respecting boolean primitives
122
+ let { readOnly = false, required = false, disabled = false } = props;
123
+ [readOnly, required, disabled] = [readOnly, required, disabled].map(
124
+ (prop) => prop === true || (typeof prop === 'string' && prop === 'true')
125
+ );
126
+
127
+ const [inputValue, setInputValue] = useState(value);
128
+ useEffect(() => setInputValue(value), [value]);
129
+
130
+ const [status, setStatus] = useState(hasSuggestions ? 'pending' : undefined);
131
+ useEffect(() => {
132
+ if (validatemessage !== '') {
133
+ setStatus('error');
134
+ }
135
+ if (hasSuggestions) {
136
+ setStatus('pending');
137
+ } else if (!hasSuggestions && status !== 'success') {
138
+ setStatus(validatemessage !== '' ? 'error' : undefined);
139
+ }
140
+ }, [validatemessage, hasSuggestions, status]);
141
+
142
+ // function to exclude country code from phone number
143
+ function getPhoneNumberAlone(phoneNumber: string) {
144
+ const phoneNumberParts = getPhoneNumberParts(phoneNumber, callingCodesList);
145
+ return phoneNumberParts && phoneNumberParts[1];
146
+ }
147
+
148
+ function handleChangeBlur(enteredValue: string, eventType: any) {
149
+ if (!getPhoneNumberAlone(enteredValue)) {
150
+ enteredValue = '';
151
+ }
152
+ handleEvent(actions, eventType, propName, enteredValue);
153
+ }
154
+
155
+ let displayComp: any = null;
156
+ if (displayMode) {
157
+ displayComp = <PhoneDisplay value={value} variant='link' />;
158
+ }
159
+
160
+ if (displayMode === 'LABELS_LEFT' || displayMode === 'DISPLAY_ONLY') {
161
+ if (isTableFormatter && formatExists(formatter)) {
162
+ displayComp = textFormatter(formatter, value);
163
+ }
164
+ return displayMode === 'DISPLAY_ONLY' ? (
165
+ <Styled{{COMPONENT_CLASS_NAME}}Wrapper>
166
+ {displayComp}
167
+ </Styled{{COMPONENT_CLASS_NAME}}Wrapper>
168
+ ) : (
169
+ <Styled{{COMPONENT_CLASS_NAME}}Wrapper>
170
+ <FieldValueList
171
+ variant={hideLabel ? 'stacked' : variant}
172
+ data-testid={testId}
173
+ fields={[{ id: '1', name: hideLabel ? '' : label, value: displayComp }]}
174
+ />
175
+ </Styled{{COMPONENT_CLASS_NAME}}Wrapper>
176
+ );
177
+ }
178
+
179
+ if (displayMode === 'STACKED_LARGE_VAL') {
180
+ return (
181
+ <Styled{{COMPONENT_CLASS_NAME}}Wrapper>
182
+ <FieldValueList
183
+ variant='stacked'
184
+ data-testid={testId}
185
+ fields={[
186
+ {
187
+ id: '2',
188
+ name: hideLabel ? '' : label,
189
+ value: (
190
+ <Text variant='h1' as='span'>
191
+ {displayComp}
192
+ </Text>
193
+ )
194
+ }
195
+ ]}
196
+ />
197
+ </Styled{{COMPONENT_CLASS_NAME}}Wrapper>
198
+ );
199
+ }
200
+
201
+ const onResolveSuggestionHandler = (accepted: boolean) => {
202
+ suggestionsHandler(accepted, pConn, setStatus);
203
+ };
204
+
205
+ return (
206
+ <Styled{{COMPONENT_CLASS_NAME}}Wrapper>
207
+ <CosmosPhone
208
+ {...additionalProps}
209
+ label={label}
210
+ info={validatemessage || helperText}
211
+ value={inputValue}
212
+ labelHidden={hideLabel}
213
+ status={status}
214
+ showCountryCode={showCountryCode}
215
+ callingCodesList={callingCodesList}
216
+ placeholder={placeholder}
217
+ disabled={disabled}
218
+ readOnly={readOnly}
219
+ required={required}
220
+ data-testid={testId}
221
+ onChange={(enteredValue: any) => {
222
+ if (hasSuggestions) {
223
+ setStatus('');
224
+ }
225
+ setInputValue(enteredValue);
226
+ if (value !== enteredValue) {
227
+ handleEvent(actions, 'change', propName, enteredValue);
228
+ }
229
+ hasValueChange.current = true;
230
+ }}
231
+ onBlur={(enteredValue: any) => {
232
+ if (!value || hasValueChange.current) {
233
+ handleChangeBlur(enteredValue, 'blur');
234
+ if (hasSuggestions) {
235
+ pConn.ignoreSuggestion('');
236
+ }
237
+ hasValueChange.current = false;
238
+ }
239
+ }}
240
+ onResolveSuggestion={onResolveSuggestionHandler}
241
+ />
242
+ </Styled{{COMPONENT_CLASS_NAME}}Wrapper>
243
+ );
244
+ }
245
+
246
+ export default withConfiguration({{COMPONENT_CLASS_NAME}});
@@ -0,0 +1,40 @@
1
+ export const configProps = {
2
+ value: '',
3
+ label: 'Phone Sample',
4
+ datasource: {
5
+ source: [
6
+ {
7
+ value: '+1'
8
+ },
9
+ {
10
+ value: '+91'
11
+ },
12
+ {
13
+ value: '+48'
14
+ },
15
+ {
16
+ value: '+44'
17
+ }
18
+ ],
19
+ fields: {}
20
+ },
21
+ showCountryCode: true,
22
+ placeholder: 'Phone Placeholder',
23
+ helperText: 'Phone Helper Text',
24
+ testId: 'phone-12345678',
25
+ hasSuggestions: false,
26
+ displayMode: '',
27
+ variant: '',
28
+ hideLabel: false,
29
+ readOnly: false,
30
+ required: false,
31
+ disabled: false,
32
+ status: '',
33
+ validatemessage: ''
34
+ };
35
+
36
+ export const stateProps = {
37
+ value: '.PhoneSample',
38
+ datasource: {},
39
+ hasSuggestions: false
40
+ };
@@ -0,0 +1,8 @@
1
+ // individual style, comment out above, and uncomment here and add styles
2
+ import styled, { css } from 'styled-components';
3
+
4
+ export default styled.div(() => {
5
+ return css`
6
+ margin: 0px 0;
7
+ `;
8
+ });
@@ -0,0 +1,29 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="100px" height="70px" viewBox="0 0 100 70" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <title>2 col copy</title>
4
+ <g id="Views" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
5
+ <g id="Template-icons" transform="translate(-320.000000, -925.000000)">
6
+ <g id="2-col--copy" transform="translate(320.000000, 925.000000)">
7
+ <rect id="bg" stroke="#A5A8BC" stroke-width="0.5" fill="#E7E9EB" x="0.25" y="0.25" width="99.5" height="69.5"></rect>
8
+ <g id="white" transform="translate(3.000000, 3.000000)" fill="#FFFFFF">
9
+ <rect id="Rectangle" x="0" y="0" width="94" height="66.5"></rect>
10
+ </g>
11
+ <g id="gray-copy-2" transform="translate(6.000000, 6.000000)" fill="#8084A7">
12
+ <rect id="Rectangle" x="0" y="-2.84217094e-14" width="42" height="11.8"></rect>
13
+ <rect id="Rectangle" x="46" y="-2.84217094e-14" width="42" height="11.8"></rect>
14
+ <rect id="Rectangle-Copy-5" x="0" y="16" width="42" height="11.8"></rect>
15
+ <rect id="Rectangle-Copy-3" x="46" y="16" width="42" height="11.8"></rect>
16
+ <rect id="Rectangle-Copy-15" x="0" y="32" width="42" height="11.8"></rect>
17
+ <rect id="Rectangle-Copy-14" x="46" y="32" width="42" height="11.8"></rect>
18
+ <rect id="Rectangle-Copy-17" x="0" y="48" width="42" height="11.8"></rect>
19
+ <rect id="Rectangle-Copy-16" x="46" y="48" width="42" height="11.8"></rect>
20
+ </g>
21
+ <g id="Group-7" transform="translate(28.000000, 11.000000)">
22
+ <path id="Line-12-Copy" d="M35.1666667,42.75 L47.1666667,48.5 L35.1666667,54.25 L35.166,49.25 L-0.25,49.25 L-0.25,47.75 L35.166,47.75 L35.1666667,42.75 Z" fill="#1E1F27" fill-rule="nonzero"></path>
23
+ <line x1="0.5" y1="48.5" x2="43.5" y2="32.5" id="Line" stroke="#1E1F27" stroke-width="1.5" stroke-linecap="square"></line>
24
+ <line x1="43.5" y1="32.5" x2="1.5" y2="32.5" id="Line-2" stroke="#1E1F27" stroke-width="1.5" stroke-linecap="square"></line>
25
+ </g>
26
+ </g>
27
+ </g>
28
+ </g>
29
+ </svg>
@@ -0,0 +1,59 @@
1
+ import { Fragment, type ReactElement } from 'react';
2
+ import { FieldValueList } from '@pega/cosmos-react-core';
3
+
4
+ interface DetailsRenderProps {
5
+ children?: never;
6
+ child: NonNullable<ReactElement>;
7
+ }
8
+
9
+ const DetailsRender = (props: DetailsRenderProps) => {
10
+ const { child } = props;
11
+
12
+ const kids = child.props.getPConnect().getChildren();
13
+
14
+ const displayCompArr: ReactElement[] = [];
15
+
16
+ Object.values(kids).forEach((value: any) => {
17
+ const { type } = value.getPConnect().getRawMetadata();
18
+ const { hideLabel, variant, testId, label } = value
19
+ .getPConnect()
20
+ .resolveConfigProps(value.getPConnect().getConfigProps());
21
+
22
+ let displayComp;
23
+ const key = JSON.stringify(value.getPConnect());
24
+
25
+ if (type === 'reference') {
26
+ const refElement = value.getPConnect().getComponent();
27
+
28
+ displayCompArr.push(refElement);
29
+ } else {
30
+ const element = value.getPConnect().getComponent();
31
+ const displayEl = <Fragment key={key}>{element}</Fragment>;
32
+
33
+ const fvlStyle = {
34
+ myColGap: {
35
+ columnGap: '0',
36
+ marginLineStart: 0
37
+ }
38
+ };
39
+
40
+ // const myEl = <div>boo</div>;
41
+ displayComp = (
42
+ <Fragment key={key}>
43
+ <FieldValueList
44
+ style={fvlStyle.myColGap}
45
+ variant={hideLabel ? 'stacked' : variant}
46
+ data-testid={testId}
47
+ fields={[{ id: '1', name: hideLabel ? '' : label, value: displayEl }]}
48
+ />
49
+ </Fragment>
50
+ );
51
+
52
+ displayCompArr.push(displayComp);
53
+ }
54
+ });
55
+
56
+ return <>{displayCompArr}</>;
57
+ };
58
+
59
+ export default DetailsRender;