@pega/sdk 0.0.13 → 0.0.14

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 (48) hide show
  1. package/package.json +1 -1
  2. package/templates/angular-sdk-reference/angular.json +2 -1
  3. package/templates/angular-sdk-reference/package.json +1 -0
  4. package/templates/angular-sdk-reference/pega-constellationjs-0.26.3-local.tgz +0 -0
  5. package/templates/angular-sdk-reference/src/app/app.component.ts +232 -15
  6. package/templates/angular-sdk-reference/src/components/component-map.ts +90 -0
  7. package/templates/angular-sdk-reference/src/components/fields/auto-complete/auto-complete.component.ts +267 -0
  8. package/templates/angular-sdk-reference/src/components/fields/checkbox/checkbox.component.ts +84 -0
  9. package/templates/angular-sdk-reference/src/components/fields/currency/currency.component.ts +97 -0
  10. package/templates/angular-sdk-reference/src/components/fields/date-input/date-input.component.ts +88 -0
  11. package/templates/angular-sdk-reference/src/components/fields/dropdown/dropdown.component.ts +101 -0
  12. package/templates/angular-sdk-reference/src/components/fields/email/email.component.ts +91 -0
  13. package/templates/angular-sdk-reference/src/components/fields/integer/integer.component.ts +93 -0
  14. package/templates/angular-sdk-reference/src/components/fields/phone/phone.component.ts +91 -0
  15. package/templates/angular-sdk-reference/src/components/fields/radio-buttons/radio-buttons.component.ts +102 -0
  16. package/templates/angular-sdk-reference/src/components/fields/text-area/text-area.component.ts +98 -0
  17. package/templates/angular-sdk-reference/src/components/fields/text-input/text-input.component.ts +97 -0
  18. package/templates/angular-sdk-reference/src/components/fields/url-input/url-input.component.ts +94 -0
  19. package/templates/angular-sdk-reference/src/components/infra/assignment/assignment.component.ts +206 -0
  20. package/templates/angular-sdk-reference/src/components/infra/case-summary/case-summary.component.ts +76 -0
  21. package/templates/angular-sdk-reference/src/components/infra/case-view/case-view.component.ts +114 -0
  22. package/templates/angular-sdk-reference/src/components/infra/flow-container/flow-container.component.ts +411 -0
  23. package/templates/angular-sdk-reference/src/components/infra/reference/reference.component.ts +158 -0
  24. package/templates/angular-sdk-reference/src/components/infra/region/region.component.ts +39 -0
  25. package/templates/angular-sdk-reference/src/components/infra/root-container/root-container.component.ts +193 -0
  26. package/templates/angular-sdk-reference/src/components/infra/stages/stages.component.ts +78 -0
  27. package/templates/angular-sdk-reference/src/components/infra/view/view.component.ts +139 -0
  28. package/templates/angular-sdk-reference/src/components/infra/view-container/view-container.component.ts +191 -0
  29. package/templates/angular-sdk-reference/src/components/templates/default-form/default-form.component.ts +101 -0
  30. package/templates/angular-sdk-reference/src/components/templates/narrow-wide/narrow-wide.component.ts +37 -0
  31. package/templates/angular-sdk-reference/src/components/templates/one-column/one-column.component.ts +37 -0
  32. package/templates/angular-sdk-reference/src/components/templates/two-column/two-column.component.ts +37 -0
  33. package/templates/angular-sdk-reference/src/components/templates/wide-narrow/wide-narrow.component.ts +37 -0
  34. package/templates/angular-sdk-reference/src/helpers/event-utils.ts +18 -0
  35. package/templates/angular-sdk-reference/src/helpers/utils.ts +38 -0
  36. package/templates/angular-sdk-reference/src/helpers/versionHelpers.ts +14 -0
  37. package/templates/angular-sdk-reference/tsconfig.json +5 -2
  38. package/templates/react-sdk-reference/.ai-common/agents/embedded-flow-expert.md +11 -4
  39. package/templates/react-sdk-reference/.ai-common/prompts/component-manifest.json +7 -0
  40. package/templates/react-sdk-reference/.ai-common/prompts/generate-all-components.md +3 -1
  41. package/templates/react-sdk-reference/.ai-common/skills/field-components.md +75 -29
  42. package/templates/react-sdk-reference/.ai-common/skills/field-skills/AutoComplete.md +133 -101
  43. package/templates/react-sdk-reference/.ai-common/skills/field-skills/EmbeddedData.md +385 -0
  44. package/templates/react-sdk-reference/.ai-common/skills/field-skills/EmbeddedDataMulti.md +506 -0
  45. package/templates/react-sdk-reference/.ai-common/skills/field-skills/ObjectReference.md +549 -86
  46. package/templates/react-sdk-reference/.ai-common/skills/field-skills/UserReference.md +181 -83
  47. package/templates/react-sdk-reference/.ai-common/skills/template-skills/ListView.md +125 -153
  48. package/templates/react-sdk-reference/.ai-common/skills/template-skills/SimpleTable.md +90 -81
@@ -0,0 +1,101 @@
1
+ /**
2
+ * DefaultForm — renders form fields in a configurable grid layout (1/2/3 columns).
3
+ *
4
+ * Reads NumCols from config to determine grid layout. Children are the form field
5
+ * components rendered via PConnectBridge.
6
+ *
7
+ * Pattern reference: angular-sdk-components DefaultFormComponent + sdk-react DefaultForm
8
+ */
9
+
10
+ /* eslint-disable @typescript-eslint/no-explicit-any */
11
+ import { Component, Input, ChangeDetectorRef, NgZone } from '@angular/core';
12
+ import type { OnInit, OnDestroy } from '@angular/core';
13
+ import { CommonModule } from '@angular/common';
14
+ import type { Unsubscribe } from '@pega/sdk-angular';
15
+ import { PConnectBridgeComponent } from '@pega/sdk-angular';
16
+
17
+ @Component({
18
+ selector: 'pega-default-form',
19
+ standalone: true,
20
+ imports: [CommonModule, PConnectBridgeComponent],
21
+ template: `
22
+ <div
23
+ *ngIf="instructions"
24
+ style="margin-bottom: 0.75rem; color: #6b7280; font-size: 0.875rem;"
25
+ [innerHTML]="instructions"
26
+ ></div>
27
+ <div [style.display]="'grid'" [style.gridTemplateColumns]="gridColumns" [style.gap]="'1rem'">
28
+ <div *ngFor="let getter of childGetters">
29
+ <pconnect-bridge [getPConnect]="getter"></pconnect-bridge>
30
+ </div>
31
+ </div>
32
+ `,
33
+ })
34
+ export class DefaultFormComponent implements OnInit, OnDestroy {
35
+ @Input() props: any;
36
+
37
+ gridColumns = 'repeat(1, minmax(0, 1fr))';
38
+ instructions = '';
39
+ childGetters: Array<() => typeof PConnect> = [];
40
+
41
+ private pConn: any;
42
+ private observable: any;
43
+ private storeUnsub: Unsubscribe | undefined;
44
+
45
+ constructor(
46
+ private ngZone: NgZone,
47
+ private cdr: ChangeDetectorRef,
48
+ ) {}
49
+
50
+ ngOnInit(): void {
51
+ this.pConn = this.props.getPConnect();
52
+ // @ts-ignore
53
+ const { PConnectObservable } = PCore.getInitialiser().getSdkCore() as any;
54
+ this.observable = new PConnectObservable(this.pConn);
55
+ this.updateSelf();
56
+
57
+ this.storeUnsub = this.observable.subscribe(() => {
58
+ this.updateSelf();
59
+ });
60
+ }
61
+
62
+ ngOnDestroy(): void {
63
+ this.storeUnsub?.();
64
+ this.observable?.destroy();
65
+ }
66
+
67
+ private updateSelf(): void {
68
+ const configProps = this.pConn.getConfigProps();
69
+ const numCols = configProps.NumCols ?? '1';
70
+ this.instructions = configProps.instructions ?? '';
71
+
72
+ switch (numCols) {
73
+ case '2':
74
+ this.gridColumns = 'repeat(2, 1fr)';
75
+ break;
76
+ case '3':
77
+ this.gridColumns = 'repeat(3, 1fr)';
78
+ break;
79
+ default:
80
+ this.gridColumns = 'repeat(1, minmax(0, 1fr))';
81
+ break;
82
+ }
83
+
84
+ // Children: first child's children are the actual form fields
85
+ const kids = this.pConn.getChildren?.() ?? [];
86
+ let fields: any[] = [];
87
+ if (kids.length > 0 && kids[0].getPConnect) {
88
+ fields = kids[0].getPConnect().getChildren?.() ?? [];
89
+ } else {
90
+ fields = kids;
91
+ }
92
+
93
+ this.childGetters = fields.map((child: any) => {
94
+ return child.getPConnect ?? (() => child);
95
+ });
96
+
97
+ this.ngZone.run(() => {
98
+ this.cdr.detectChanges();
99
+ });
100
+ }
101
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * NarrowWide — narrow-left/wide-right two-column layout (1:2 ratio).
3
+ *
4
+ * Pattern reference: angular-sdk-components NarrowWideFormComponent + sdk-react NarrowWide
5
+ */
6
+
7
+ /* eslint-disable @typescript-eslint/no-explicit-any */
8
+ import { Component, Input } from '@angular/core';
9
+ import type { OnInit } from '@angular/core';
10
+ import { CommonModule } from '@angular/common';
11
+ import { PConnectBridgeComponent } from '@pega/sdk-angular';
12
+
13
+ @Component({
14
+ selector: 'pega-narrow-wide',
15
+ standalone: true,
16
+ imports: [CommonModule, PConnectBridgeComponent],
17
+ template: `
18
+ <div style="display: grid; grid-template-columns: 1fr 2fr; gap: 1rem;">
19
+ <div *ngFor="let getter of childGetters">
20
+ <pconnect-bridge [getPConnect]="getter"></pconnect-bridge>
21
+ </div>
22
+ </div>
23
+ `,
24
+ })
25
+ export class NarrowWideComponent implements OnInit {
26
+ @Input() props: any;
27
+
28
+ childGetters: Array<() => typeof PConnect> = [];
29
+
30
+ ngOnInit(): void {
31
+ const pConn = this.props.getPConnect();
32
+ const children = pConn.getChildren?.() ?? [];
33
+ this.childGetters = children.map((child: any) => {
34
+ return child.getPConnect ?? (() => child);
35
+ });
36
+ }
37
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * OneColumn — single-column layout template that renders children vertically.
3
+ *
4
+ * Pattern reference: angular-sdk-components OneColumnComponent + sdk-react OneColumn
5
+ */
6
+
7
+ /* eslint-disable @typescript-eslint/no-explicit-any */
8
+ import { Component, Input } from '@angular/core';
9
+ import type { OnInit } from '@angular/core';
10
+ import { CommonModule } from '@angular/common';
11
+ import { PConnectBridgeComponent } from '@pega/sdk-angular';
12
+
13
+ @Component({
14
+ selector: 'pega-one-column',
15
+ standalone: true,
16
+ imports: [CommonModule, PConnectBridgeComponent],
17
+ template: `
18
+ <div style="display: flex; flex-direction: column; gap: 0.25rem;">
19
+ <div *ngFor="let getter of childGetters">
20
+ <pconnect-bridge [getPConnect]="getter"></pconnect-bridge>
21
+ </div>
22
+ </div>
23
+ `,
24
+ })
25
+ export class OneColumnComponent implements OnInit {
26
+ @Input() props: any;
27
+
28
+ childGetters: Array<() => typeof PConnect> = [];
29
+
30
+ ngOnInit(): void {
31
+ const pConn = this.props.getPConnect();
32
+ const children = pConn.getChildren?.() ?? [];
33
+ this.childGetters = children.map((child: any) => {
34
+ return child.getPConnect ?? (() => child);
35
+ });
36
+ }
37
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * TwoColumn — two-column grid layout template.
3
+ *
4
+ * Pattern reference: angular-sdk-components TwoColumnComponent + sdk-react TwoColumn
5
+ */
6
+
7
+ /* eslint-disable @typescript-eslint/no-explicit-any */
8
+ import { Component, Input } from '@angular/core';
9
+ import type { OnInit } from '@angular/core';
10
+ import { CommonModule } from '@angular/common';
11
+ import { PConnectBridgeComponent } from '@pega/sdk-angular';
12
+
13
+ @Component({
14
+ selector: 'pega-two-column',
15
+ standalone: true,
16
+ imports: [CommonModule, PConnectBridgeComponent],
17
+ template: `
18
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;">
19
+ <div *ngFor="let getter of childGetters">
20
+ <pconnect-bridge [getPConnect]="getter"></pconnect-bridge>
21
+ </div>
22
+ </div>
23
+ `,
24
+ })
25
+ export class TwoColumnComponent implements OnInit {
26
+ @Input() props: any;
27
+
28
+ childGetters: Array<() => typeof PConnect> = [];
29
+
30
+ ngOnInit(): void {
31
+ const pConn = this.props.getPConnect();
32
+ const children = pConn.getChildren?.() ?? [];
33
+ this.childGetters = children.map((child: any) => {
34
+ return child.getPConnect ?? (() => child);
35
+ });
36
+ }
37
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * WideNarrow — wide-left/narrow-right two-column layout (2:1 ratio).
3
+ *
4
+ * Pattern reference: angular-sdk-components WideNarrowFormComponent + sdk-react WideNarrow
5
+ */
6
+
7
+ /* eslint-disable @typescript-eslint/no-explicit-any */
8
+ import { Component, Input } from '@angular/core';
9
+ import type { OnInit } from '@angular/core';
10
+ import { CommonModule } from '@angular/common';
11
+ import { PConnectBridgeComponent } from '@pega/sdk-angular';
12
+
13
+ @Component({
14
+ selector: 'pega-wide-narrow',
15
+ standalone: true,
16
+ imports: [CommonModule, PConnectBridgeComponent],
17
+ template: `
18
+ <div style="display: grid; grid-template-columns: 2fr 1fr; gap: 1rem;">
19
+ <div *ngFor="let getter of childGetters">
20
+ <pconnect-bridge [getPConnect]="getter"></pconnect-bridge>
21
+ </div>
22
+ </div>
23
+ `,
24
+ })
25
+ export class WideNarrowComponent implements OnInit {
26
+ @Input() props: any;
27
+
28
+ childGetters: Array<() => typeof PConnect> = [];
29
+
30
+ ngOnInit(): void {
31
+ const pConn = this.props.getPConnect();
32
+ const children = pConn.getChildren?.() ?? [];
33
+ this.childGetters = children.map((child: any) => {
34
+ return child.getPConnect ?? (() => child);
35
+ });
36
+ }
37
+ }
@@ -0,0 +1,18 @@
1
+ // From DX Components src/utils/event-utils.js
2
+
3
+ export function handleEvent(actions: any, eventType: string, propName: string, value: string | boolean | number) {
4
+ switch (eventType) {
5
+ case 'change':
6
+ actions.updateFieldValue(propName, value);
7
+ break;
8
+ case 'blur':
9
+ actions.triggerFieldChange(propName, value);
10
+ break;
11
+ case 'changeNblur':
12
+ actions.updateFieldValue(propName, value);
13
+ actions.triggerFieldChange(propName, value);
14
+ break;
15
+ default:
16
+ break;
17
+ }
18
+ }
@@ -0,0 +1,38 @@
1
+ export function getOptionList(configProps: any, dataObject: any): any[] {
2
+ const listType = configProps.listType;
3
+ let arReturn: any[] = [];
4
+
5
+ if (listType) {
6
+ switch (listType.toLowerCase()) {
7
+ case 'associated':
8
+ // data source should be an array
9
+ if (typeof configProps.datasource === 'object') {
10
+ arReturn = configProps.datasource;
11
+ }
12
+ break;
13
+
14
+ case 'datapage':
15
+ // get data page
16
+ // eslint-disable-next-line no-case-declarations
17
+ const dataPage = configProps.datasource;
18
+ if (typeof dataPage === 'string' && dataObject[dataPage]) {
19
+ alert('need to handle data page');
20
+ } else {
21
+ let listSourceItems = configProps.listOutput;
22
+ if (typeof dataPage === 'object' && !Array.isArray(listSourceItems)) {
23
+ listSourceItems = dataPage.source ? dataPage.source : [];
24
+ }
25
+ (listSourceItems || []).forEach((item: any) => {
26
+ item.value = item.text ? item.text : item.value;
27
+ });
28
+ arReturn = listSourceItems || [];
29
+ }
30
+ break;
31
+
32
+ default:
33
+ break;
34
+ }
35
+ }
36
+
37
+ return arReturn;
38
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * versionHelpers.ts
3
+ *
4
+ * Container helper functions that can identify which version of
5
+ * PCore/PConnect is being run
6
+ */
7
+
8
+ export const sdkVersion = '8.7';
9
+
10
+ export function compareSdkPCoreVersions() {
11
+ // const theConstellationVersion = PCore.getPCoreVersion();
12
+
13
+ console.warn(`Using Constellation version ${PCore.getPCoreVersion()}. Ensure this is the same version as your Infinity server.`);
14
+ }
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "compileOnSave": false,
3
3
  "compilerOptions": {
4
+ "rootDir": "../..",
4
5
  "outDir": "./dist/out-tsc",
5
6
  "forceConsistentCasingInFileNames": true,
6
7
  "strict": true,
7
8
  "noImplicitOverride": true,
8
- "noPropertyAccessFromIndexSignature": true,
9
+ "noPropertyAccessFromIndexSignature": false,
9
10
  "noImplicitReturns": true,
10
11
  "noFallthroughCasesInSwitch": true,
11
12
  "sourceMap": true,
@@ -21,7 +22,9 @@
21
22
  "@pega/sdk-angular": ["../../packages/sdk-angular/src/index.ts"],
22
23
  "@pega/sdk-types": ["../../packages/sdk-types/src/index.ts"]
23
24
  },
24
- "ignoreDeprecations": "5.0"
25
+ "ignoreDeprecations": "5.0",
26
+ "typeRoots": ["../../node_modules/@types", "../../node_modules/@pega"],
27
+ "types": ["pcore-pconnect-typedefs"]
25
28
  },
26
29
  "angularCompilerOptions": {
27
30
  "enableI18nLegacyMessageIdFormat": false,
@@ -90,7 +90,7 @@ Reduce that response to a generatable list by applying the following in order. P
90
90
  2. **Keep components that appear in at least one lifecycle view.** A view is out-of-the-box, and therefore not part of the case lifecycle, when its name begins with `py` or `pz`, or when it is `CaseHistory`. Keep a component if it appears in **at least one** view that is not out-of-the-box. A component may legitimately appear in both kinds of view — one lifecycle view is enough to keep it. Drop a component only when every view it appears in is out-of-the-box.
91
91
 
92
92
  3. **Strip what is never generated, wherever it appears.** This rule is independent of point 2 and applies even to components that passed it:
93
- - Structural wrappers the SDK's registry already provides and that render nothing of their own: View, Region, FlowContainer, Assignment, CaseView, RootContainer. Templates traverse through these to reach their children rather than rendering them, so there is no visual contract to implement.
93
+ - Structural wrappers the SDK's registry already provides and that render nothing of their own: View, Region, FlowContainer, Assignment, CaseView, RootContainer, and reference nodes. Templates traverse through these to reach their children rather than rendering them, so there is no visual contract to implement. A reference node resolves a view by name — including the one an embedded record uses for its inline form — and the runtime already handles it.
94
94
  - Any component whose name starts with `px` (internal Pega infrastructure)
95
95
  - Chrome the SDK adapter provides and that is never generated: NavBar, DeferLoad, VerticalTabs, DashboardFilter
96
96
  - Chrome whose fate point 4 decides rather than the data page: ActionButtons, Stages, MultiStep
@@ -103,9 +103,15 @@ Reduce that response to a generatable list by applying the following in order. P
103
103
 
104
104
  `Stages` is the counter-example: it is case chrome, never appears in an embedded assignment, and must not be generated for an embedded flow. It stays stripped.
105
105
 
106
- 5. **Present the resolved list, and the exclusions with their reasons.** Name what will be generated, then separately name what was dropped because it appears only in out-of-the-box views, and what was stripped because it is never generated. An exclusion the user disagrees with is far easier to catch when it is visible, and a silently missing component surfaces much later as a rendering gap. **Report the starting fields here too** — either the property names the case type accepts at creation, or that none were confirmed and pre-fill will therefore be off. This is the last point before analysis and generation begin, so it is the last cheap moment for the user to correct either one. Then ask whether to proceed.
106
+ 5. **Present the resolved list, and the exclusions with their reasons.** Name what will be generated, then separately name what was dropped because it appears only in out-of-the-box views, what was stripped because it is never generated, and what was added because a selected component declares it as a registry dependency. An exclusion the user disagrees with is far easier to catch when it is visible, and a silently missing component surfaces much later as a rendering gap. **Report the starting fields here too** — either the property names the case type accepts at creation, or that none were confirmed and pre-fill will therefore be off. This is the last point before analysis and generation begin, so it is the last cheap moment for the user to correct either one. Then ask whether to proceed.
107
107
 
108
- 6. **Beyond the additions in point 4, generate only what this resolved list contains.** Do NOT add components based on assumptions about what a case type might need.
108
+ 6. **Beyond the additions in point 4, generate only what this resolved list contains, plus the registry dependencies the selected components declare.** Do NOT add components based on assumptions about what a case type might need.
109
+
110
+ Some components are orchestrators: they render no control of their own, and instead resolve other components from the registry at runtime. Reference fields and embedded data fields are the clearest examples — one of them may resolve a table, a repeating-group template, a picker, or a value display depending on how it was configured. Those dependencies are building blocks rather than fields, so they never appear in view metadata and this data page never returns them. A registry lookup that finds nothing degrades to a fallback or a blank render rather than raising an error, so an orchestrator generated on its own looks like a styling fault rather than a missing component.
111
+
112
+ A dependency named in a generated component's own skill file is therefore **not** an assumption — it is part of that component's contract. Read each selected component's skill file, collect the registry keys it declares it will resolve, and add any that are neither already registered in the project nor already in the list. The dependency is **transitive**: a dependency's own skill may declare further ones, so repeat until the set stops growing. Record which component required each addition, and report them under point 5 separately from the chrome added by point 4.
113
+
114
+ The distinction to hold: a dependency a skill file declares is required, and omitting it produces a component that cannot render. A component you believe a case type might need is not. Never widen the list on your own judgement.
109
115
 
110
116
  ### Step 0.4 — Proceed to workflows
111
117
 
@@ -148,7 +154,7 @@ If the user named a launch point but no render target, the skill infers it from
148
154
  7. **Adapt to the customer's framework** — the skills and prompts are framework-agnostic. Determine the customer's framework from their project configuration and apply conventions accordingly.
149
155
  8. **Verification is mandatory, and it is not only static** — the generation prompt's checks confirm the generated files are well-formed. They do not confirm the flow runs. Whenever the integration has been wired, finish with `{{SKILL_DIR}}/embedded-flow/run-and-verify-integration.md` and report how far it got. Never declare success on static checks alone.
150
156
  9. **Case type class must be used** — the confirmed case type class must be written into `sdk-config.json` (in the `appMashupCaseType` field) and used in the bootstrap/wiring module when calling the mashup API to create a case.
151
- 10. **Only generate server-resolved components** — generate exactly what Step 0.3 produced: the components the case type's data page returned and that survived its filters, plus the additions point 4 names (`FieldValueList`, `ActionButtons`, and `MultiStep` for a multi-step case). Do NOT add anything else based on assumptions about what a case type might need.
157
+ 10. **Only generate server-resolved components, their declared dependencies, and the named chrome** — generate exactly what Step 0.3 produced: the components the case type's data page returned and that survived its filters, the additions point 4 names (`FieldValueList`, `ActionButtons`, and `MultiStep` for a multi-step case), and the registry dependencies that the selected components' own skill files declare, resolved transitively per point 6. Do NOT add anything else based on assumptions about what a case type might need.
152
158
  11. **Never silently replace existing behaviour, and never assume where the flow renders** — before anything is written, resolve the launch point and the render target. If the named control already does something, ask whether to override; if they decline, stop the whole flow, do not embed on a different control, and do not leave partial edits behind. If the render target was never stated and cannot be inherited from the control's existing behaviour, ask. See Step 0 of the wire-integration skill.
153
159
  12. **Never handle credentials** — when verification reaches the Pega login form in the browser, a human signs in at a visible window. Do not request, capture, log, echo, or store those credentials, at any stage and under any failure condition.
154
160
 
@@ -164,6 +170,7 @@ If the user named a launch point but no render target, the skill infers it from
164
170
  | Every component is removed by the lifecycle filter | The case type may have no lifecycle views. Show the views that were returned, explain that all of them are out-of-the-box, and ask the user to confirm before proceeding |
165
171
  | Customer's project uses an unfamiliar framework | Read the framework's documentation (if accessible) + rely heavily on the representative components from the Design Profile |
166
172
  | A requested component has no skill file | The name is not a Pega component name. Resolve it to a canonical one using the staged process in Step 1 of the generation prompt (normalized name, then alias table, then behaviour class, then ask the user), implement that component's skill, and tell the user which substitution you made |
173
+ | A generated component renders blank or shows the fallback | Most likely a registry dependency it resolves at runtime was never generated. Orchestrator components fail this way silently. Re-read that component's skill file, collect the registry keys it declares, and confirm each one is registered — see point 6 of Step 0.3. Do not treat it as a styling fault |
167
174
  | Design Profile extraction finds no clear patterns | Ask the user to point to specific example components in their codebase |
168
175
  | Generated component fails type check after 2 retries | Report the specific error, show the problematic code, and ask the user for guidance |
169
176
  | Customer uses multiple design systems in one project | Ask which one should be used for the Pega components, or default to the one used for form elements |
@@ -29,6 +29,11 @@
29
29
  { "name": "Decimal", "path": "src/components/field/Decimal" },
30
30
  { "name": "Dropdown", "path": "src/components/field/Dropdown" },
31
31
  { "name": "Email", "path": "src/components/field/Email" },
32
+ { "name": "EmbeddedData", "path": "src/components/field/EmbeddedData" },
33
+ {
34
+ "name": "EmbeddedDataMulti",
35
+ "path": "src/components/field/EmbeddedDataMulti"
36
+ },
32
37
  { "name": "Group", "path": "src/components/field/Group" },
33
38
  { "name": "Integer", "path": "src/components/field/Integer" },
34
39
  { "name": "Location", "path": "src/components/field/Location" },
@@ -274,6 +279,8 @@
274
279
  "web address": ["URL"],
275
280
  "formatted rich text entry": ["RichText", "RichTextEditor"],
276
281
  "list of simple values": ["ScalarList"],
282
+ "a record stored on the case itself": ["EmbeddedData"],
283
+ "a list of records stored on the case itself": ["EmbeddedDataMulti"],
277
284
  "reference to another record": ["ObjectReference"],
278
285
  "reference to a person": ["UserReference", "Operator"],
279
286
  "geographic location": ["Location"],
@@ -193,7 +193,9 @@ Intersect the confirmed selection with the type scope from Step 0, group the res
193
193
  - Step 3 checks for existing files only within the generation set.
194
194
  - Steps 4–8 each generate only the components of their type that are in the generation set, and are skipped entirely when it holds none of their type.
195
195
 
196
- Generate nothing outside the generation set. Do not add components based on assumptions about what a portal might need.
196
+ Generate nothing outside the generation set, with one exception: the registry dependencies that the selected components' own skill files declare. Some components are orchestrators — they render no control of their own and instead resolve other components from the registry at runtime, as reference and embedded data fields do. Those dependencies are building blocks rather than fields, so they never appear in view metadata and no data source above returns them, and a registry lookup that finds nothing degrades to a blank render rather than raising an error. Read each selected component's skill file, collect the registry keys it declares it will resolve, and add any that are neither already registered nor already in the set; repeat until the set stops growing, since a dependency's own skill may declare further ones. Report these additions in the Step 9 summary, naming which component required each.
197
+
198
+ A dependency a skill file declares is required. A component you believe a portal might need is not — do not add components based on assumptions about what a portal might need.
197
199
 
198
200
  ---
199
201
 
@@ -45,6 +45,50 @@ Extend the field input contract for component-specific additional inputs (e.g.,
45
45
 
46
46
  ---
47
47
 
48
+ ## Condition Encoding
49
+
50
+ Several configuration settings describe a _condition_ rather than a fixed value. This section states their contract once; individual field skills may reference it instead of restating it.
51
+
52
+ ### The six shapes
53
+
54
+ A condition-style setting can arrive in one of six forms: 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 runtime before the component receives the input.**
55
+
56
+ This applies to `readOnly`, `required`, `disabled`, `visibility`, the nested visibility that governs a field-input warning message, and the same settings on any nested field descriptor. Because a descriptor is itself an ordinary field, the contract applies **recursively** to every level of nesting.
57
+
58
+ ### Consequences
59
+
60
+ - Type every one of these inputs as a plain boolean. Never inspect its raw string form.
61
+ - Never treat a non-empty string as automatically true. Doing so makes every expression-based or rule-based setting permanently active — the single most common way to get this wrong.
62
+ - Treat absent, an empty string, and an explicitly-emitted default value as equivalent to the setting's documented default.
63
+ - Ensure a resolved `disabled` or `readOnly` genuinely prevents interaction, rather than being accepted as an unused input.
64
+
65
+ ### Key presence never indicates intent
66
+
67
+ Configuration does not clear a setting's key consistently when its control stops being relevant. All of the following occur:
68
+
69
+ - A control that becomes hidden may leave its last value behind as a stale key.
70
+ - A control that becomes hidden may instead have its key cleared.
71
+ - A key cleared by one change may reappear later carrying a **re-seeded default**, not the value that was last configured for it.
72
+ - Some presentations emit a setting's default explicitly while others omit it entirely, for the identical setting at the identical value.
73
+
74
+ Therefore: decide which settings are active from the component's mode and presentation, never from which keys are present, and never assume a key's value reflects the last choice made for it.
75
+
76
+ ### Convenience visibility choices
77
+
78
+ Visibility offers extra options phrased as "if not blank" and "if not zero". These are authoring conveniences that compile to ordinary expressions evaluated against the field's own bound value — they introduce no new value shape. They are offered only where the field has a single scalar bound value to test; a field bound to a list, or one presented as an embedded form, offers only the always / expression / rule choices.
79
+
80
+ Never implement show/hide logic from `visibility`. A field whose visibility resolves to false is not rendered by the surrounding runtime at all.
81
+
82
+ ### Exception: conditions scoped to a single row
83
+
84
+ A condition that governs an individual row of a list does **not** arrive resolved.
85
+
86
+ Such a setting must be read from the component's **raw** configuration — the resolved inputs do not carry it — and evaluated per row against that row's own data, using the platform's expression engine. The configuration surface offers these settings only three choices: never, always, and a custom condition. The When-Rule option is deliberately absent, because a When Rule resolves once and cannot vary from row to row.
87
+
88
+ Two failure modes to avoid. Typing such a setting as a boolean silently discards the per-row behaviour and applies one verdict to the whole list. Truthiness-checking the raw marked string makes the action permanently available for every row. Handle the three real cases explicitly: absent or true means allowed, an expression means evaluate per row, and anything else means denied.
89
+
90
+ ---
91
+
48
92
  ## Implementation Pattern
49
93
 
50
94
  ### Abstract Field Component Pattern
@@ -146,35 +190,37 @@ After creating a component, register it in the project's component map: import t
146
190
 
147
191
  ## Existing Field Components
148
192
 
149
- | Component | Pega Name | Description |
150
- | --------------- | --------------- | --------------------------------- |
151
- | AutoComplete | AutoComplete | Typeahead search field |
152
- | CancelAlert | CancelAlert | Cancel confirmation dialog |
153
- | Checkbox | Checkbox | Single checkbox with label |
154
- | Currency | Currency | Currency input with formatting |
155
- | Date | Date | Date picker |
156
- | DateTime | DateTime | Date + time picker |
157
- | Decimal | Decimal | Decimal number input |
158
- | Dropdown | Dropdown | Select/dropdown with options |
159
- | Email | Email | Email input with icon |
160
- | Group | Group | Field group container |
161
- | Integer | Integer | Integer-only input |
162
- | Location | Location | Google Maps location picker |
163
- | Multiselect | Multiselect | Multi-select dropdown |
164
- | ObjectReference | ObjectReference | Reference to another object |
165
- | Percentage | Percentage | Percentage input |
166
- | Phone | Phone | Phone input with country selector |
167
- | RadioButtons | RadioButtons | Radio button group |
168
- | RichText | RichText | Rich text editor |
169
- | ScalarList | ScalarList | List of scalar values |
170
- | SelectableCard | SelectableCard | Card-style selection |
171
- | SemanticLink | SemanticLink | Clickable link to another case |
172
- | TextArea | TextArea | Multi-line text input |
173
- | TextContent | TextContent | Static text display |
174
- | TextInput | TextInput | Single-line text input |
175
- | Time | Time | Time picker |
176
- | URL | URL | URL input with validation |
177
- | UserReference | UserReference | User picker |
193
+ | Component | Pega Name | Description |
194
+ | ----------------- | ----------------- | ---------------------------------------------- |
195
+ | AutoComplete | AutoComplete | Typeahead search field |
196
+ | CancelAlert | CancelAlert | Cancel confirmation dialog |
197
+ | Checkbox | Checkbox | Single checkbox with label |
198
+ | Currency | Currency | Currency input with formatting |
199
+ | Date | Date | Date picker |
200
+ | DateTime | DateTime | Date + time picker |
201
+ | Decimal | Decimal | Decimal number input |
202
+ | Dropdown | Dropdown | Select/dropdown with options |
203
+ | Email | Email | Email input with icon |
204
+ | EmbeddedData | EmbeddedData | Single embedded record shown as a picker |
205
+ | EmbeddedDataMulti | EmbeddedDataMulti | List of embedded records (table, groups, tabs) |
206
+ | Group | Group | Field group container |
207
+ | Integer | Integer | Integer-only input |
208
+ | Location | Location | Google Maps location picker |
209
+ | Multiselect | Multiselect | Multi-select dropdown |
210
+ | ObjectReference | ObjectReference | Reference to another object |
211
+ | Percentage | Percentage | Percentage input |
212
+ | Phone | Phone | Phone input with country selector |
213
+ | RadioButtons | RadioButtons | Radio button group |
214
+ | RichText | RichText | Rich text editor |
215
+ | ScalarList | ScalarList | List of scalar values |
216
+ | SelectableCard | SelectableCard | Card-style selection |
217
+ | SemanticLink | SemanticLink | Clickable link to another case |
218
+ | TextArea | TextArea | Multi-line text input |
219
+ | TextContent | TextContent | Static text display |
220
+ | TextInput | TextInput | Single-line text input |
221
+ | Time | Time | Time picker |
222
+ | URL | URL | URL input with validation |
223
+ | UserReference | UserReference | User picker |
178
224
 
179
225
  ---
180
226