@pega/sdk 0.0.13 → 0.0.15

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 (139) hide show
  1. package/README.md +46 -6
  2. package/dist/index.js +50 -24
  3. package/package.json +42 -3
  4. package/templates/angular-sdk-reference/extra-webpack.config.cjs +23 -0
  5. package/templates/angular-sdk-reference/index.html +12 -0
  6. package/templates/angular-sdk-reference/src/app/pconnect-renderer.component.ts +153 -0
  7. package/templates/angular-sdk-reference/src/components/component-map.ts +90 -0
  8. package/templates/angular-sdk-reference/src/components/fields/auto-complete/auto-complete.component.ts +304 -0
  9. package/templates/angular-sdk-reference/src/components/fields/checkbox/checkbox.component.ts +89 -0
  10. package/templates/angular-sdk-reference/src/components/fields/currency/currency.component.ts +112 -0
  11. package/templates/angular-sdk-reference/src/components/fields/date-input/date-input.component.ts +101 -0
  12. package/templates/angular-sdk-reference/src/components/fields/dropdown/dropdown.component.ts +118 -0
  13. package/templates/angular-sdk-reference/src/components/fields/email/email.component.ts +104 -0
  14. package/templates/angular-sdk-reference/src/components/fields/integer/integer.component.ts +106 -0
  15. package/templates/angular-sdk-reference/src/components/fields/phone/phone.component.ts +104 -0
  16. package/templates/angular-sdk-reference/src/components/fields/radio-buttons/radio-buttons.component.ts +113 -0
  17. package/templates/angular-sdk-reference/src/components/fields/text-area/text-area.component.ts +111 -0
  18. package/templates/angular-sdk-reference/src/components/fields/text-input/text-input.component.ts +110 -0
  19. package/templates/angular-sdk-reference/src/components/fields/url-input/url-input.component.ts +113 -0
  20. package/templates/angular-sdk-reference/src/components/helpers/sdk-helpers.ts +93 -0
  21. package/templates/angular-sdk-reference/src/components/infra/assignment/assignment.component.ts +206 -0
  22. package/templates/angular-sdk-reference/src/components/infra/case-summary/case-summary.component.ts +75 -0
  23. package/templates/angular-sdk-reference/src/components/infra/case-view/case-view.component.ts +126 -0
  24. package/templates/angular-sdk-reference/src/components/infra/flow-container/flow-container.component.ts +411 -0
  25. package/templates/angular-sdk-reference/src/components/infra/reference/reference.component.ts +158 -0
  26. package/templates/angular-sdk-reference/src/components/infra/region/region.component.ts +39 -0
  27. package/templates/angular-sdk-reference/src/components/infra/root-container/root-container.component.ts +199 -0
  28. package/templates/angular-sdk-reference/src/components/infra/stages/stages.component.ts +89 -0
  29. package/templates/angular-sdk-reference/src/components/infra/view/view.component.ts +144 -0
  30. package/templates/angular-sdk-reference/src/components/infra/view-container/view-container.component.ts +191 -0
  31. package/templates/angular-sdk-reference/src/components/templates/default-form/default-form.component.ts +105 -0
  32. package/templates/angular-sdk-reference/src/components/templates/narrow-wide/narrow-wide.component.ts +37 -0
  33. package/templates/angular-sdk-reference/src/components/templates/one-column/one-column.component.ts +37 -0
  34. package/templates/angular-sdk-reference/src/components/templates/two-column/two-column.component.ts +37 -0
  35. package/templates/angular-sdk-reference/src/components/templates/wide-narrow/wide-narrow.component.ts +37 -0
  36. package/templates/angular-sdk-reference/tsconfig.app.json +13 -0
  37. package/templates/react-sdk-reference/.ai-common/agents/embedded-flow-expert.md +75 -34
  38. package/templates/react-sdk-reference/.ai-common/agents/implementation-expert.md +74 -38
  39. package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions-embedded.md +33 -1
  40. package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions.md +57 -22
  41. package/templates/react-sdk-reference/.ai-common/instructions/embedded-component.md +25 -10
  42. package/templates/react-sdk-reference/.ai-common/prompts/add-component.md +40 -19
  43. package/templates/react-sdk-reference/.ai-common/prompts/component-manifest.json +62 -1
  44. package/templates/react-sdk-reference/.ai-common/prompts/embedded-component-manifest.md +26 -4
  45. package/templates/react-sdk-reference/.ai-common/prompts/generate-all-components.md +84 -33
  46. package/templates/react-sdk-reference/.ai-common/prompts/generate-dse-components.md +46 -26
  47. package/templates/react-sdk-reference/.ai-common/prompts/generate-embedded-components.md +28 -15
  48. package/templates/react-sdk-reference/.ai-common/prompts/generate-field-components.md +24 -6
  49. package/templates/react-sdk-reference/.ai-common/prompts/generate-infra-components.md +24 -6
  50. package/templates/react-sdk-reference/.ai-common/prompts/generate-template-components.md +24 -6
  51. package/templates/react-sdk-reference/.ai-common/prompts/generate-widget-components.md +24 -6
  52. package/templates/react-sdk-reference/.ai-common/prompts/identify-components.md +2 -0
  53. package/templates/react-sdk-reference/.ai-common/prompts/replace-design-system.md +44 -17
  54. package/templates/react-sdk-reference/.ai-common/skills/connect-pega-server.md +14 -1
  55. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/AssignmentHeader.md +79 -0
  56. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/Toast.md +96 -0
  57. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension.md +56 -35
  58. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/analyze-customer-repo.md +29 -3
  59. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/run-and-verify-integration.md +97 -37
  60. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/wire-integration.md +91 -60
  61. package/templates/react-sdk-reference/.ai-common/skills/field-components.md +88 -30
  62. package/templates/react-sdk-reference/.ai-common/skills/field-skills/AutoComplete.md +133 -101
  63. package/templates/react-sdk-reference/.ai-common/skills/field-skills/EmbeddedData.md +385 -0
  64. package/templates/react-sdk-reference/.ai-common/skills/field-skills/EmbeddedDataMulti.md +506 -0
  65. package/templates/react-sdk-reference/.ai-common/skills/field-skills/ObjectReference.md +549 -86
  66. package/templates/react-sdk-reference/.ai-common/skills/field-skills/UserReference.md +181 -83
  67. package/templates/react-sdk-reference/.ai-common/skills/infra-components.md +13 -1
  68. package/templates/react-sdk-reference/.ai-common/skills/portal-flow/run-and-verify-portal.md +290 -0
  69. package/templates/react-sdk-reference/.ai-common/skills/template-components.md +13 -1
  70. package/templates/react-sdk-reference/.ai-common/skills/template-skills/ListView.md +125 -153
  71. package/templates/react-sdk-reference/.ai-common/skills/template-skills/SimpleTable.md +90 -81
  72. package/templates/react-sdk-reference/.ai-common/skills/widget-components.md +13 -1
  73. package/templates/react-sdk-reference/assets/icons/trash.svg +3 -0
  74. package/templates/react-sdk-reference/index.html +0 -1
  75. package/templates/react-sdk-reference/package.json +2 -2
  76. package/templates/react-sdk-reference/package.minimal.json +2 -2
  77. package/templates/react-sdk-reference/sdk-config.json +3 -3
  78. package/templates/react-sdk-reference/src/FallbackComponent.tsx +1 -1
  79. package/templates/react-sdk-reference/src/MashupApp.tsx +33 -78
  80. package/templates/react-sdk-reference/src/PortalApp.tsx +23 -100
  81. package/templates/react-sdk-reference/src/components/component-map.ts +15 -1
  82. package/templates/react-sdk-reference/src/components/designSystemExtension/AssignmentHeader/AssignmentHeader.tsx +15 -0
  83. package/templates/react-sdk-reference/src/components/designSystemExtension/AssignmentHeader/index.tsx +1 -0
  84. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldGroup/FieldGroup.tsx +1 -1
  85. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldGroupList/FieldGroupList.tsx +1 -1
  86. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldValueList/FieldValueList.tsx +16 -4
  87. package/templates/react-sdk-reference/src/components/designSystemExtension/ModalDialog/ModalDialog.tsx +26 -0
  88. package/templates/react-sdk-reference/src/components/designSystemExtension/ModalDialog/index.tsx +1 -0
  89. package/templates/react-sdk-reference/src/components/designSystemExtension/Toast/Toast.tsx +35 -0
  90. package/templates/react-sdk-reference/src/components/designSystemExtension/Toast/index.tsx +1 -0
  91. package/templates/react-sdk-reference/src/components/field/AutoComplete/AutoComplete.tsx +362 -24
  92. package/templates/react-sdk-reference/src/components/field/CancelAlert/CancelAlert.tsx +1 -1
  93. package/templates/react-sdk-reference/src/components/field/Checkbox/Checkbox.tsx +3 -1
  94. package/templates/react-sdk-reference/src/components/field/Currency/Currency.tsx +6 -3
  95. package/templates/react-sdk-reference/src/components/field/Date/Date.tsx +2 -1
  96. package/templates/react-sdk-reference/src/components/field/DateTime/DateTime.tsx +2 -1
  97. package/templates/react-sdk-reference/src/components/field/Decimal/Decimal.tsx +4 -3
  98. package/templates/react-sdk-reference/src/components/field/Dropdown/Dropdown.tsx +2 -0
  99. package/templates/react-sdk-reference/src/components/field/Email/Email.tsx +2 -1
  100. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/EmbeddedDataMulti.tsx +121 -0
  101. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/config-ext.json +7 -0
  102. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/index.tsx +1 -0
  103. package/templates/react-sdk-reference/src/components/field/Integer/Integer.tsx +2 -1
  104. package/templates/react-sdk-reference/src/components/field/Location/Location.tsx +1 -1
  105. package/templates/react-sdk-reference/src/components/field/Multiselect/Multiselect.tsx +40 -20
  106. package/templates/react-sdk-reference/src/components/field/ObjectReference/ObjectReference.tsx +554 -49
  107. package/templates/react-sdk-reference/src/components/field/ObjectReference/utils.ts +111 -20
  108. package/templates/react-sdk-reference/src/components/field/Percentage/Percentage.tsx +4 -3
  109. package/templates/react-sdk-reference/src/components/field/Phone/Phone.tsx +2 -1
  110. package/templates/react-sdk-reference/src/components/field/SelectableCard/SelectableCard.tsx +2 -1
  111. package/templates/react-sdk-reference/src/components/field/TextArea/TextArea.tsx +2 -1
  112. package/templates/react-sdk-reference/src/components/field/TextInput/TextInput.tsx +2 -1
  113. package/templates/react-sdk-reference/src/components/field/Time/Time.tsx +2 -1
  114. package/templates/react-sdk-reference/src/components/field/URL/URL.tsx +2 -1
  115. package/templates/react-sdk-reference/src/components/field/UserReference/UserReference.tsx +1 -1
  116. package/templates/react-sdk-reference/src/components/helpers/field-utils.ts +44 -0
  117. package/templates/react-sdk-reference/src/components/helpers/simpleTableHelpers.ts +19 -7
  118. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/DataViewActionButtons/DataViewActionButtons.tsx +97 -0
  119. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/DataViewActionButtons/index.tsx +1 -0
  120. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/ListViewActionButtons/ListViewActionButtons.tsx +53 -0
  121. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/ListViewActionButtons/index.tsx +1 -0
  122. package/templates/react-sdk-reference/src/components/template/AdvancedSearch/SearchGroups/SearchGroups.tsx +2 -2
  123. package/templates/react-sdk-reference/src/components/template/CaseSummary/CaseSummary.tsx +3 -1
  124. package/templates/react-sdk-reference/src/components/template/DataReference/SearchForm.tsx +4 -4
  125. package/templates/react-sdk-reference/src/components/template/HierarchicalForm/HierarchicalForm.tsx +2 -2
  126. package/templates/react-sdk-reference/src/components/template/InlineDashboard/InlineDashboard.tsx +1 -1
  127. package/templates/react-sdk-reference/src/components/template/ListView/ListView.tsx +7 -3
  128. package/templates/react-sdk-reference/src/components/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +173 -99
  129. package/templates/react-sdk-reference/src/components/template/SimpleTable/SimpleTableSelect/SimpleTableSelect.tsx +63 -56
  130. package/templates/react-sdk-reference/src/components/widget/ToDo/ToDo.tsx +1 -1
  131. package/templates/react-sdk-reference/vite.config.ts +26 -4
  132. package/templates/react-sdk-reference/.ai-common/instructions/dse-component.md +0 -47
  133. package/templates/react-sdk-reference/.ai-common/instructions/field-component.md +0 -50
  134. package/templates/react-sdk-reference/.ai-common/instructions/infra-component.md +0 -76
  135. package/templates/react-sdk-reference/.ai-common/instructions/template-component.md +0 -43
  136. package/templates/react-sdk-reference/.ai-common/instructions/widget-component.md +0 -45
  137. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/authenticate.md +0 -311
  138. package/templates/react-sdk-reference/pega-constellationjs-0.26.3-local.tgz +0 -0
  139. package/templates/react-sdk-reference/pega-sdk-react-0.1.0.tgz +0 -0
@@ -1,6 +1,6 @@
1
1
  # Skill: UserReference
2
2
 
3
- User picker field that renders as either a search box (AutoComplete) or a dropdown, populated from the Pega operators data page.
3
+ User picker field that binds to a Pega case property, backed by a data page of operators.
4
4
 
5
5
  > **Prerequisite skill:** [`field-components.md`](../field-components.md) — covers architecture, input contract, display modes, event handling, and registration patterns common to ALL field components.
6
6
 
@@ -8,7 +8,7 @@ User picker field that renders as either a search box (AutoComplete) or a dropdo
8
8
 
9
9
  ## Component Purpose
10
10
 
11
- Renders a user selection field. Can display as a typeahead search box or a dropdown list of Pega users. Resolves user IDs to display names for read-only and display modes. Optimized with shallow comparison to avoid unnecessary re-renders.
11
+ Renders a user selection field. With the current field-configuration UI it is always set up as a searchable typeahead picker backed by a data page of operators (or another selected data page). Resolves the raw stored identifier to a human-readable display name for read-only and display presentations. Skips redundant re-rendering when unrelated inputs change.
12
12
 
13
13
  ## Pega Metadata
14
14
 
@@ -16,114 +16,178 @@ Renders a user selection field. Can display as a typeahead search box or a dropd
16
16
  - **Type / Subtype:** `Field` / `Text-UserReference`
17
17
  - **Registration key:** `UserReference` (in the project's component map)
18
18
 
19
+ ### Configuration Settings → Config Keys
20
+
21
+ The Configure Field dialog for this field type exposes the following controls, and each one emits the config key(s) listed below into the view metadata. Every value below arrives at the component already resolved by the runtime — see Annotation Prefixes and Condition Encoding for what "resolved" means.
22
+
23
+ | Configuration control | Emitted config key(s) | Value shape and notes |
24
+ | -------------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
25
+ | Display As | `displayAs` | Always `"Search box"` with the current configuration UI — the control is permanently disabled there. Treat this as a fixed fact about the field type, not a real choice. |
26
+ | Label | `labelOption` + `label` | `labelOption` is `"default"` when the field's own name is kept (emitted as plain text) or `"custom"` when custom text is supplied (emitted with the localization marker). Always render the resolved `label` value; never branch rendering on `labelOption`. |
27
+ | Edit mode | `readOnly` | Absent (Auto), `true` (Read-only), an expression-marked string (Read-only on a Custom Condition), or a When-Rule-marked string (Read-only via a When Rule). See Condition Encoding. |
28
+ | Data page | `referenceList` | The rule name of the selected data page — not the friendly label shown in the picker. This is fully configurable; never assume a fixed data page. |
29
+ | Parameters | `parameters` | A flat object whose keys are the parameter names defined by the selected data page's own rule (the set of names differs per data page) and whose values may be a plain literal, a property reference, or an environment reference (see Annotation Prefixes). Present only when at least one parameter has a value; a parameter that is configured but left empty is emitted as an empty string and must be treated as not provided. |
30
+ | Placeholder | `placeholder` | The built-in default prompt is emitted as plain text; a custom placeholder is emitted with the localization marker. |
31
+ | Helper text | `helperText` | Emitted with the localization marker when configured; absent otherwise. |
32
+ | Show field input warning | `showFieldMessage` + `messageConfig` | Enabling the checkbox emits `showFieldMessage: true` plus a `messageConfig` object with a `content` field (the localization-marked warning text, including any literal quote characters that were typed into it) and its own nested `visibility` field controlling when the warning itself should appear, encoded exactly like the top-level Condition Encoding. This nested `visibility` governs only the warning message, not the field itself — do not confuse the two. |
33
+ | Show as formatted text | `showAsFormattedText` | Boolean; only meaningful when the field is read-only (see Behavioral Contract). |
34
+ | Required / Disabled / Visibility | `required` / `disabled` / `visibility` | Each encoded per Condition Encoding below. Visibility's extra choices (shown as "if not blank" or "if not zero") are convenience options in the configuration UI that compile down to the same expression encoding, evaluated against the field's own bound value — they introduce no new value shape. |
35
+ | Test ID | `testId` | A plain, non-localized string. |
36
+
37
+ ### Annotation Prefixes
38
+
39
+ The runtime resolves every one of the following markers before the component ever receives its inputs. The component must consume the already-resolved value and must never itself parse, strip, or evaluate these markers:
40
+
41
+ - a **localization** marker on user-facing text (labels, placeholders, helper text, warning messages)
42
+ - a **property reference** marker on values sourced from another field on the case
43
+ - an **environment reference** marker on values sourced from application/operator environment information — this is the encoding actually used when a parameter's source is set to reference an operator attribute; despite that wording in the configuration UI, the resolved marker is an environment reference, not an operator-scoped one, so do not assume otherwise
44
+ - an **expression** marker on values computed from a custom condition
45
+ - a **When Rule** marker on values that reference a named decision rule
46
+ - a **user reference** marker on the field's own bound value, identifying it as a reference to an operator
47
+
48
+ Whenever a configuration picker displays a friendly label (a rule's description, a case field's display name, a data page's description), the underlying configuration stores the rule or property NAME instead of that label. Never assume one can be reconstructed from the other — treat both as opaque, independently-sourced strings.
49
+
50
+ ### Condition Encoding
51
+
52
+ State this rule once and apply it everywhere it is relevant: `readOnly`, `required`, `disabled`, `visibility`, and the nested field-warning `visibility` can each arrive in one of six shapes — absent, the boolean `true`, the boolean `false`, an empty string, an expression-marked string, or a When-Rule-marked string. All six are already resolved to a plain boolean by the time the component receives the input. Consequences for a generated component:
53
+
54
+ - Treat every one of these inputs as a plain boolean type. Never inspect its raw string form, and never treat a non-empty string as automatically true (doing so would make an expression- or rule-based setting permanently active).
55
+ - Treat an absent value as equivalent to that setting's documented default, and treat an explicitly-set default value (for example an explicit `false`) exactly the same as an absent key. Never use key presence alone as a signal that a setting was deliberately changed.
56
+ - Treat an empty string the same way. It means the setting was never given a value, not that it was set to something falsy — so it must resolve to the setting's default rather than being read as a present-but-empty value.
57
+
58
+ ### Generation Rules
59
+
60
+ Guardrails that a generated component must follow to correctly honor every combination of settings:
61
+
62
+ 1. Use the data page named in `referenceList` as the source of selectable options; fall back to `PCore.getEnvironmentInfo().getDefaultOperatorDP()` only when `referenceList` is absent.
63
+ 2. Forward the `parameters` object to the datasource lookup unchanged, which means using `PCore.getDataApiUtils().getData(dataPageName, payload, context)` rather than a call that accepts no parameter payload. Never assume a fixed set of parameter names, and never send an empty-string parameter value as though it were provided.
64
+ 3. Apply mode precedence: while the field is read-only, ignore any configured `required`, `disabled`, `placeholder`, or field-warning settings even if those keys are still present in the metadata — they are stale leftovers from when the field was last editable, not active settings.
65
+ 4. Ensure the resolved `disabled` state genuinely prevents interaction with the rendered control, rather than simply being accepted as an unused input.
66
+ 5. Implement the field-warning contract as its own pair: only show a warning when `showFieldMessage` is true, and when it is, display the resolved `messageConfig` content, gated by the resolved `messageConfig` visibility — which is independent of the field's own visibility and must not be conflated with it.
67
+ 6. Never implement custom show/hide logic driven by the `visibility` setting. A field whose visibility resolves to false is not rendered at all by the surrounding runtime, so the component does not need to and should not handle that case itself.
68
+ 7. Resolve and display the user's name — not just the raw identifier — on every read-only and display-only rendering path, not only the one gated by "show as formatted text"; otherwise some read-only presentations will show an empty value instead of the user's name.
69
+ 8. Do not assume the fields used to search and display results are operator-specific. `pyUserName` and `pyUserIdentifier` are only guaranteed to exist when the configured data page is the operator list; a different data page requires resolving different fields generically rather than hardcoding these operator-specific property names.
70
+ 9. Treat the typeahead/search presentation as the only reachable rendering path for this field type. Do not build, wire, or rely on a separate dropdown-list rendering path, since the current configuration UI cannot produce the setting that would select it.
71
+ 10. Confirm this component's registry dependencies actually exist before relying on them. This component renders nothing of its own — it resolves a search/typeahead component and a value-display component out of the component registry — so if either is missing from the registry, this component silently renders nothing. See Registry Dependency Prerequisite below; generate and register any missing dependency before finishing this component.
72
+
19
73
  ## Inputs (component-specific)
20
74
 
21
75
  > Extends the project's base component interface (NOT the field input contract — field-specific inputs are defined manually).
22
76
 
23
- | Prop | Type | Default | Description |
24
- | --------------------- | -------------------- | ---------- | ---------------------------------------------------------------- |
25
- | `displayAs` | `string` (optional) | `''` | `'Drop-down list'` or `'Search box'` — determines the input type |
26
- | `displayMode` | `string` (optional) | `''` | `'DISPLAY_ONLY'` or `'STACKED_LARGE_VAL'` |
27
- | `label` | `string` (optional) | `''` | Field label |
28
- | `value` | `any` (optional) | `''` | Raw value from Pega store (may be a user object or string ID) |
29
- | `testId` | `string` (optional) | `''` | Test identifier |
30
- | `placeholder` | `string` (optional) | `''` | Placeholder text |
31
- | `helperText` | `string` (optional) | `''` | Helper text |
32
- | `disabled` | `boolean` (optional) | `false` | |
33
- | `readOnly` | `boolean` (optional) | `false` | |
34
- | `required` | `boolean` (optional) | `false` | |
35
- | `validatemessage` | `string` (optional) | `''` | Validation error message |
36
- | `showAsFormattedText` | `boolean` (optional) | `false` | When `true` in read-only mode, show formatted user name text |
37
- | `additionalProps` | `object` (optional) | `{}` | Extra inputs forwarded to the child component |
38
- | `hideLabel` | `boolean` (optional) | `false` | |
39
- | `variant` | `string` (optional) | `'inline'` | Layout variant |
40
- | `onChange` | `any` (optional) | — | Change handler (passed through to child) |
77
+ | Input | Type | Default | Description |
78
+ | --------------------- | -------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------- |
79
+ | `displayAs` | `string` (optional) | `''` | Always arrives as `'Search box'`; informational only, do not branch rendering on it |
80
+ | `displayMode` | `string` (optional) | `''` | `'DISPLAY_ONLY'` or `'STACKED_LARGE_VAL'` |
81
+ | `label` | `string` (optional) | `''` | Field label, already resolved (any localization marker already removed by the runtime) |
82
+ | `value` | `any` (optional) | `''` | Raw value from Pega store (may be a user object or string ID) |
83
+ | `status` | `string` (optional) | — | `'error'` or `'warning'` — drives validation-state styling |
84
+ | `testId` | `string` (optional) | `''` | Test identifier |
85
+ | `placeholder` | `string` (optional) | `''` | Placeholder text, already resolved |
86
+ | `helperText` | `string` (optional) | `''` | Helper text, already resolved |
87
+ | `disabled` | `boolean` (optional) | `false` | |
88
+ | `readOnly` | `boolean` (optional) | `false` | Already-resolved boolean regardless of whether it was set to Always, a Custom Condition, or a When Rule |
89
+ | `required` | `boolean` (optional) | `false` | Already-resolved boolean |
90
+ | `validatemessage` | `string` (optional) | `''` | Validation error message; takes precedence over `helperText` when both are present |
91
+ | `showAsFormattedText` | `boolean` (optional) | `false` | Meaningful only when `readOnly` is `true` — see Behavioral Contract |
92
+ | `referenceList` | `string` (optional) | — | The configured data page name; source of options for the picker |
93
+ | `parameters` | `object` (optional) | — | Flat name-to-value map of data-page parameters; names and required-ness are defined by the selected data page, not by this field |
94
+ | `showFieldMessage` | `boolean` (optional) | `false` | Enables the field-warning contract |
95
+ | `messageConfig` | `object` (optional) | — | Field-warning content and its own independent visibility |
96
+ | `labelOption` | `string` (optional) | `'default'` | `'default'` or `'custom'`; informational only — always render the resolved `label` |
97
+ | `visibility` | `boolean` (optional) | `true` | Already-resolved boolean; the component is typically never rendered at all when this is `false` |
98
+ | `additionalProps` | `object` (optional) | `{}` | Extra inputs forwarded to the child component |
99
+ | `hideLabel` | `boolean` (optional) | `false` | |
100
+ | `variant` | `string` (optional) | `'inline'` | Layout variant |
101
+ | `onChange` | `any` (optional) | — | Change handler (passed through to child) |
41
102
 
42
103
  ## Implementation Structure
43
104
 
44
- Orchestrator component — renders either AutoComplete, Dropdown, formatted text, or FieldValueList based on mode. Wrapped in a memoization wrapper with a custom comparison function.
105
+ Orchestrator component — it renders no input control itself, but instead delegates to a registered search/typeahead component, a registered formatted-text/value-display component, or an inline label-plus-name block, depending on mode. It also skips redundant re-rendering when its inputs have not meaningfully changed.
106
+
107
+ ### Registry Dependency Prerequisite
108
+
109
+ > **Check this before writing the component.** Because this component only orchestrates other components, it cannot work unless its dependencies are already generated and registered.
110
+
111
+ The components it resolves from the registry — the search/typeahead component (registry key `AutoComplete`), the value-display component (registry key `FieldValueList`), and, only if the legacy path is retained, the dropdown/select component (registry key `Dropdown`) — are **not** guaranteed to exist. Tooling that discovers components by walking a case's view metadata will not find them, because they never appear as fields in that metadata; they are internal building blocks that only this component (and others like it) reach for at runtime. So a discovery-driven generation pass can produce `UserReference` while silently omitting everything it depends on.
112
+
113
+ The failure this causes is quiet: the registry lookup returns nothing, and the field renders as blank with no error. Do not assume a missing dependency will announce itself.
45
114
 
46
- **Module Setup:** The component depends on the project's component registry (to resolve `AutoComplete`, `Dropdown`, and `FieldValueList`) and local utility helpers (`getUserId` and `isUserNameAvailable`). It also uses `PCore.getUserApi()`, `PCore.getRestClient()`, and `PCore.getEnvironmentInfo()` for user data resolution. Define two constants: `DROPDOWN_LIST = 'Drop-down list'` and `SEARCH_BOX = 'Search box'`. Define the input contract as an extension of the project's base component interface with all the optional fields listed in the inputs table above.
115
+ Before finishing this component:
47
116
 
48
- **Main Component Logic** (defined as an arrow function, not a plain function declaration) — steps in order:
117
+ 1. Check whether each required registry key is already registered in the project's component map, or was generated earlier in the current session.
118
+ 2. For any key that is missing, generate that component from its own skill file and register it under its expected key.
119
+ 3. Only then wire this component to resolve them.
49
120
 
50
- 1. **Registry lookups** — resolve `AutoComplete`, `Dropdown`, and `FieldValueList` via the project's component registry.
51
- 2. **Receive inputs (all with defaults)** — `label` (default `''`), `displayAs` (default `''`), `displayMode` (default `''`), `getPConnect`, `value` (default `''`), `testId` (default `''`), `helperText` (default `''`), `validatemessage` (default `''`), `placeholder` (default `''`), `showAsFormattedText` (default `false`), `additionalProps` (default `{}`), `hideLabel` (default `false`), `readOnly` (default `false`), `required` (default `false`), `disabled` (default `false`), `onChange`.
52
- 3. **Local state** — `dropDownDataSource` (array, default `[]`) and `userName` (string, default `''`).
53
- 4. **Derived values** — `OPERATORS_DP = PCore.getEnvironmentInfo().getDefaultOperatorDP()` (the default operators data page name) and `userId = getUserId(value)`.
54
- 5. **Mount/update effect** — a lifecycle effect with dependencies `[displayAs, readOnly, showAsFormattedText, value]`, handling two cases (see Behavioral Contract below for the exact branching logic): resolving the display username when in read-only formatted-text mode, or fetching the dropdown data source when `displayAs === 'Drop-down list'`.
55
- 6. **Rendering decision tree** (see Behavioral Contract below for the exact order): `DISPLAY_ONLY` returns `FieldValueList(userName || '')`; `STACKED_LARGE_VAL` returns the stacked variant; read-only formatted text mode returns a label + username text block; `'Search box'` mode renders `AutoComplete`; `'Drop-down list'` mode renders `Dropdown`.
121
+ Apply the same check to any component that is itself an orchestrator — a missing leaf dependency several levels down produces the same blank render.
56
122
 
57
- **Export:** wrap the component in a memoization wrapper with a custom comparison function (see "Re-render optimization" below).
123
+ **Module Setup:** The component depends on the project's component registry (to resolve the registered search/typeahead component and the registered value-display component) and on local utility helpers for extracting a user identifier from the value and for checking whether a display name is already present on the value. It also depends on three Pega Platform APIs, all reached through the global `PCore` object and detailed in the Pega Platform APIs section below: `PCore.getEnvironmentInfo().getDefaultOperatorDP()`, `PCore.getUserApi().getOperatorDetails(userId)`, and `PCore.getDataApiUtils().getData(dataPageName, payload, context)`. Recognize that `displayAs` can in principle carry either of its two known values, but only one of them (the search/typeahead value) is reachable through the current configuration UI — see Generation Rules. Define the input contract as an extension of the project's base component interface with every optional field listed in the Inputs table above, including the previously-unused `referenceList`, `parameters`, `showFieldMessage`, and `messageConfig`.
124
+
125
+ **Main Component Logic** — steps in order:
126
+
127
+ 1. **Registry lookups** — resolve the registered search/typeahead component and the registered value-display component via the project's component registry. See Registry Dependency Prerequisite above — these must already be generated and registered, or the field renders blank.
128
+ 2. **Receive inputs (all with defaults)** — every input listed in the Inputs table, each defaulted as documented there.
129
+ 3. **Local state** — a resolved-display-name value (initially empty) and, only for the legacy dropdown-list path, a fetched options list (initially empty).
130
+ 4. **Derived values** — resolve which data page to query: the configured `referenceList` when present, otherwise the value returned by `PCore.getEnvironmentInfo().getDefaultOperatorDP()`; and resolve the user identifier from the raw `value` using the identifier-extraction helper.
131
+ 5. **Asynchronous resolution step** — work that runs once when the component is first displayed, and again whenever the resolved identifier, read-only state, formatted-text flag, or value changes. It resolves the display name needed for every read-only and display presentation (see Behavioral Contract), and — unlike a naïve implementation — also resolves the field-warning message and its visibility when the field warning is enabled. Use whatever mechanism the target framework provides for running side effects in response to changed inputs.
132
+ 6. **Rendering decision tree** (see Behavioral Contract below for the exact order): a display-only mode renders the value-display component with the resolved name; a stacked display mode renders its stacked variant; read-only with formatted text renders the inline label-plus-name block; otherwise render the search/typeahead component, passing through the resolved datasource and parameters.
133
+
134
+ **Expose the component** with the re-render-skipping behavior described under "Re-render optimization" below applied to it, using whatever change-detection mechanism the target framework provides.
58
135
 
59
136
  ## Behavioral Contract
60
137
 
61
138
  ### User ID extraction
62
139
 
63
- `getUserId(value)` — utility that extracts the user identifier from the value (which may be a plain string or a user object with an ID property).
140
+ An identifier-extraction helper reads the user identifier out of the value, which may be a plain string or a user object carrying an identifier property.
64
141
 
65
142
  ### State
66
143
 
67
- - `dropDownDataSource` (array): populated when `displayAs === 'Drop-down list'`
68
- - `userName` (string): resolved display name for formatted text mode
144
+ - A fetched options list, populated only on the legacy, no-longer-configurable dropdown-list path.
145
+ - A resolved display name, used by every read-only and display presentation.
69
146
 
70
- ### Mount effect: lifecycle effect watching `[displayAs, readOnly, showAsFormattedText, value]`
147
+ ### Asynchronous resolution
71
148
 
72
- **Case 1: `userId && readOnly && showAsFormattedText`**
149
+ This work runs once when the component is first displayed, and again whenever the resolved identifier, read-only state, formatted-text flag, or value changes. It handles two situations:
73
150
 
74
- - If `isUserNameAvailable(value)`: `setUserName(value.userName)` — username already in value object
75
- - Else: call `PCore.getUserApi().getOperatorDetails(userId)` and extract `pyUserName` from response
151
+ **Resolving the display name** — needed whenever the field is being shown in a read-only or display presentation (not only when "show as formatted text" is checked; see Generation Rules). If the value already carries a display name, use it directly. Otherwise, call `PCore.getUserApi().getOperatorDetails(userId)` with the resolved identifier and read the display name from `pyUserName` inside the `pyOperatorInfo` object on the resolved response's `data` property.
76
152
 
77
- **Case 2: `displayAs === 'Drop-down list'`**
153
+ **Resolving the field-warning content** — when the field warning is enabled, resolve its message text and its own independent visibility so they are ready before the warning needs to be shown.
78
154
 
79
- - Call `PCore.getRestClient().invokeRestApi('getListData', { queryPayload: { dataViewName: OPERATORS_DP } })`
80
- - Map results to `{key: pyUserIdentifier, value: pyUserName}` array
81
- - `setDropDownDataSource(mapped)`
82
-
83
- `OPERATORS_DP = PCore.getEnvironmentInfo().getDefaultOperatorDP()` — the default operators data page name.
155
+ The legacy dropdown-list path (no longer producible through configuration) additionally fetches a full list of users by calling `PCore.getRestClient().invokeRestApi('getListData', { queryPayload: { dataViewName } })` and maps each row from the resolved response's nested `data.data` array into an option keyed by `pyUserIdentifier` with `pyUserName` as its display value.
84
156
 
85
157
  ### Rendering decision tree
86
158
 
87
- Evaluated in this order: if `displayMode === 'DISPLAY_ONLY'`, render `FieldValueList(userName || '')`; else if `displayMode === 'STACKED_LARGE_VAL'`, render the stacked `FieldValueList` variant; else if `readOnly && showAsFormattedText && userId`, render the formatted text block; else if `displayAs === 'Search box'`, render the `AutoComplete` component; else if `displayAs === 'Drop-down list'`, render the `Dropdown` component.
88
-
89
- ### Subsection: Search box mode (`displayAs === 'Search box'`)
159
+ Evaluated in this order: a display-only mode renders the value-display component with the resolved display name; a stacked display mode renders that same component's stacked variant; being read-only with "show as formatted text" enabled and an identifier present renders the inline label-plus-name block; otherwise render the search/typeahead component using the resolved datasource, resolved parameters, and resolved identifier.
90
160
 
91
- Render `AutoComplete` with hardcoded columns for operator search: a primary column on `pyUserName` (displayed, used for search, marked primary), and a secondary key column on `pyUserIdentifier` (displayed, used for search, marked secondary, with `setProperty: 'Associated property'` and `key: 'true'`).
161
+ ### Subsection: Search/typeahead presentation
92
162
 
93
- Inputs: `datasource` set to `OPERATORS_DP`, `listType='datapage'`, `value` set to `userId`, plus label/placeholder/readOnly/disabled/required/helperText/validatemessage/hideLabel/onChange/additionalProps/testId.
163
+ This is the only presentation the current configuration UI can produce. Render the registered search/typeahead component using the datasource resolved in step 4 (the configured `referenceList`, or `PCore.getEnvironmentInfo().getDefaultOperatorDP()` as a fallback) and the parameters resolved from the `parameters` setting. Configure the search/select columns generically rather than assuming operator-specific field names: when the datasource is known to be the operator list, a display column and a paired identifier column — `pyUserName` and `pyUserIdentifier` respectively — are appropriate; for any other configured data page, resolve equivalent display and identifier columns from that data page's own shape instead of assuming these operator-specific names apply.
94
164
 
95
- ### Subsection: Dropdown mode (`displayAs === 'Drop-down list'`)
165
+ Also pass through: label, placeholder, read-only state, disabled state, required state, helper text, validation message, hide-label flag, change handler, additional inputs, and test id.
96
166
 
97
- Render `Dropdown` with:
167
+ ### Subsection: Legacy dropdown-list presentation (no longer producible through configuration)
98
168
 
99
- - `datasource={dropDownDataSource}` (fetched user list)
100
- - `listType='associated'`
101
- - `value={userId}`
102
- - Plus same field inputs as above
169
+ A dropdown-style presentation exists in the reference implementation for backward compatibility with views built before the current configuration UI, but the control that would select it is now permanently fixed to the search/typeahead value. Do not implement this as a co-equal alternative path when generating a new component; treat the search/typeahead presentation as the sole target, and only preserve a dropdown fallback if there is a concrete need to support pre-existing views that still carry the legacy value.
103
170
 
104
- ### Subsection: Formatted text read-only (`readOnly && showAsFormattedText && userId`)
171
+ ### Subsection: Formatted text read-only presentation
105
172
 
106
- Render a small wrapper containing a caption-style text element showing `label`, followed by a body-style text element showing `userName`.
173
+ Render a small block containing a caption-style text element showing the label, followed by a body-style text element showing the resolved display name.
107
174
 
108
175
  ### Re-render optimization
109
176
 
110
- Export with a memoization wrapper using a custom comparison function that returns `true` (skip re-render) only when all of the following are equal between previous and next inputs: `getUserId(value)` (resolved on both sides), `validatemessage`, `required`, `disabled`, and `readOnly`.
177
+ The component should re-render only when something it actually displays has changed. Skip the re-render only when every one of the following is unchanged between the previous and next inputs: the resolved user identifier, the validation message, the required state, the disabled state, the read-only state, and — to correct a gap in the original approach — the displayed text inputs as well (label, placeholder, helper text, and test id), so that configured text changes always repaint. Express this with whatever change-detection mechanism the target framework offers; the comparison list above is the contract, not the mechanism.
111
178
 
112
179
  ## Display Mode Rendering
113
180
 
114
- Uses resolved `userName` (not raw `value`):
181
+ Both display-only and stacked-display modes render through the registered value-display component, passing the resolved display name (not the raw value), so the same identifier-to-name resolution used for formatted-text mode is reused here too. For the stacked mode, additionally request the value-display component's stacked layout.
115
182
 
116
- - **`DISPLAY_ONLY`:** `<FieldValueList name={hideLabel ? '' : label} value={userName || ''} />`
117
- - **`STACKED_LARGE_VAL`:** `<FieldValueList name={hideLabel ? '' : label} value={userName || ''} variant='stacked' />`
118
-
119
- `userName` may still be empty string while the async `getOperatorDetails` call resolves — this is expected.
183
+ The value-display component shows a placeholder dash sequence when given an empty or undefined value, rather than rendering nothing — so the resolved display name must genuinely be available before this render happens. Resolve the display name whenever the field is in a display-only or stacked-display mode, not only when it is read-only and showing formatted text; otherwise these presentations will show the placeholder dash sequence instead of the user's name.
120
184
 
121
185
  ## Visual Specifications
122
186
 
123
- The visual appearance is determined by the child component rendered:
187
+ The visual appearance is determined by which presentation is active:
124
188
 
125
- - **Search box**: Same as `AutoComplete` — combobox input with outlined border, floating label
126
- - **Dropdown**: Same as `Dropdown` — select field with outlined border, floating label
189
+ - **Search/typeahead presentation**: combobox input with outlined border, floating label — matching the project's shared typeahead/search component
190
+ - **Legacy dropdown-list presentation**: select field with outlined border, floating label — matching the project's shared dropdown/select component
127
191
  - **Formatted text read-only**:
128
192
 
129
193
  | Property | Value |
@@ -136,31 +200,65 @@ The visual appearance is determined by the child component rendered:
136
200
 
137
201
  ## Edge Cases & Special Logic
138
202
 
139
- - **`getUserId`**: handles both plain string values and object values with an ID property.
140
- - **`isUserNameAvailable`**: checks whether the value object already contains a `userName` property (avoiding unnecessary API call).
141
- - **Async name resolution**: when `userName` is not available in the value object, a REST call is made. The component renders empty initially and updates when the call completes.
142
- - **Drop-down source**: Users are fetched via REST API (`getListData`), not via a data page config — this is different from `AutoComplete`/`Dropdown` field patterns.
143
- - **`onChange` prop** is passed through to the child component unchanged — it's the platform-wired handler.
203
+ - **Identifier extraction**: handles both plain string values and object values with an identifier property.
204
+ - **Display-name availability check**: checks whether the value object already contains a display-name property, avoiding an unnecessary lookup call.
205
+ - **Async name resolution**: when the display name is not already available on the value object, a `PCore.getUserApi().getOperatorDetails(userId)` call is made. The resolved name starts empty and updates once the Promise resolves; any presentation that depends on it should tolerate this brief empty state rather than treating it as an error.
206
+ - **Stale configuration keys**: keys such as `required`, `disabled`, `placeholder`, `showFieldMessage`, or `messageConfig` may still be present in the metadata even after the field has become read-only, because the configuration UI does not necessarily clear a setting's value when its control becomes hidden. Apply the mode-precedence rule from Generation Rules rather than trusting key presence.
207
+ - **Empty parameter values**: a data-page parameter that is configured but left blank is emitted as an empty string rather than omitted entirely; treat it as not provided rather than forwarding it as a real value.
208
+ - **Non-operator data pages**: `pyUserName` and `pyUserIdentifier` are only guaranteed to exist when the configured data page is the operator list. A different configured data page may expose different fields, and those need to be resolved from that data page's own shape rather than assumed.
209
+ - **Field warning independence**: the field-warning contract (`showFieldMessage` / `messageConfig`) is a separate notification channel from validation messaging (`validatemessage`) and helper text (`helperText`); implement it as its own affordance rather than folding it into either of those.
210
+ - **Legacy dropdown-list data source**: when the legacy path is retained, its options come from `PCore.getRestClient().invokeRestApi('getListData', ...)`, which accepts no parameter payload, rather than the parameter-aware `PCore.getDataApiUtils().getData(...)` used by the search/typeahead presentation — keep this distinction if both paths are ever supported side by side.
211
+ - **Missing registry dependencies**: a registry lookup that finds nothing causes a silent blank render, not an error. This is the most likely failure mode when this component is generated by a pass that discovered components from case view metadata, since its dependencies never appear in that metadata. See Registry Dependency Prerequisite.
212
+ - **`onChange` input** is passed through to the child component unchanged — it's the platform-wired handler.
144
213
 
145
214
  ## Dependencies
146
215
 
147
- - A memoization wrapper from the framework.
148
- - Local utility helpers: `getUserId`, `isUserNameAvailable`.
149
- - The project's component registry, resolving `AutoComplete` — for search box mode.
150
- - The project's component registry, resolving `Dropdown` — for dropdown mode.
151
- - The project's component registry, resolving `FieldValueList` — for display modes.
152
- - `PCore.getUserApi().getOperatorDetails()` — for async user name resolution.
153
- - `PCore.getRestClient().invokeRestApi('getListData', ...)` — for dropdown data source.
154
- - `PCore.getEnvironmentInfo().getDefaultOperatorDP()` — for operators data page name.
216
+ > Every registry dependency below must be generated and registered before this component can render — see Registry Dependency Prerequisite.
217
+
218
+ - The target framework's change-detection mechanism for skipping redundant re-renders.
219
+ - Local utility helpers for identifier extraction and display-name availability checking.
220
+ - The project's component registry, resolving the shared search/typeahead component (key `AutoComplete`) — for the search/typeahead presentation.
221
+ - The project's component registry, resolving the shared dropdown/select component (key `Dropdown`) — for the legacy dropdown-list presentation, if retained.
222
+ - The project's component registry, resolving the shared value-display component (key `FieldValueList`) — for display-only and stacked-display presentations.
223
+ - The Pega Platform APIs listed in the next section.
224
+
225
+ ## Pega Platform APIs
226
+
227
+ All of these are reached through the global `PCore` object, which the SDK runtime installs on the window before any component renders. Never import them from a package — read them off `PCore` at the point of use. Each entry below gives the call, what it returns, and how this component uses it.
228
+
229
+ **`PCore.getEnvironmentInfo().getDefaultOperatorDP()`**
230
+
231
+ - Returns: a string — the rule name of the application's default operator data page (a `D_`-prefixed data page listing operators).
232
+ - Synchronous; safe to call during render.
233
+ - Used as the fallback datasource for the picker when the `referenceList` config key is absent. When `referenceList` is present, use that value instead and do not call this.
234
+
235
+ **`PCore.getUserApi().getOperatorDetails(userId)`**
236
+
237
+ - Parameter: `userId` — the operator identifier string extracted from the field's `value`.
238
+ - Returns: a Promise resolving to a response object whose `data` property contains a `pyOperatorInfo` object; the operator's display name is the `pyUserName` property inside it.
239
+ - Used to resolve a raw operator identifier into a human-readable name for every read-only and display presentation. Guard the read — `data`, `pyOperatorInfo`, and `pyUserName` may each be missing — and only set the resolved name when all three are present.
240
+
241
+ **`PCore.getDataApiUtils().getData(dataPageName, payload, context)`**
242
+
243
+ - Parameters: `dataPageName` — the resolved datasource rule name; `payload` — an object carrying the data page's parameters, built from the `parameters` config key; `context` — the current context name, obtained from `getPConnect().getContextName()`.
244
+ - Returns: a Promise resolving to a response object whose rows are at the nested `data.data` array.
245
+ - Used to fetch selectable options when the picker needs its own list, and it is the correct call for honoring the `parameters` config key, because it accepts a parameter payload.
246
+
247
+ **`PCore.getRestClient().invokeRestApi('getListData', { queryPayload: { dataViewName } })`** — legacy only
248
+
249
+ - Parameters: the literal API name `'getListData'` and an options object containing a `queryPayload` whose `dataViewName` is the data page rule name.
250
+ - Returns: a Promise resolving to a response object whose rows are at the nested `data.data` array.
251
+ - Used only by the legacy dropdown-list path. Prefer `PCore.getDataApiUtils().getData(...)` for anything new, since this call takes no parameter payload and therefore cannot honor the `parameters` config key.
155
252
 
156
253
  ## Design System Mapping
157
254
 
158
- **UI control type:** User picker — delegates to AutoComplete or Dropdown for the actual input.
255
+ **UI control type:** User picker — delegates to a shared search/typeahead or dropdown/select component for the actual input.
159
256
 
160
257
  When implementing in a specific design system, map the following:
161
258
 
162
- - **Search box mode** → render the `AutoComplete` component with operator columns
163
- - **Dropdown mode** → render the `Dropdown` component with the fetched operator list
259
+ - **Search/typeahead presentation** → render the shared search/typeahead component, sourced from the configured data page (with the default operator data page as fallback) and the configured parameters, with generically-resolved search/display fields
260
+ - **Legacy dropdown-list presentation** → render the shared dropdown/select component with a fetched option list, retained only for backward compatibility and no longer producible through configuration
164
261
  - **Formatted text read-only** → render a label + text display (caption + body text)
165
- - **Display mode** → render `FieldValueList` with the resolved username
166
- - **Memoization** → wrap the component with a custom comparison to avoid unnecessary re-renders
262
+ - **Display-only / stacked-display presentation** → render the shared value-display component with the resolved display name
263
+ - **Field warning** → map to a secondary/alternate messaging affordance, independent of the error/helper-text region
264
+ - **Re-render skipping** → apply the framework's change-detection mechanism using the comparison list above, which must include the displayed-text inputs so configured text changes are never missed
@@ -108,7 +108,7 @@ When an infrastructure component renders another Pega component, resolve it thro
108
108
 
109
109
  The runtime contract — inputs, callback signatures, derivation logic, and localization — is identical regardless of design system. Only the rendered markup changes.
110
110
 
111
- **1. Check the component-specific skill file** — `{{SKILL_DIR}}/infra-skills/<ComponentName>.md` contains a **Design System Mapping** section. Use it as a starting point.
111
+ **1. Check the component-specific skill file** — `{{SKILL_DIR}}/infra-skills/<ComponentName>{{SKILL_EXT}}` contains a **Design System Mapping** section. Use it as a starting point.
112
112
 
113
113
  **2. If the chosen design system is not covered** — use the component purpose description to identify the appropriate primitives (button, stepper, breadcrumb, divider, list).
114
114
 
@@ -129,6 +129,18 @@ The runtime contract — inputs, callback signatures, derivation logic, and loca
129
129
 
130
130
  ---
131
131
 
132
+ ## Visual Preservation
133
+
134
+ When replacing an existing implementation, the replacement must look the same as the original:
135
+
136
+ 1. **Read the component's companion style file first** (for example a `.css` file in its folder). Note every class's visual intent — spacing, sizing, colours, and layout.
137
+ 2. Reproduce that intent through the new design system's inputs or variants, inline styles, or by keeping the style import — whichever gives the closest match.
138
+ 3. Never silently drop legacy styling utility classes — map each one to an equivalent style.
139
+
140
+ In the embedded flow there is no original to preserve: the customer's look, recorded in the Design Profile, decides instead.
141
+
142
+ ---
143
+
132
144
  ## Registration
133
145
 
134
146
  Register infrastructure overrides in the project's component map under the component's Pega name. Because the SDK's own components are contributed as a spread of built-in entries, **an override must appear after that spread** — an entry listed before it is replaced by the SDK's version and the override silently does nothing.