@pega/custom-dx-components 26.1.11 → 26.1.12-alpha.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/package.json +48 -64
- package/src/ai/README.md +44 -0
- package/src/ai/catalog/README.md +133 -0
- package/src/ai/catalog/best-practices/README.md +24 -0
- package/src/ai/catalog/best-practices/accessibility-for-async-components.md +53 -0
- package/src/ai/catalog/best-practices/error-handling-and-resiliency.md +116 -0
- package/src/ai/catalog/best-practices/genai-assistant-integration-patterns.md +49 -0
- package/src/ai/catalog/best-practices/performance-and-efficiency.md +109 -0
- package/src/ai/catalog/best-practices/security-considerations.md +93 -0
- package/src/ai/catalog/best-practices/testing-pconnect-components.md +245 -0
- package/src/ai/catalog/best-practices/troubleshooting-common-pitfalls.md +132 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/SKILL.md +44 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/README.md +39 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/approval-workflow-decision.md +47 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/attachment-upload.md +45 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/bulk-action-submit.md +50 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/confirm-before-destructive-action.md +43 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/create-and-stage-new-case.md +45 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/graceful-submit-failure.md +39 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/modal-assignment-submit.md +58 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/multi-step-wizard.md +44 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/resolve-or-ignore-duplicate.md +47 -0
- package/src/ai/catalog/pconnect-assignment-lifecycle/cookbooks/safe-case-deletion.md +36 -0
- package/src/ai/catalog/pconnect-case-collaboration/SKILL.md +42 -0
- package/src/ai/catalog/pconnect-case-collaboration/cookbooks/README.md +36 -0
- package/src/ai/catalog/pconnect-case-collaboration/cookbooks/look-up-user-details.md +43 -0
- package/src/ai/catalog/pconnect-case-collaboration/cookbooks/manage-case-attachments.md +51 -0
- package/src/ai/catalog/pconnect-case-collaboration/cookbooks/manage-case-participants.md +52 -0
- package/src/ai/catalog/pconnect-case-collaboration/cookbooks/participant-and-follower.md +40 -0
- package/src/ai/catalog/pconnect-case-collaboration/cookbooks/post-and-manage-feed.md +50 -0
- package/src/ai/catalog/pconnect-case-collaboration/cookbooks/relate-cases.md +35 -0
- package/src/ai/catalog/pconnect-case-collaboration/cookbooks/tag-case-and-find-related.md +44 -0
- package/src/ai/catalog/pconnect-data-subscriptions/SKILL.md +42 -0
- package/src/ai/catalog/pconnect-data-subscriptions/cookbooks/README.md +35 -0
- package/src/ai/catalog/pconnect-data-subscriptions/cookbooks/data-page-subscription-cleanup.md +41 -0
- package/src/ai/catalog/pconnect-data-subscriptions/cookbooks/publish-and-subscribe-events.md +40 -0
- package/src/ai/catalog/pconnect-data-subscriptions/cookbooks/pubsub-cleanup.md +38 -0
- package/src/ai/catalog/pconnect-data-subscriptions/cookbooks/query-paginated-list-data.md +44 -0
- package/src/ai/catalog/pconnect-data-subscriptions/cookbooks/realtime-case-subscription.md +46 -0
- package/src/ai/catalog/pconnect-data-subscriptions/cookbooks/refresh-and-update-data.md +41 -0
- package/src/ai/catalog/pconnect-forms-and-fields/SKILL.md +44 -0
- package/src/ai/catalog/pconnect-forms-and-fields/cookbooks/README.md +36 -0
- package/src/ai/catalog/pconnect-forms-and-fields/cookbooks/autosave-tracking.md +45 -0
- package/src/ai/catalog/pconnect-forms-and-fields/cookbooks/cascading-dependent-fields.md +51 -0
- package/src/ai/catalog/pconnect-forms-and-fields/cookbooks/collect-form-changes-for-manual-save.md +45 -0
- package/src/ai/catalog/pconnect-forms-and-fields/cookbooks/custom-field-validators.md +44 -0
- package/src/ai/catalog/pconnect-forms-and-fields/cookbooks/discard-changes-and-reset-form.md +41 -0
- package/src/ai/catalog/pconnect-forms-and-fields/cookbooks/full-form-validation.md +38 -0
- package/src/ai/catalog/pconnect-forms-and-fields/cookbooks/persist-widget-ui-state.md +41 -0
- package/src/ai/catalog/pconnect-lists-and-views/SKILL.md +44 -0
- package/src/ai/catalog/pconnect-lists-and-views/cookbooks/README.md +35 -0
- package/src/ai/catalog/pconnect-lists-and-views/cookbooks/activate-and-switch-container-items.md +52 -0
- package/src/ai/catalog/pconnect-lists-and-views/cookbooks/container-item-lifecycle.md +61 -0
- package/src/ai/catalog/pconnect-lists-and-views/cookbooks/insert-delete-list-rows.md +40 -0
- package/src/ai/catalog/pconnect-lists-and-views/cookbooks/reorder-list-rows.md +39 -0
- package/src/ai/catalog/pconnect-lists-and-views/cookbooks/repeating-row-edit.md +39 -0
- package/src/ai/catalog/pconnect-lists-and-views/cookbooks/view-personalization.md +60 -0
- package/src/ai/catalog/pconnect-navigation-locale-genai/SKILL.md +45 -0
- package/src/ai/catalog/pconnect-navigation-locale-genai/cookbooks/README.md +35 -0
- package/src/ai/catalog/pconnect-navigation-locale-genai/cookbooks/agent-conversation-for-tasks.md +54 -0
- package/src/ai/catalog/pconnect-navigation-locale-genai/cookbooks/bookmarkable-filter-state.md +40 -0
- package/src/ai/catalog/pconnect-navigation-locale-genai/cookbooks/deep-link-semantic-url.md +39 -0
- package/src/ai/catalog/pconnect-navigation-locale-genai/cookbooks/genai-assistant-conversation.md +43 -0
- package/src/ai/catalog/pconnect-navigation-locale-genai/cookbooks/locale-switch-and-relocalize.md +38 -0
- package/src/ai/catalog/pconnect-navigation-locale-genai/cookbooks/persist-operator-preferences.md +40 -0
- package/src/ai/catalog/references/architecture-overview.md +52 -0
- package/src/ai/catalog/references/pconnect-actions-api.md +948 -0
- package/src/ai/catalog/references/pconnect-case-info-data-info-localization.md +618 -0
- package/src/ai/catalog/references/pconnect-case-validation-utilities.md +238 -0
- package/src/ai/catalog/references/pconnect-container-manager.md +215 -0
- package/src/ai/catalog/references/pconnect-list-actions.md +250 -0
- package/src/ai/catalog/references/pconnect-misc-suggestions-creation.md +231 -0
- package/src/ai/catalog/references/pconnect-reference-context-component.md +471 -0
- package/src/ai/catalog/references/pconnect-state-config.md +316 -0
- package/src/ai/catalog/references/pconnect-validation-api.md +45 -0
- package/src/ai/catalog/references/pcore-analytics-genai-details.md +50 -0
- package/src/ai/catalog/references/pcore-bootstrap-init-details.md +121 -0
- package/src/ai/catalog/references/pcore-bootstrap-registry-routing.md +253 -0
- package/src/ai/catalog/references/pcore-case-collaboration-details.md +191 -0
- package/src/ai/catalog/references/pcore-case-collaboration-genai.md +264 -0
- package/src/ai/catalog/references/pcore-environment-info-details.md +96 -0
- package/src/ai/catalog/references/pcore-environment-locale-namespace.md +175 -0
- package/src/ai/catalog/references/pcore-messaging-details.md +99 -0
- package/src/ai/catalog/references/pcore-misc-details.md +207 -0
- package/src/ai/catalog/references/pcore-misc-utilities.md +325 -0
- package/src/ai/catalog/references/pcore-rest-data-details.md +164 -0
- package/src/ai/catalog/references/pcore-rest-data-messaging.md +308 -0
- package/src/ai/catalog/references/pcore-store-context-details.md +40 -0
- package/src/ai/catalog/references/pcore-store-context-state.md +130 -0
- package/src/ai/index.js +154 -0
- package/src/ai/project/.claude/skills/boolean/SKILL.md +43 -0
- package/src/ai/project/.claude/skills/case/SKILL.md +58 -0
- package/src/ai/project/.claude/skills/create-dx-component/SKILL.md +98 -0
- package/src/ai/project/.claude/skills/create-dx-component/assets/PConnProps.d.ts +24 -0
- package/src/ai/project/.claude/skills/create-dx-component/assets/create-nonce.ts +5 -0
- package/src/ai/project/.claude/skills/create-dx-component/assets/event-utils.ts +18 -0
- package/src/ai/project/.claude/skills/create-dx-component/assets/styles.ts +7 -0
- package/src/ai/project/.claude/skills/create-dx-component/cookbooks/README.md +28 -0
- package/src/ai/project/.claude/skills/create-dx-component/cookbooks/build-a-data-widget.md +281 -0
- package/src/ai/project/.claude/skills/create-dx-component/cookbooks/field-with-limits-and-validation.md +156 -0
- package/src/ai/project/.claude/skills/create-dx-component/cookbooks/status-badge-field.md +97 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/accessibility.md +71 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/choosing-type-and-subtype.md +79 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/cli-workflow.md +125 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/component-patterns.md +241 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/config-schema.md +296 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/cosmos-components.md +137 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/field-behavior.md +155 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/field-essentials.md +90 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/field-subtypes-extra.md +68 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/localization.md +30 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/pcore-pconnect-apis.md +77 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/presentation-essentials.md +57 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/props-contract.md +182 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/state-matrix.md +102 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/storybook-pattern.md +262 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/styles-pattern.md +54 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/template-essentials.md +87 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/template-patterns.md +131 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/test-pattern.md +215 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/ui-gallery-reuse.md +93 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/widget-essentials.md +84 -0
- package/src/ai/project/.claude/skills/create-dx-component/references/widget-patterns.md +164 -0
- package/src/ai/project/.claude/skills/currency/SKILL.md +46 -0
- package/src/ai/project/.claude/skills/date/SKILL.md +46 -0
- package/src/ai/project/.claude/skills/decimal/SKILL.md +49 -0
- package/src/ai/project/.claude/skills/details/SKILL.md +60 -0
- package/src/ai/project/.claude/skills/email/SKILL.md +42 -0
- package/src/ai/project/.claude/skills/field/SKILL.md +68 -0
- package/src/ai/project/.claude/skills/form/SKILL.md +51 -0
- package/src/ai/project/.claude/skills/generate-component-set/SKILL.md +80 -0
- package/src/ai/project/.claude/skills/generate-component-set/component-manifest.json +161 -0
- package/src/ai/project/.claude/skills/identify-components/SKILL.md +76 -0
- package/src/ai/project/.claude/skills/integer/SKILL.md +45 -0
- package/src/ai/project/.claude/skills/page/SKILL.md +60 -0
- package/src/ai/project/.claude/skills/page-widget/SKILL.md +55 -0
- package/src/ai/project/.claude/skills/percentage/SKILL.md +52 -0
- package/src/ai/project/.claude/skills/phone/SKILL.md +44 -0
- package/src/ai/project/.claude/skills/picklist/SKILL.md +50 -0
- package/src/ai/project/.claude/skills/plan-dx-component/SKILL.md +51 -0
- package/src/ai/project/.claude/skills/plan-dx-component/references/design-system-mapping.md +108 -0
- package/src/ai/project/.claude/skills/plan-dx-component/references/intake.md +146 -0
- package/src/ai/project/.claude/skills/plan-dx-component/references/plan-template.md +76 -0
- package/src/ai/project/.claude/skills/plan-dx-component/references/requirements-template.md +88 -0
- package/src/ai/project/.claude/skills/presentation/SKILL.md +61 -0
- package/src/ai/project/.claude/skills/publish-library/SKILL.md +106 -0
- package/src/ai/project/.claude/skills/radiobuttons/SKILL.md +51 -0
- package/src/ai/project/.claude/skills/review-component/SKILL.md +49 -0
- package/src/ai/project/.claude/skills/review-component/references/checklist.md +77 -0
- package/src/ai/project/.claude/skills/template/SKILL.md +60 -0
- package/src/ai/project/.claude/skills/text/SKILL.md +45 -0
- package/src/ai/project/.claude/skills/update-dx-component/SKILL.md +56 -0
- package/src/ai/project/.claude/skills/update-dx-component/references/maintenance.md +43 -0
- package/src/ai/project/.claude/skills/url/SKILL.md +46 -0
- package/src/ai/project/.claude/skills/validate-component/SKILL.md +78 -0
- package/src/ai/project/.claude/skills/validate-component/references/runtime-troubleshooting.md +56 -0
- package/src/ai/project/.claude/skills/validate-component/scripts/check-component.mjs +327 -0
- package/src/ai/project/.claude/skills/widget/SKILL.md +59 -0
- package/src/ai/project/.gemini/settings.json +5 -0
- package/src/ai/project/AGENTS.md +74 -0
- package/src/ai/readme-section.md +91 -0
- package/src/cli.js +48 -7
- package/src/constants.js +54 -53
- package/src/internal-tests.js +27 -0
- package/src/tasks/ai-toggle/index.js +46 -0
- package/src/tasks/authenticate/helper.js +38 -38
- package/src/tasks/authenticate/index.js +17 -15
- package/src/tasks/build-all/helper.js +4 -4
- package/src/tasks/build-all/index.js +7 -7
- package/src/tasks/build-comp/helper.js +17 -17
- package/src/tasks/build-comp/index.js +10 -10
- package/src/tasks/build-jest-assets/index.js +7 -9
- package/src/tasks/build-lib/helper.js +8 -8
- package/src/tasks/build-lib/index.js +8 -8
- package/src/tasks/bundle/builder/index.js +9 -12
- package/src/tasks/bundle/builder/modules.js +8 -9
- package/src/tasks/bundle/builder/paths.js +2 -19
- package/src/tasks/bundle/builder/webpack.config.js +60 -77
- package/src/tasks/bundle/index.js +8 -8
- package/src/tasks/create/index.js +35 -35
- package/src/tasks/create/templates/Constellation/Field/Boolean/index.tsx.mustache +1 -36
- package/src/tasks/create/templates/Constellation/Field/Date/date.ts.mustache +2 -2
- package/src/tasks/create/templates/Constellation/Field/Date/index.tsx.mustache +2 -27
- package/src/tasks/create/templates/Constellation/Field/DateTime/date-utils.ts.mustache +2 -2
- package/src/tasks/create/templates/Constellation/Field/DateTime/date.ts.mustache +2 -2
- package/src/tasks/create/templates/Constellation/Field/DateTime/index.tsx.mustache +2 -35
- package/src/tasks/create/templates/Constellation/Field/Decimal/index.tsx.mustache +3 -36
- package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/index.tsx.mustache +4 -39
- package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/index.tsx.mustache +4 -53
- package/src/tasks/create/templates/Constellation/Field/Icon-Button-URL/index.tsx.mustache +5 -5
- package/src/tasks/create/templates/Constellation/Field/Integer/index.tsx.mustache +3 -36
- package/src/tasks/create/templates/Constellation/Field/Picklist/index.tsx.mustache +7 -42
- package/src/tasks/create/templates/Constellation/Field/Picklist-Autocomplete/component-constants.ts +1 -1
- package/src/tasks/create/templates/Constellation/Field/Picklist-Autocomplete/date.ts.mustache +0 -2
- package/src/tasks/create/templates/Constellation/Field/Picklist-Autocomplete/embed-utils.ts.mustache +1 -1
- package/src/tasks/create/templates/Constellation/Field/Picklist-Autocomplete/index.tsx.mustache +11 -11
- package/src/tasks/create/templates/Constellation/Field/Picklist-Autocomplete/repeat-utils.ts.mustache +3 -13
- package/src/tasks/create/templates/Constellation/Field/Picklist-Autocomplete/textformat-utils.tsx.mustache +2 -3
- package/src/tasks/create/templates/Constellation/Field/Picklist-Autocomplete/utils.ts.mustache +28 -28
- package/src/tasks/create/templates/Constellation/Field/Picklist-RadioButtons/index.tsx.mustache +2 -2
- package/src/tasks/create/templates/Constellation/Field/Picklist-RadioButtons/textformat-utils.tsx.mustache +2 -3
- package/src/tasks/create/templates/Constellation/Field/Text/index.tsx.mustache +4 -33
- package/src/tasks/create/templates/Constellation/Field/Text-Email/index.tsx.mustache +3 -33
- package/src/tasks/create/templates/Constellation/Field/Text-Input/index.tsx.mustache +3 -31
- package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/index.tsx.mustache +3 -31
- package/src/tasks/create/templates/Constellation/Field/Text-Phone/index.tsx.mustache +3 -35
- package/src/tasks/create/templates/Constellation/Field/Text-URL/index.tsx.mustache +3 -33
- package/src/tasks/create/templates/Constellation/Field/Text-URL/text-url.tsx.mustache +2 -3
- package/src/tasks/create/templates/Constellation/Field/TimeofDay/index.tsx.mustache +2 -35
- package/src/tasks/create/templates/Constellation/Field/TimeofDay/time-of-day.ts.mustache +2 -2
- package/src/tasks/create/templates/Constellation/Template/DETAILS/Avatar.tsx.mustache +19 -15
- package/src/tasks/create/templates/Constellation/Template/DETAILS/Operator.tsx.mustache +6 -6
- package/src/tasks/create/templates/Constellation/Template/DETAILS/demo.stories.tsx.mustache +1 -1
- package/src/tasks/create/templates/Constellation/Template/DETAILS/index.tsx.mustache +4 -8
- package/src/tasks/create/templates/Constellation/Template/DETAILS/mock.ts.mustache +9 -9
- package/src/tasks/create/templates/Constellation/Template/DETAILS/utils.js.mustache +4 -8
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/Avatar.tsx.mustache +19 -15
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/Operator.tsx.mustache +6 -6
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/demo.stories.tsx.mustache +1 -1
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/index.tsx.mustache +1 -1
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/mock.ts.mustache +9 -9
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/utils.ts.mustache +4 -8
- package/src/tasks/create/templates/Constellation/Template/FORM/demo.stories.tsx.mustache +8 -8
- package/src/tasks/create/templates/Constellation/Template/FORM-region/demo.stories.tsx.mustache +8 -8
- package/src/tasks/create/templates/Constellation/Template/PAGE/utils.ts.mustache +4 -9
- package/src/tasks/create/templates/Constellation/Widget/CASE/demo.test.tsx.mustache +3 -3
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/Avatar.tsx.mustache +19 -14
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/Operator.tsx.mustache +6 -6
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/index.tsx.mustache +1 -1
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/mock.ts.mustache +1 -1
- package/src/tasks/create/templates/Launchpad/Field/Icon-Button-URL/index.tsx.mustache +5 -5
- package/src/tasks/create/templates/Launchpad/Field/Text-Phone/index.tsx.mustache +3 -35
- package/src/tasks/create/templates/Launchpad/Field/__components.md +1 -1
- package/src/tasks/create/templates/Launchpad/Template/FORM/demo.stories.tsx.mustache +8 -8
- package/src/tasks/create/templates/Launchpad/Template/FORM-region/demo.stories.tsx.mustache +8 -8
- package/src/tasks/create/templates/Launchpad/Widget/CASE/demo.test.tsx.mustache +3 -3
- package/src/tasks/create/templates/Launchpad/Widget/PAGE-CASE/index.tsx.mustache +1 -1
- package/src/tasks/create/templates/Launchpad/Widget/PAGE-CASE/mock.ts.mustache +1 -1
- package/src/tasks/create-all/index.js +42 -41
- package/src/tasks/create-lib/helper.js +13 -13
- package/src/tasks/create-lib/index.js +5 -5
- package/src/tasks/create-version/helper.js +10 -10
- package/src/tasks/create-version/index.js +3 -4
- package/src/tasks/delete/helper.js +20 -19
- package/src/tasks/delete/index.js +2 -2
- package/src/tasks/delete-all/helper.js +26 -25
- package/src/tasks/delete-all/index.js +2 -2
- package/src/tasks/delete-lib/helper.js +6 -6
- package/src/tasks/delete-lib/index.js +6 -6
- package/src/tasks/delete-pub/helper.js +18 -18
- package/src/tasks/delete-pub/index.js +8 -8
- package/src/tasks/delete-version/index.js +2 -2
- package/src/tasks/dev-server/index.js +1 -1
- package/src/tasks/export-archive/helper.js +21 -21
- package/src/tasks/export-archive/index.js +27 -40
- package/src/tasks/export-rc/helper.js +34 -34
- package/src/tasks/export-rc/index.js +21 -31
- package/src/tasks/import-archive/helper.js +39 -39
- package/src/tasks/import-archive/index.js +69 -89
- package/src/tasks/import-comp/helper.js +8 -8
- package/src/tasks/import-comp/index.js +30 -42
- package/src/tasks/index.js +5 -0
- package/src/tasks/init/Node.gitignore +149 -0
- package/src/tasks/init/helper.js +15 -8
- package/src/tasks/init/index.js +115 -35
- package/src/tasks/init/template/.prettierrc.json +4 -1
- package/src/tasks/init/template/.storybook/main.ts +1 -4
- package/src/tasks/init/template/.storybook/manager.ts +1 -1
- package/src/tasks/init/template/.storybook/preview.tsx +2 -2
- package/src/tasks/init/template/.storybook/theme.js +1 -1
- package/src/tasks/init/template/.vscode/extensions.json +0 -1
- package/src/tasks/init/template/README.md +2 -2
- package/src/tasks/init/template/eslint.config.mjs +13 -155
- package/src/tasks/init/template/jest.config.cjs +2 -0
- package/src/tasks/init/template/package-lock.json +26864 -0
- package/src/tasks/init/template/package.json.mustache +19 -74
- package/src/tasks/init/template/setupTests.ts +10 -4
- package/src/tasks/init/template/tsconfig.json +14 -6
- package/src/tasks/internal-test/index.js +21 -0
- package/src/tasks/internal-test-full/index.js +15 -0
- package/src/tasks/internal-test-functional/index.js +15 -0
- package/src/tasks/internal-test-unit/index.js +13 -0
- package/src/tasks/linter/index.js +2 -2
- package/src/tasks/list/helper.js +41 -40
- package/src/tasks/list/index.js +3 -3
- package/src/tasks/list-lib/helper.js +5 -5
- package/src/tasks/list-lib/index.js +8 -8
- package/src/tasks/list-pub/helper.js +23 -16
- package/src/tasks/list-pub/index.js +24 -21
- package/src/tasks/move/helper.js +8 -8
- package/src/tasks/move/index.js +19 -23
- package/src/tasks/promote-webpack/index.js +4 -4
- package/src/tasks/promote-webpack/webpack.config.js +62 -93
- package/src/tasks/publish/helper.js +21 -21
- package/src/tasks/publish/index.js +16 -16
- package/src/tasks/publish-all/helper.js +20 -20
- package/src/tasks/publish-all/index.js +11 -12
- package/src/tasks/publish-archive/helper.js +9 -9
- package/src/tasks/publish-archive/index.js +12 -14
- package/src/tasks/publish-lib/helper.js +3 -3
- package/src/tasks/publish-lib/index.js +28 -34
- package/src/tasks/quarantine/index.js +8 -8
- package/src/tasks/rename/index.js +26 -30
- package/src/tasks/rename-lib/index.js +21 -25
- package/src/tasks/restore/index.js +8 -8
- package/src/tasks/restore-config/index.js +3 -5
- package/src/tasks/set-perm/index.js +8 -8
- package/src/tasks/show-help/index.js +17 -9
- package/src/tasks/show-status/index.js +2 -2
- package/src/tasks/store/index.js +8 -8
- package/src/tasks/switch-lib/helper.js +7 -7
- package/src/tasks/switch-lib/index.js +7 -7
- package/src/tasks/switch-version/helper.js +6 -6
- package/src/tasks/switch-version/index.js +7 -7
- package/src/tasks/update/index.js +1 -1
- package/src/tasks/upgrade/index.js +7 -7
- package/src/tasks/validator/index.js +49 -203
- package/src/util.js +169 -186
- package/src/rules/no-pcore-pconnect-in-presentation.js +0 -103
- package/src/tasks/init/template/.stylelintrc.json +0 -4
- package/src/tasks/init/template/babel.config.cjs +0 -22
- package/src/tasks/init/template/cspell.json +0 -14
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Field essentials
|
|
2
|
+
|
|
3
|
+
Read this instead of the deep references. Open one only for the cases listed at the end.
|
|
4
|
+
|
|
5
|
+
## Before you code
|
|
6
|
+
|
|
7
|
+
- States to cover (mark one not applicable with a reason): empty (`''`, `undefined`, `null`), populated, editing, invalid, required, disabled, read-only, display only, long or malformed value, narrow width, unchanged or empty blur. Add suggestion, field warning and `status` rows only if the field uses them.
|
|
8
|
+
- Each covered state gets a `mock.ts` fixture, a story and at least one test assertion.
|
|
9
|
+
- The scaffold is a working sample: start from it and replace demo content that does not serve the request.
|
|
10
|
+
|
|
11
|
+
## index.tsx
|
|
12
|
+
|
|
13
|
+
- `interface Props extends PConnFieldProps`; each extra prop is optional and named exactly like its `config.json` property. Export `withConfiguration(AcmeLibMyField)` (key without underscores).
|
|
14
|
+
- Keep `import '../shared/create-nonce';`. `PConnProps.d.ts` and `create-nonce.ts` live in `src/components/shared/`: never copy or edit them. `PCore` is a global; do not import it.
|
|
15
|
+
- `handleEvent` comes from `import handleEvent from './event-utils'`. If the scaffold did not create `event-utils.ts` (Text does not), copy `.claude/skills/create-dx-component/assets/event-utils.ts` into the component folder once; do not edit it.
|
|
16
|
+
- `propName` is `(pConn.getStateProps() as StateProps).value`.
|
|
17
|
+
- Config booleans can arrive as `'true'`: normalize `readOnly`, `required` and `disabled` with `value === true || value === 'true'`. Numeric config arrives as a string: `parseInt(x, 10)`, with a deliberate `NaN` fallback.
|
|
18
|
+
- `value` can be `null`, which a destructure default misses: `const value = valueProp ?? ''`.
|
|
19
|
+
- Commit with `handleEvent(actions, type, propName, value)`: `'change'` calls `updateFieldValue`, `'blur'` calls `triggerFieldChange`, `'changeNblur'` both.
|
|
20
|
+
|
|
21
|
+
| Control | While typing | On blur |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| Text, TextArea, Email, URL | local draft, clear the error | `changeNblur` only if changed |
|
|
24
|
+
| Integer, Decimal, Percentage, Currency | validate draft, keep local | to number or `''`, compare, `changeNblur` |
|
|
25
|
+
| Date, DateTime, Time | commit only a complete valid value | same |
|
|
26
|
+
| Dropdown, RadioButtons, Checkbox | `changeNblur` on change | `validate(value)` (RadioButtons only when there is no value) |
|
|
27
|
+
| Stepper, slider | `changeNblur` on change | none |
|
|
28
|
+
|
|
29
|
+
- Read the blur value from the callback argument, not React state.
|
|
30
|
+
- Unchanged value: no commit, only `pConn.getValidationApi().validate(value)`. Both empty: `validate('')`, so required still reports.
|
|
31
|
+
- Zero is a value: never `if (!value)` for a number. Clear commits `''`, not `null` or `0`.
|
|
32
|
+
- Guard blur with `!readOnly`. On change call `pConn.clearErrorMessages({ property: propName })`. A local draft needs an effect on `[value]` that resyncs it.
|
|
33
|
+
- `info` is `validatemessage` if non-empty, else the field warning, else `helperText`. `status` is `'error'` with a `validatemessage`, `'pending'` for a suggestion, `'warning'` for a field warning, else `undefined`; never pass `'suggestion-accepted'` to Cosmos.
|
|
34
|
+
- Spread `{...additionalProps}` first; `testId={testId ?? label}`. `hideLabel` maps to `labelHidden`; the label stays the accessible name.
|
|
35
|
+
- `DISPLAY_ONLY` returns early, after all hooks, with no label or input. Empty renders `NoValue`; prefer the Cosmos `*Display` components (`undefined`, not `''`, for `NumberDisplay`, `CurrencyDisplay`).
|
|
36
|
+
- Cosmos-first: the control already handles label, required, disabled, readOnly, status, info and placeholder. Check any Cosmos prop you have not used in `node_modules/@pega/cosmos-react-core/lib/components/<Name>/<Name>.d.ts`.
|
|
37
|
+
- Look up every `PCore` and `pConn` call in [pcore-pconnect-apis.md](./pcore-pconnect-apis.md); use only documented methods.
|
|
38
|
+
- No inline `style={{ ... }}`, `dangerouslySetInnerHTML`, `console`, nested ternaries, `++`, index keys or dead code.
|
|
39
|
+
|
|
40
|
+
## config.json
|
|
41
|
+
|
|
42
|
+
- Start from the scaffolded file, never from memory. Add only properties the user confirmed, `label`, `hideLabel` and `readOnly` included.
|
|
43
|
+
- `index.tsx` reads every named property with a safe default, or `check-component.mjs` fails (`VISIBILITY`, `REQUIRED`, `DISABLED`, `READONLY` are platform-handled). Remove a property from config, props and code together.
|
|
44
|
+
- Order: `label`, `hideLabel`, `readOnly`; `GROUP` "Input settings" with `"visibility": "(!readOnly = true)"`; optional "Read-only settings"; `GROUP` "Conditions" (`REQUIRED` shown only when not read-only, `DISABLED`, `VISIBILITY`); collapsible `GROUP` "Advanced" with `testId`.
|
|
45
|
+
- `validate-schema` rejects missing `componentKey`, `name`, `description`, `type`, `subtype` or `properties`, a wrong subtype or casing, a property lacking `name`, `label` or `format`, and duplicates. It does not check `format`: use only scaffold formats.
|
|
46
|
+
- `name` equals `componentKey` and the folder. `SELECT` needs `source: [{ key, value }]`; `GROUP` has no `name`; `NUMBER` defaults are numbers, not strings. Labels are sentence case without `@L`; `@L` marks `defaultConfig` values.
|
|
47
|
+
|
|
48
|
+
## styles.ts
|
|
49
|
+
|
|
50
|
+
- Keep the single default-exported `styled.div` wrapper.
|
|
51
|
+
- Add rules only for what Cosmos cannot express (animation, missing states); never layout, text, badges or loading.
|
|
52
|
+
- The theme is undefined here: `useTheme()` in `index.tsx`, pass values as transient props (`$error`).
|
|
53
|
+
- Delete selectors for markup that is gone.
|
|
54
|
+
|
|
55
|
+
## mock.ts and demo.stories.tsx
|
|
56
|
+
|
|
57
|
+
- `mock.ts` exports `configProps` (keys mirror `config.json`, resolved, never `@L`) and `stateProps = { value: '.PropertyName' }`.
|
|
58
|
+
- Base story is `Base<InnerFunctionName>`; one story per covered state.
|
|
59
|
+
- Meta `argTypes` gives every `config.json` property a matching control ([storybook-pattern.md](./storybook-pattern.md#controls-argtypes)); hide `getPConnect`.
|
|
60
|
+
- The fake `getPConnect` has exactly the methods the component calls; `updateFieldValue` updates story state; forward `triggerFieldChange` to a story-only arg. Empty callbacks need `/* nothing */`.
|
|
61
|
+
|
|
62
|
+
## demo.test.tsx
|
|
63
|
+
|
|
64
|
+
- Query by role and accessible name (`getByRole('textbox', { name: /email/i })`); needing a test id is an accessibility finding. Use `fireEvent` (no `user-event`).
|
|
65
|
+
- One assertion per covered state: label, hidden label with helper text; `required`, `disabled` (`toBeRequired()`, `toBeDisabled()`), `readOnly`; `DISPLAY_ONLY` with and without a value; `validatemessage` replacing `helperText` (assert `toHaveAccessibleDescription`; Cosmos sets `aria-describedby`, not `aria-invalid`); `null`, `''`, `0`, typed over `null`; change does not commit; blur commits `propName` and value; unchanged blur only validates; clear commits `''`; long value.
|
|
66
|
+
- Toggle props with `rerender`; pass story-only args through a `Record<string, unknown>` spread. Never weaken an assertion to pass.
|
|
67
|
+
|
|
68
|
+
## localizations.json
|
|
69
|
+
|
|
70
|
+
- Text the field shows itself goes through `pConn.getLocalizationService().getLocalizedText('English text')` and is listed under `fields` in `localizations.json` next to `index.tsx` as `"English text": "English text"`, kept in step with the code.
|
|
71
|
+
- Use whole sentences with `{0}` placeholders; plurals are separate keys; never translate data.
|
|
72
|
+
|
|
73
|
+
## Open a deep reference only when
|
|
74
|
+
|
|
75
|
+
| Situation | Read |
|
|
76
|
+
| --- | --- |
|
|
77
|
+
| Dates, time zones, numbers, precision, pickers, URL/email/phone, suggestions, field warnings | [field-behavior.md](./field-behavior.md) |
|
|
78
|
+
| Text-Input, Text-Paragraph, Icon-Button-URL, DateTime, TimeOfDay, Picklist-Autocomplete | [field-subtypes-extra.md](./field-subtypes-extra.md) |
|
|
79
|
+
| A subtype with its own skill | e.g. [text](../../text/SKILL.md), [picklist](../../picklist/SKILL.md) |
|
|
80
|
+
| A config format beyond the scaffold's, visibility, bindings | [config-schema.md](./config-schema.md) |
|
|
81
|
+
| A failing or async test, jsdom stubs, a fuller story fake | [test-pattern.md](./test-pattern.md), [storybook-pattern.md](./storybook-pattern.md) |
|
|
82
|
+
| A Cosmos component you have not used before | [cosmos-components.md](./cosmos-components.md) |
|
|
83
|
+
| Focus, keyboard, announcements, manual checks | [accessibility.md](./accessibility.md) |
|
|
84
|
+
| Placeholders, plurals, formatting, right-to-left | [localization.md](./localization.md) |
|
|
85
|
+
| Full prop list or code skeleton | [props-contract.md](./props-contract.md), [component-patterns.md](./component-patterns.md), [styles-pattern.md](./styles-pattern.md) |
|
|
86
|
+
| A custom control or unclear subtype | [choosing-type-and-subtype.md](./choosing-type-and-subtype.md) |
|
|
87
|
+
| AI-generated content | [state-matrix.md](./state-matrix.md) |
|
|
88
|
+
| A worked example | [field-with-limits-and-validation.md](../cookbooks/field-with-limits-and-validation.md) |
|
|
89
|
+
|
|
90
|
+
Finish with `node .claude/skills/validate-component/scripts/check-component.mjs <Org>_<Library>_<Name>`; see [cli-workflow.md](./cli-workflow.md).
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Other Field Subtypes
|
|
2
|
+
|
|
3
|
+
Six valid Field subtypes have no skill of their own: `Text-Input`, `Text-Paragraph`, `Icon-Button-URL`, `DateTime`, `TimeOfDay` and `Picklist-Autocomplete`. This file gives what is specific to each. The shared rules (commit protocol, empty and zero handling, message precedence) are in [field-behavior.md](./field-behavior.md); props and display modes are in [props-contract.md](./props-contract.md).
|
|
4
|
+
|
|
5
|
+
Three of them are variants of a base scaffold: the CLI generates `Text-Input` from the `Text` scaffold, `Icon-Button-URL` from `Text-URL`, and `Picklist-Autocomplete` and `Picklist-RadioButtons` from `Picklist`. The `subtype` in `config.json` is what tells App Studio where the author can pick the component. Anything beyond the base scaffold's behavior is **your** implementation, so read the scaffolded `index.tsx` first and change only what the user asked for. Check every Cosmos prop in the installed `.d.ts` before using it.
|
|
6
|
+
|
|
7
|
+
## Text-Input
|
|
8
|
+
|
|
9
|
+
A single-line text value. Same as [text](../../text/SKILL.md) with the Cosmos `Input` control and no multi-line option. Do not add a `multiLine` property; if the user needs several lines, the subtype is `Text-Paragraph`.
|
|
10
|
+
|
|
11
|
+
## Text-Paragraph
|
|
12
|
+
|
|
13
|
+
A multi-line text value.
|
|
14
|
+
|
|
15
|
+
| Concern | Guidance |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| Control | Cosmos `TextArea`. Display mode uses `ParagraphDisplay` (pass `undefined`, not `''`, for an empty value) |
|
|
18
|
+
| Length | Read `maxLength` from `fieldMetadata` when present. Pass `maxLength` and `displayCharCount` to `TextArea`; its `hardStop` prop blocks typing past the limit |
|
|
19
|
+
| Commit | Like Text: keep a local draft, commit on blur only when the value changed. Also call `PCore.getAutosaveUtils().notifyChange(context, pageReference + propName, value)` on change so autosave sees the edit (documented in the catalog) |
|
|
20
|
+
| Size | A paragraph can be long. Test a very long value for layout and for performance |
|
|
21
|
+
| Rich text | Rich text editing is a different control with its own package and an HTML value. Do not build it as a Paragraph, and never render stored HTML with `dangerouslySetInnerHTML` |
|
|
22
|
+
|
|
23
|
+
## Icon-Button-URL
|
|
24
|
+
|
|
25
|
+
A web address shown as an icon button that opens the link. It carries all the risk of [url](../../url/SKILL.md): allow only `http:` and `https:`, set `rel='noopener noreferrer'` when opening a new tab, and do not trust the display component to block unsafe schemes. Two additions: an icon-only button **must** have an accessible name (a `label`, never icon alone), and an empty or unsafe value should render no link rather than a dead one.
|
|
26
|
+
|
|
27
|
+
## DateTime
|
|
28
|
+
|
|
29
|
+
A date and time stored as a UTC instant, `YYYY-MM-DDTHH:mm:ss.000Z`.
|
|
30
|
+
|
|
31
|
+
| Concern | Guidance |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| Conversion | Convert the stored value to the operator's time zone for the input, and back to UTC on commit. The zone comes from `PCore.getEnvironmentInfo().getTimeZone()`; if it is empty and the feature flag `pyEnableDateTimeSystemTimezoneFallback` is on in `getEnvironmentInfo().getFeatureMap()`, use `PCore.getLocaleUtils().getTimeZoneInUse()` |
|
|
34
|
+
| Library | Time-zone arithmetic needs a date library such as `dayjs` with its `utc` and `timezone` plugins. Check whether it is already installed and follow the consent rule in [AGENTS.md](../../../../AGENTS.md) before importing it |
|
|
35
|
+
| Options | `pickerInterval` accepts only 5, 10, 15, 20, 30 or 60 minutes (fall back to 30). `clockFormat` accepts 12 or 24 (fall back to the locale default). Both arrive as strings |
|
|
36
|
+
| Input state | While the Cosmos input reports an invalid or incomplete state, keep the draft and validate; commit only a complete valid value |
|
|
37
|
+
| Read-only | Guard the commit handlers with `!readOnly` |
|
|
38
|
+
| Display | `DateTimeDisplay`. A relative display ("3 hours ago") needs no zone conversion |
|
|
39
|
+
|
|
40
|
+
## TimeOfDay
|
|
41
|
+
|
|
42
|
+
A time without a date, stored as `HH:mm:ss`.
|
|
43
|
+
|
|
44
|
+
| Concern | Guidance |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| Control | Cosmos `TimeInput`; display `DateTimeDisplay` with the time variant |
|
|
47
|
+
| Commit | On blur only, using the same helper as Date: a complete valid time, otherwise keep the draft and validate |
|
|
48
|
+
| Empty | Pass `undefined` to the control for an empty value |
|
|
49
|
+
| Time zones | A time of day is not an instant. Do not convert it between zones |
|
|
50
|
+
|
|
51
|
+
## Picklist-Autocomplete
|
|
52
|
+
|
|
53
|
+
A single choice from a list the user filters by typing.
|
|
54
|
+
|
|
55
|
+
| Concern | Guidance |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| Options | As in [picklist](../../picklist/SKILL.md): the platform resolves the options and passes them as props (`datasource`, `listType`, `fieldMetadata`). Do not fetch the list yourself unless the user needs a source the platform does not provide, and then follow [widget-patterns.md](./widget-patterns.md) for the request lifecycle |
|
|
58
|
+
| Control | Cosmos `ComboBox` in single-select mode with a `menu` of items |
|
|
59
|
+
| Two values | Keep the **typed filter text** separate from the **selected item**. Clearing the text deselects the item. Store the key of the selected item, never the text |
|
|
60
|
+
| Loading | Initialize the list on first focus or open, not on mount |
|
|
61
|
+
| Search | Debounce the search (500 ms is typical) and ignore or abort the previous request before sending a new one, so a late response cannot overwrite a newer one. Page long lists. Highlight matches with `createStringMatcher` from Cosmos |
|
|
62
|
+
| Stored key not in the first page | Look the stored key up on its own so the selected label still shows |
|
|
63
|
+
| Empty and error | A search with no match shows an empty message; a failed search shows an error and keeps what the user typed |
|
|
64
|
+
| Accessibility | Keep the combo box's role and arrow-key behavior from Cosmos; do not rebuild it |
|
|
65
|
+
|
|
66
|
+
## Picklist-RadioButtons
|
|
67
|
+
|
|
68
|
+
See [radiobuttons](../../radiobuttons/SKILL.md).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Localization
|
|
2
|
+
|
|
3
|
+
Every string a user sees must be translatable, because the same component runs in many languages. This file covers what the scaffolds do and the rules that follow. Anything about how translations reach Pega at runtime is a Pega localization process outside the component: say that you cannot see it and ask the user.
|
|
4
|
+
|
|
5
|
+
## What the scaffolds do
|
|
6
|
+
|
|
7
|
+
- A scaffold that shows its own text ships a `localizations.json` next to `index.tsx`. Its shape is a `fields` object whose keys are the English strings, each mapped to the same English string as the default. The Widget `CASE` scaffold, for example, lists `Date`, `Description`, `Performed by` and `Loading case history`.
|
|
8
|
+
- The component asks the platform for the translation of an English string with `pConn.getLocalizationService().getLocalizedText('English text')`. One scaffold uses `PCore.getLocaleUtils().getLocaleValue('English text', category)` with a category name (`'Case'`). Both are in the API catalog.
|
|
9
|
+
- The English text is the lookup key. If no translation exists, the English text is shown.
|
|
10
|
+
|
|
11
|
+
## Rules
|
|
12
|
+
|
|
13
|
+
1. **Never hard-code visible text in JSX.** Pass every label, message, button text, empty-state message, error message, `aria-label` and placeholder through `getLocalizedText`.
|
|
14
|
+
2. **Every string you pass must appear in `localizations.json`**, as `"English text": "English text"`. Keep that file in step with the code: a string added in code is added there, and a string removed from code is removed there. A reviewer should be able to diff the two.
|
|
15
|
+
3. **Use a stable, complete sentence as the key.** Do not build a sentence from fragments (`'Showing ' + n + ' of ' + total`), because word order differs between languages. Use a whole string with placeholders that you substitute yourself (for example `'Showing {0} of {1}'` and replace `{0}`, `{1}` after translating). `getLocaleValue` has no placeholder engine.
|
|
16
|
+
4. **Plurals are separate strings.** `'1 item'` and `'{0} items'` are two keys. Do not append an `s`.
|
|
17
|
+
5. **Do not translate values that are data.** A picklist stores the key; show the label the platform provides. Case ids, user names and amounts are not translated.
|
|
18
|
+
6. **Do not store translated text.** Resolve it at render time. When the user switches language, the component receives a new `locale` prop and re-renders, so the translated text must not be cached in state.
|
|
19
|
+
7. **Format numbers, dates and currency with the Cosmos formatters and display components** (`NumberDisplay`, `CurrencyDisplay`, `DateTimeDisplay`, `formatNumber`) and the operator's locale. Do not format by string concatenation.
|
|
20
|
+
8. **Leave room for longer text.** Translations are often 30 to 40 percent longer. Wrap text, avoid fixed widths, and check the longest string in Storybook.
|
|
21
|
+
9. **Labels you put in `config.json` are authoring-time text.** Keep them in sentence case and plain English; only default values that appear to the end user (for example a default heading in `defaultConfig`) use the `@L` prefix to mark them as localizable.
|
|
22
|
+
10. **Right-to-left languages** are handled by Cosmos layout components. Do not hard-code `left` and `right`; use logical properties or Cosmos layout props.
|
|
23
|
+
|
|
24
|
+
## In tests and stories
|
|
25
|
+
|
|
26
|
+
Mock `getLocalizationService` to return the key unchanged, so a test asserts the English text. Add one test that passes a non-English mock and checks that the component renders what the service returns instead of its own literal.
|
|
27
|
+
|
|
28
|
+
## Review checks
|
|
29
|
+
|
|
30
|
+
[review-component](../../review-component/SKILL.md) item C7 checks that visible text goes through the service. When you review, grep the JSX for string literals and compare the keys used with `localizations.json`.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# PCore and PConnect API Reference
|
|
2
|
+
|
|
3
|
+
This file is an **index**. The authoritative method-by-method catalog (signature, purpose, example, notes) is installed with this project in [`.claude/skills/references/`](../../references/), and the workflow skills (`pconnect-*`) add cookbooks and pitfalls.
|
|
4
|
+
|
|
5
|
+
**Rules**
|
|
6
|
+
|
|
7
|
+
1. Before calling any PCore or PConnect method, look up its exact signature in the catalog. Do not write it from memory: names, argument order and return values are easy to get wrong.
|
|
8
|
+
2. Use only the methods documented in the catalog. Treat anything else on `PCore` or `pConn` as unsupported, and tell the user if the task needs it.
|
|
9
|
+
3. Component code reaches PConnect through `props.getPConnect()` and PCore through the global `PCore`. The type of `pConn` comes from `@pega/pcore-pconnect-typedefs`, so `tsc --noEmit` will reject a method that does not exist.
|
|
10
|
+
|
|
11
|
+
## Look up a method: search, don't read whole files
|
|
12
|
+
|
|
13
|
+
The catalog files are 5–22 KB each, so search them instead of reading them:
|
|
14
|
+
|
|
15
|
+
1. Search `.claude/skills/references/` for the bare method name as literal text (for example `getDataPageData` or `isFormValid`). A top-level method is a heading such as `` ### `finishAssignment(containerItemID, options?)` ``; a method on a sub-API object is a backticked first cell in a `| Method | Signature | Purpose |` table row. Do not limit the search to headings, or the table rows are missed.
|
|
16
|
+
2. Read only the matching section: from its heading to the next heading of the same level, or the matching table row and the rows around it.
|
|
17
|
+
3. If you know only the class (`FormUtils`, `EnvironmentInfo`), search for `` (via `PCore.get `` or use the tables below to pick the file.
|
|
18
|
+
4. For call order, cleanup or a sequence of several methods, read the matching `pconnect-*` skill's cookbook instead of assembling it from signatures.
|
|
19
|
+
|
|
20
|
+
Open the full catalog index, [`.claude/skills/README.md`](../../README.md), only when the search finds nothing and the tables below do not help.
|
|
21
|
+
|
|
22
|
+
## Where each API is documented
|
|
23
|
+
|
|
24
|
+
Paths are relative to [`.claude/skills/references/`](../../references/).
|
|
25
|
+
|
|
26
|
+
### PConnect (`const pConn = getPConnect()`)
|
|
27
|
+
|
|
28
|
+
| You need to... | Methods | Catalog file |
|
|
29
|
+
| ---------------------------------------------------------------------- | ----------------------------------------------------------------- | -------------------------------------------------- |
|
|
30
|
+
| Read the bound property name, config, or inherited props | `getStateProps`, `getConfigProps`, `getRawMetadata`, `getInheritedProps`, `resolveConfigProps` | `pconnect-state-config.md` |
|
|
31
|
+
| Read or write values and pass props to children | `getValue`, `setValue`, `setInheritedProp`, `setInheritedConfig` | `pconnect-state-config.md` |
|
|
32
|
+
| Know the context, component name, children | `getContextName`, `getComponentName`, `getChildren` | `pconnect-reference-context-component.md` |
|
|
33
|
+
| Create a child component | `createComponent` | `pconnect-misc-suggestions-creation.md` |
|
|
34
|
+
| Clear a validation message, accept or ignore a suggestion | `clearErrorMessages`, `acceptSuggestion`, `ignoreSuggestion` | `pconnect-misc-suggestions-creation.md` |
|
|
35
|
+
| Update a field, submit, cancel, open actions | `getActionsApi().updateFieldValue`, `triggerFieldChange`, `finishAssignment`, `cancelAssignment`, `openLocalAction`, ... | `pconnect-actions-api.md` |
|
|
36
|
+
| Validate a value | `getValidationApi().validate` | `pconnect-validation-api.md` |
|
|
37
|
+
| Read case details | `getCaseInfo().getKey`, `getID`, `getName`, ... | `pconnect-case-info-data-info-localization.md` |
|
|
38
|
+
| Localize text | `getLocalizationService().getLocalizedText` | `pconnect-case-info-data-info-localization.md` |
|
|
39
|
+
| Edit rows of a list property | `getListActions()` | `pconnect-list-actions.md` |
|
|
40
|
+
| Manage containers | `getContainerManager()` | `pconnect-container-manager.md` |
|
|
41
|
+
|
|
42
|
+
### PCore (global)
|
|
43
|
+
|
|
44
|
+
| You need to... | Accessor | Catalog file |
|
|
45
|
+
| ----------------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------- |
|
|
46
|
+
| Load a data page or data view | `PCore.getDataApiUtils().getData`, `PCore.getDataPageUtils()` | `pcore-rest-data-messaging.md`, `pcore-rest-data-details.md` |
|
|
47
|
+
| Call a REST endpoint | `PCore.getRestClient()` | `pcore-rest-data-messaging.md`, `pcore-rest-data-details.md` |
|
|
48
|
+
| Publish or subscribe to events | `PCore.getPubSubUtils()`, `PCore.getEvents()` | `pcore-rest-data-messaging.md`, `pcore-messaging-details.md` |
|
|
49
|
+
| Show or clear messages | `PCore.getMessageManager()` | `pcore-rest-data-messaging.md`, `pcore-messaging-details.md` |
|
|
50
|
+
| Use constants such as `CASE_INFO` | `PCore.getConstants()` | `pcore-misc-utilities.md` |
|
|
51
|
+
| Read operator, locale or environment details | `PCore.getEnvironmentInfo()`, `PCore.getLocaleUtils()` | `pcore-environment-locale-namespace.md`, `pcore-environment-info-details.md` |
|
|
52
|
+
| Work with cases, containers, attachments, feed, tags, users | `PCore.getCaseUtils()`, `getContainerUtils()`, `getAttachmentUtils()`, `getFeedUtils()`, `getTagUtils()`, `getUserApi()` | `pcore-case-collaboration-genai.md`, `pcore-case-collaboration-details.md` |
|
|
53
|
+
| Form helpers and error handling | `PCore.getFormUtils()`, `PCore.getErrorHandler()` | `pcore-misc-utilities.md`, `pcore-misc-details.md` |
|
|
54
|
+
| Build deep links, change locale | `PCore.getSemanticUrlUtils()`, `PCore.getLocaleUtils()` | `pcore-rest-data-messaging.md`, `pcore-environment-locale-namespace.md` |
|
|
55
|
+
| GenAI assistant, analytics, personalization | `PCore.getGenAIAssistantUtils()`, `getAnalyticsUtils()`, `getPersonalizationUtils()` | `pcore-case-collaboration-genai.md`, `pcore-analytics-genai-details.md` |
|
|
56
|
+
|
|
57
|
+
For anything not listed here, search the catalog for the method name as described above.
|
|
58
|
+
|
|
59
|
+
## Which skill covers the workflow
|
|
60
|
+
|
|
61
|
+
| Task | Skill |
|
|
62
|
+
| ------------------------------------------------------------------------- | ---------------------------------- |
|
|
63
|
+
| Submit, validate, cancel or delete assignments and cases; attachments | `pconnect-assignment-lifecycle` |
|
|
64
|
+
| Field validation, dependent fields, autosave, persisting widget UI state | `pconnect-forms-and-fields` |
|
|
65
|
+
| Data page subscriptions, pub/sub, real-time updates | `pconnect-data-subscriptions` |
|
|
66
|
+
| Participants, followers, related cases, tags, feed | `pconnect-case-collaboration` |
|
|
67
|
+
| Repeating rows, list view personalization, container lifecycle | `pconnect-lists-and-views` |
|
|
68
|
+
| Deep links, locale switching, GenAI assistant | `pconnect-navigation-locale-genai` |
|
|
69
|
+
|
|
70
|
+
Cross-cutting guidance (testing, error handling, performance, security, accessibility) is in [`.claude/skills/best-practices/`](../../best-practices/).
|
|
71
|
+
|
|
72
|
+
## Official documentation
|
|
73
|
+
|
|
74
|
+
- [Using PCore and PConnect public APIs](https://docs.pega.com/bundle/pcore-pconnect/page/pcore-pconnect-public-apis/api/using-pcore-pconnect-public-apis.html)
|
|
75
|
+
- [Accessing APIs from the PConnect object](https://docs.pega.com/bundle/pcore-pconnect/page/pcore-pconnect-public-apis/api/accessing-apis-pconnect-object.html)
|
|
76
|
+
- [Accessing APIs from the PCore object](https://docs.pega.com/bundle/pcore-pconnect/page/pcore-pconnect-public-apis/api/accessing-apis-pcore-object.html)
|
|
77
|
+
- [Using type definitions for PCore and PConnect APIs](https://docs.pega.com/bundle/pcore-pconnect/page/pcore-pconnect-public-apis/api/using-type-definitions-pcore-pconnect-apis.html)
|
package/src/ai/project/.claude/skills/create-dx-component/references/presentation-essentials.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Presentation essentials
|
|
2
|
+
|
|
3
|
+
Read this instead of the deep references for a typical presentation. Open a deep reference only for the cases listed at the end.
|
|
4
|
+
|
|
5
|
+
## Before you code
|
|
6
|
+
|
|
7
|
+
- There are no Presentation rows in the state matrix: use the Widget rows for the data the case view shows and the Template rows for its regions. Cover optional props being absent (`subheading`, `banners`, `utilities` and similar); long content and narrow width usually apply too.
|
|
8
|
+
- Each covered state gets a `mock.ts` fixture, a story and at least one test assertion.
|
|
9
|
+
- Start from the scaffolded files; the scaffold is a working sample, replace demo content that does not serve the request. Its plain-HTML markup is a placeholder to replace with Cosmos components.
|
|
10
|
+
|
|
11
|
+
## index.tsx
|
|
12
|
+
|
|
13
|
+
- Props are `CaseViewProps` from `@pega/cosmos-react-work` (`CASEVIEW`) or `@pega/cosmos-react-wss` (`WSSCASEVIEW`). Read `node_modules/@pega/cosmos-react-work/lib/components/CaseView/CaseView.types.d.ts` (for `WSSCASEVIEW`, the same path under `node_modules/@pega/cosmos-react-wss/lib/components/CaseView/`; if it is missing, list that folder) before using a prop.
|
|
14
|
+
- No `getPConnect`, `PCore`, `getActionsApi`, `getValidationApi` or any PCore/PConnect API; the lint rule `no-pcore-pconnect-in-presentation` rejects them. If the props do not carry the data, the component should be a Widget.
|
|
15
|
+
- Pure render: output is a deterministic function of props. No data fetching or side-effecting effects; local UI state (open, hover) is fine.
|
|
16
|
+
- Keep `export default withConfiguration(...)`. The scaffold has no `create-nonce` import: add `import '../shared/create-nonce';` if you keep `styled-components` (copy [create-nonce.ts](../assets/create-nonce.ts) into `src/components/shared/` if missing).
|
|
17
|
+
- Cosmos-first (`Flex`, `Text`, `Status`, `Tag`, `Count`, `Icon`, `FieldValueList`, `Tabs`, ...). Check any new Cosmos prop in its `.d.ts`.
|
|
18
|
+
- No inline `style={{ ... }}`, `dangerouslySetInnerHTML`, `console`, dead code, secrets, tokens or per-environment URLs (`check-component.mjs` fails).
|
|
19
|
+
|
|
20
|
+
## config.json
|
|
21
|
+
|
|
22
|
+
- Keep `type: "Presentation"` and the scaffolded `subtype`; `validate-schema` rejects any subtype other than `CASEVIEW` and `WSSCASEVIEW`.
|
|
23
|
+
- `"properties": []` by default. Add a property only if the user wants a designer-configurable setting, and make `index.tsx` read it.
|
|
24
|
+
|
|
25
|
+
## styles.ts
|
|
26
|
+
|
|
27
|
+
- Keep the single default-exported `styled.div` wrapper; add rules only for what Cosmos cannot express.
|
|
28
|
+
- The theme is undefined here: `useTheme()` in `index.tsx`, pass values as transient props.
|
|
29
|
+
|
|
30
|
+
## mock.ts and demo.stories.tsx
|
|
31
|
+
|
|
32
|
+
- `mock.ts` holds sample case view props; extend it when the component reads more props.
|
|
33
|
+
- Stories render the component with those props; no `getPConnect` or `PCore` fakes are needed. One story per covered state.
|
|
34
|
+
|
|
35
|
+
## demo.test.tsx
|
|
36
|
+
|
|
37
|
+
- Assert on rendered output only, querying by role and accessible name first. Use `fireEvent` (no `user-event`).
|
|
38
|
+
- One assertion per covered state, including a render with the optional props absent. Never weaken an assertion.
|
|
39
|
+
|
|
40
|
+
## localizations.json
|
|
41
|
+
|
|
42
|
+
- The scaffold ships one listing its visible strings under `fields` as `"English text": "English text"`. Keep it in step with the text the component renders.
|
|
43
|
+
|
|
44
|
+
## Open a deep reference only when
|
|
45
|
+
|
|
46
|
+
| Situation | Read |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| The full Presentation procedure | [presentation](../../presentation/SKILL.md) |
|
|
49
|
+
| The Widget and Template state rows | [state-matrix.md](./state-matrix.md) |
|
|
50
|
+
| A Cosmos component you have not used, theme palette keys | [cosmos-components.md](./cosmos-components.md), [styles-pattern.md](./styles-pattern.md) |
|
|
51
|
+
| A failing test | [test-pattern.md](./test-pattern.md) |
|
|
52
|
+
| Headings, focus, keyboard, manual checks | [accessibility.md](./accessibility.md) |
|
|
53
|
+
| Localization rules | [localization.md](./localization.md) |
|
|
54
|
+
| A config property | [config-schema.md](./config-schema.md) |
|
|
55
|
+
| The full skeleton or the props contract | [component-patterns.md](./component-patterns.md), [props-contract.md](./props-contract.md) |
|
|
56
|
+
|
|
57
|
+
Finish with `node .claude/skills/validate-component/scripts/check-component.mjs <Org>_<Library>_<Name>`; see [cli-workflow.md](./cli-workflow.md).
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Custom Component Types and the Props Contract
|
|
2
|
+
|
|
3
|
+
> Part of the [create-dx-component skill](../SKILL.md). PCore/PConnect signatures are in the [API catalog](./pcore-pconnect-apis.md).
|
|
4
|
+
|
|
5
|
+
A Constellation custom component is a React function component wrapped with `withConfiguration` from `@pega/cosmos-react-core`. At runtime Constellation renders it with a **props object** built from three sources:
|
|
6
|
+
|
|
7
|
+
1. The values of the properties declared in the component's `config.json` (`properties[].name`), resolved for the current case, page or view.
|
|
8
|
+
2. Standard field props that Constellation adds for field components (`value`, `required`, `readOnly`, `validatemessage`, ...).
|
|
9
|
+
3. `getPConnect`, a function that returns the component's `PConnect` object. This is the entry point to the PConnect and (through the global `PCore`) PCore APIs documented in this skills folder.
|
|
10
|
+
|
|
11
|
+
Stories and tests build the same props object by hand (see [test-pattern.md](./test-pattern.md)).
|
|
12
|
+
|
|
13
|
+
## Choosing the component type
|
|
14
|
+
|
|
15
|
+
| You want to... | Type and subtype | Gets `getPConnect` | Gets `children` |
|
|
16
|
+
| --------------------------------------------------------------------------------- | ----------------------------------------------------- | ------------------ | --------------- |
|
|
17
|
+
| Edit or display a single property value in a new way | `Field` + the matching data subtype | yes | no |
|
|
18
|
+
| Arrange the fields of a form or details view (columns, groups, sections) | `Template` + `FORM` or `DETAILS` | yes | yes |
|
|
19
|
+
| Arrange fields in named regions the designer fills in | `Template` + `FORM-region` or `DETAILS-region` | yes | yes (per region) |
|
|
20
|
+
| Lay out a whole page from regions | `Template` + `PAGE` | yes | yes |
|
|
21
|
+
| Add a self-contained panel that loads its own data (a list, a chart, a summary) | `Widget` + `PAGE` (a page) or `CASE` (a case view) | yes | no |
|
|
22
|
+
| Replace how a case view is rendered from data passed in as props | `Presentation` + `CASEVIEW` or `WSSCASEVIEW` | no | no |
|
|
23
|
+
|
|
24
|
+
Pick the **subtype that matches the property's data type** for a field (`Integer`, `Date`, `Picklist`, `Boolean`, ...). The scaffold for that subtype already handles the display modes and value types that data type needs.
|
|
25
|
+
|
|
26
|
+
## Props common to every component with `getPConnect`
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import type { PConnect } from '@pega/pcore-pconnect-typedefs';
|
|
30
|
+
|
|
31
|
+
interface PConnProps {
|
|
32
|
+
getPConnect: () => typeof PConnect; // always present at runtime
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The scaffolded `PConnProps.d.ts` (in `src/components/shared/` in library mode) defines `PConnProps` and `PConnFieldProps`. Extend `PConnFieldProps` with the extra props your `config.json` declares.
|
|
37
|
+
|
|
38
|
+
## Field components
|
|
39
|
+
|
|
40
|
+
`PConnFieldProps` provides:
|
|
41
|
+
|
|
42
|
+
| Prop | Meaning |
|
|
43
|
+
| --------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
44
|
+
| `value` | Current value of the bound property |
|
|
45
|
+
| `label`, `hideLabel`, `helperText` | Label text, whether to hide it visually, and help text |
|
|
46
|
+
| `placeholder` | Placeholder text |
|
|
47
|
+
| `required`, `disabled`, `readOnly` | Edit state. These can arrive as strings (`'true'`), so normalize them, as the scaffolds do |
|
|
48
|
+
| `validatemessage` | Validation error text. A non-empty string means the field is in error |
|
|
49
|
+
| `status` | Optional status string (for example `'error'`, `'success'`, `'pending'`) |
|
|
50
|
+
| `displayMode` | How to render: editable when empty, or read-only variants (see below) |
|
|
51
|
+
| `testId` | Value for `data-testid` / the design-system `testId` prop |
|
|
52
|
+
| `additionalProps`, `fieldMetadata` | Extra metadata passed by the platform (shape depends on the subtype) |
|
|
53
|
+
|
|
54
|
+
### Display modes
|
|
55
|
+
|
|
56
|
+
The scaffolded fields branch on `displayMode`:
|
|
57
|
+
|
|
58
|
+
- `'DISPLAY_ONLY'`: render just the value, no label or input.
|
|
59
|
+
- anything else (including empty): render the editable control.
|
|
60
|
+
|
|
61
|
+
Always handle `DISPLAY_ONLY`. A field that only renders an input looks broken in details views and tables. Older view metadata and the authoring preview can still pass `'LABELS_LEFT'` (a label/value pair); the runtime itself only distinguishes `DISPLAY_ONLY`, and the scaffolds no longer branch on `LABELS_LEFT` or `'STACKED_LARGE_VAL'`.
|
|
62
|
+
|
|
63
|
+
### Reading and writing the value
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const pConn = getPConnect();
|
|
67
|
+
const actions = pConn.getActionsApi();
|
|
68
|
+
const stateProps = pConn.getStateProps() as { value: string }; // e.g. { value: '.FirstName' }
|
|
69
|
+
const propName = stateProps.value; // the property reference to write to
|
|
70
|
+
|
|
71
|
+
// while the user types: update the value in the store
|
|
72
|
+
actions.updateFieldValue(propName, newValue);
|
|
73
|
+
// when the user leaves the field (blur) or picks an option: commit and trigger dependent logic
|
|
74
|
+
actions.triggerFieldChange(propName, newValue);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The convention used by every scaffolded field: call `updateFieldValue` on change, `triggerFieldChange` on blur, and both on change for controls with no blur moment (selects, checkboxes, radio buttons). Signatures are in [pconnect-actions-api.md](../../references/pconnect-actions-api.md).
|
|
78
|
+
|
|
79
|
+
Read-only data and expressions use `getStateProps()`; see [pconnect-state-config.md](../../references/pconnect-state-config.md).
|
|
80
|
+
|
|
81
|
+
### Validation and error messages
|
|
82
|
+
|
|
83
|
+
- Show `validatemessage` when it is a non-empty string (the scaffolds set the design-system field `status` to `'error'` and pass the message as `info`).
|
|
84
|
+
- Client-side validation: `pConn.getValidationApi().validate(...)` (see [pconnect-validation-api.md](../../references/pconnect-validation-api.md)); clear a message with `pConn.clearErrorMessages({ property })` (see [pconnect-misc-suggestions-creation.md](../../references/pconnect-misc-suggestions-creation.md)).
|
|
85
|
+
|
|
86
|
+
## Template components (FORM, DETAILS, PAGE)
|
|
87
|
+
|
|
88
|
+
Templates receive `children`: React elements for the child components in the template's regions. Render them where they belong in your layout instead of recreating them.
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
const { children = [], NumCols = '1', label, showLabel, getPConnect } = props;
|
|
92
|
+
const inherited = getPConnect().getInheritedProps(); // props inherited from the parent view (readOnly, displayMode, ...)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- `children` can be a single element, an array or nested arrays. Normalize with `[props.children].flat(Infinity).filter(isValidElement)` when you need to inspect them, and guard against an empty or undefined value.
|
|
96
|
+
- `FORM` and `DETAILS` templates lay out `children` in a grid with a configurable number of columns (`NumCols`).
|
|
97
|
+
- `*-region` templates declare named regions in `config.json` (`A`, `B`, ... with format `CONTENTPICKER`); `children` has one entry per region.
|
|
98
|
+
- `DETAILS` marks child fields read-only through `child.props.getPConnect().setInheritedProp('readOnly', true)` and `setInheritedProp('displayMode', 'DISPLAY_ONLY')`.
|
|
99
|
+
- Inherited-prop methods are in [pconnect-state-config.md](../../references/pconnect-state-config.md); child components and `createComponent` are in [pconnect-reference-context-component.md](../../references/pconnect-reference-context-component.md) and [pconnect-misc-suggestions-creation.md](../../references/pconnect-misc-suggestions-creation.md).
|
|
100
|
+
|
|
101
|
+
## Widget components
|
|
102
|
+
|
|
103
|
+
A widget owns its data. The scaffolds fetch data in `useEffect` through `PCore` and render it with design-system components:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
const pConn = getPConnect();
|
|
107
|
+
const context = pConn.getContextName();
|
|
108
|
+
const caseID = pConn.getValue(PCore.getConstants().CASE_INFO.CASE_INFO_ID, '');
|
|
109
|
+
|
|
110
|
+
PCore.getDataApiUtils()
|
|
111
|
+
.getData('D_pyWorkHistory', { dataViewParameters: { CaseInstanceKey: caseID } }, context)
|
|
112
|
+
.then((response) => { /* map response.data.data to rows */ });
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`PCore.getConstants()` is documented in [pcore-misc-utilities.md](../../references/pcore-misc-utilities.md). Rules for widgets: track a loading state, handle `response.data.data === null`, handle rejection, and re-fetch only when the inputs (`context`, `caseID`) change. See [pcore-rest-data-details.md](../../references/pcore-rest-data-details.md) and the [error handling](../../best-practices/error-handling-and-resiliency.md) and [performance](../../best-practices/performance-and-efficiency.md) guides.
|
|
116
|
+
|
|
117
|
+
Use `pConn.getLocalizationService().getLocalizedText('...')` for user-visible strings (see [pconnect-case-info-data-info-localization.md](../../references/pconnect-case-info-data-info-localization.md)). Widget scaffolds include a `localizations.json` file for translations.
|
|
118
|
+
|
|
119
|
+
## Presentation components
|
|
120
|
+
|
|
121
|
+
`CASEVIEW` and `WSSCASEVIEW` components do not use `getPConnect` or `PCore`. They receive everything as props whose type comes from the design system (`CaseViewProps` from `@pega/cosmos-react-work`, or from `@pega/cosmos-react-wss` for `WSSCASEVIEW`). Implement the rendering only; the type tells you which props exist.
|
|
122
|
+
|
|
123
|
+
## Rules that apply to every type
|
|
124
|
+
|
|
125
|
+
1. Export the component as `export default withConfiguration(MyComponent)`.
|
|
126
|
+
2. Keep `import '../shared/create-nonce';` in `index.tsx` (Presentation scaffolds do not include it). It sets the webpack nonce for styles.
|
|
127
|
+
3. Render through the design-system (`@pega/cosmos-react-core`, `-work`, `-wss`) components. They provide accessibility and theming. Wrap the output in the scaffolded `styled-components` wrapper from `styles.ts`.
|
|
128
|
+
4. Every prop you read must be declared in the props interface **and** exist as a `config.json` property (or be a standard prop above). See [config-schema.md](./config-schema.md).
|
|
129
|
+
5. Do not use PCore or PConnect members that are not documented in this folder. Treat them as unsupported.
|
|
130
|
+
6. Do not read or write the DOM or `window` for application data. Use the PCore and PConnect APIs.
|
|
131
|
+
|
|
132
|
+
## `index.tsx` file rules
|
|
133
|
+
|
|
134
|
+
### Required shape
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { Input, withConfiguration } from '@pega/cosmos-react-core';
|
|
139
|
+
import type { PConnFieldProps } from '../shared/PConnProps';
|
|
140
|
+
import '../shared/create-nonce';
|
|
141
|
+
import handleEvent from './event-utils';
|
|
142
|
+
import StyledWrapper from './styles';
|
|
143
|
+
|
|
144
|
+
interface Props extends PConnFieldProps {
|
|
145
|
+
// one entry per extra property in config.json, all optional
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function AcmeLibComponentName(props: Props) { ... }
|
|
149
|
+
|
|
150
|
+
export default withConfiguration(AcmeLibComponentName);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
- The inner function name is `AcmeLib<ComponentName>` — PascalCase, matching `config.json` `name` with underscores removed.
|
|
154
|
+
- `import '../shared/create-nonce';` is side-effect only (the scaffold generates it in `src/components/shared/`). Never remove it, never bind it to a variable.
|
|
155
|
+
- Always default-export through `withConfiguration()`.
|
|
156
|
+
- `Props` extends `PConnFieldProps`; every added prop is optional and mirrors a `config.json` property name exactly.
|
|
157
|
+
- Never edit `PConnProps.d.ts`, `create-nonce.ts`, or `event-utils.ts` — they are contract files.
|
|
158
|
+
|
|
159
|
+
### Cosmos-first in this file
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
The canonical rule lives in [AGENTS.md](../../../../AGENTS.md) and loads on every request. What it means *in this file*: the component's rendered tree must be Cosmos components. `StyledWrapper` from `./styles` is a positioning shell, not a layout system — put `Flex`/`Grid` inside it, not `<div className='row'>`.
|
|
163
|
+
|
|
164
|
+
**Never use inline `style={{ ... }}` here.** Custom CSS belongs in `styles.ts`.
|
|
165
|
+
|
|
166
|
+
**Verify every Cosmos prop you have not used before** by reading `node_modules/@pega/cosmos-react-core/lib/components/<Name>/<Name>.d.ts`. Prop names here are often not what they sound like — `Banner` needs an array, `EmptyState` uses `message` not `title`, `Tag` needs `children` not `label`, and `Divider` / `Badge` / `IconButton` / `Tab` do not exist. The known traps are in [cosmos-components.md](../../../../.claude/skills/create-dx-component/references/cosmos-components.md).
|
|
167
|
+
|
|
168
|
+
To read a Cosmos theme value, call `useTheme()` in this file and pass the value into the styled component as a prop — the theme does not reach `styles.ts` on its own.
|
|
169
|
+
|
|
170
|
+
### Lint constraints that bite here
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
- `no-console` — no `console.*`
|
|
174
|
+
- `no-plusplus` — use `+= 1`
|
|
175
|
+
- `no-nested-ternary`, `no-lonely-if`
|
|
176
|
+
- `func-names` — no anonymous function expressions
|
|
177
|
+
- `radix` — `parseInt(x, 10)`
|
|
178
|
+
- `react/no-array-index-key` — use a stable key, not the index
|
|
179
|
+
- `react/button-has-type` — every `<button>` needs an explicit `type`
|
|
180
|
+
- `@typescript-eslint/no-unused-vars` — every import, variable, state value, helper, and interface field must be referenced. Delete anything that is not.
|
|
181
|
+
|
|
182
|
+
`any` and `@ts-ignore` are permitted. `PCore` is a global — do not import it.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# State Matrix
|
|
2
|
+
|
|
3
|
+
Decide which states a component covers **before** writing code, and show the list to the user with the contract. The same list then drives `mock.ts`, the stories and the tests, so a state that is not in the matrix is not built, not demonstrated and not tested.
|
|
4
|
+
|
|
5
|
+
Cover every row marked *applicable* for the type. Mark a row *not applicable* with a reason instead of silently skipping it.
|
|
6
|
+
|
|
7
|
+
## How to use it
|
|
8
|
+
|
|
9
|
+
1. Copy the rows for the component type into the plan and mark each *applicable* or *not applicable*.
|
|
10
|
+
2. For each applicable row, state what is visible, what is interactive and what is announced.
|
|
11
|
+
3. Give each applicable row one `mock.ts` fixture and one story (see [storybook-pattern.md](./storybook-pattern.md)).
|
|
12
|
+
4. Give each applicable row at least one assertion in `demo.test.tsx` (see [test-pattern.md](./test-pattern.md)).
|
|
13
|
+
|
|
14
|
+
Do not model states as independent booleans (`isLoading`, `hasError`, `isEmpty`) when contradictory combinations are possible. Use one status value, for example `'loading' | 'ready' | 'empty' | 'error'`.
|
|
15
|
+
|
|
16
|
+
## Field
|
|
17
|
+
|
|
18
|
+
A Field receives its state from the platform as props ([props-contract.md](./props-contract.md)). The matrix is about how the control reacts to those props.
|
|
19
|
+
|
|
20
|
+
| State | Platform input | Check |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| Empty | `value` is `''` or `undefined` | Control stays controlled (default to `''`); placeholder or empty display is meaningful |
|
|
23
|
+
| Populated | `value` set | Formatted consistently; the stored value is not the formatted text |
|
|
24
|
+
| Editing | user input | Change goes through `handleEvent`; commit happens on the event the contract names (change or blur) |
|
|
25
|
+
| Invalid | `validatemessage` is a non-empty string | Error is visible, tied to the control and not conveyed by color alone |
|
|
26
|
+
| Required | `required` | Required status is shown without color alone |
|
|
27
|
+
| Disabled | `disabled` | Not focusable or operable; the reason is clear when the label alone does not explain it |
|
|
28
|
+
| Read-only | `readOnly` | Value readable; does not look editable |
|
|
29
|
+
| Display only | `displayMode === 'DISPLAY_ONLY'` | Just the value, no label or input (details views and tables) |
|
|
30
|
+
| Long or malformed value | very long string, wrong type, `null` | Layout holds and nothing throws |
|
|
31
|
+
| Narrow width | small container | Label, control, helper text and error reflow in order |
|
|
32
|
+
| Suggestion available / accepted | platform suggestion, `status` | Pending status shown only when the suggested value is among the options; accepted and rejected paths both clear it |
|
|
33
|
+
| Field warning | `showFieldMessage` with `messageConfig` | Shown when enabled, suppressed when read-only, hidden when its condition is false |
|
|
34
|
+
| Unchanged or empty blur | blur with the stored value | No commit; `validate` still runs so a required field reports its error |
|
|
35
|
+
|
|
36
|
+
Add `status` (`'error'`, `'success'`, `'pending'`) rows only if the component reads it.
|
|
37
|
+
|
|
38
|
+
## Widget
|
|
39
|
+
|
|
40
|
+
A Widget owns its data, so the matrix is mostly about the request lifecycle. Keep these cases distinct: they are often merged and then misreported.
|
|
41
|
+
|
|
42
|
+
| State | Check |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| Initial loading | Placeholder (`Progress` or a skeleton) keeps the layout stable |
|
|
45
|
+
| Loaded | Data and available actions are clear |
|
|
46
|
+
| Empty | Wording separates "no results" from "not configured" |
|
|
47
|
+
| Error | Message is actionable, hides internals, and offers a retry when retrying can help |
|
|
48
|
+
| Refreshing | Existing content stays visible while new data loads |
|
|
49
|
+
| Stale response | A late response for an older request is ignored |
|
|
50
|
+
| Action pending | Duplicate activation is blocked and progress is announced |
|
|
51
|
+
| Partial data | One failing section does not blank the others (only if the widget has sections) |
|
|
52
|
+
| Permission-limited | Restricted content is omitted and not reported as an error (only if the data source can restrict) |
|
|
53
|
+
| Failed mutation | A message is shown in a `Banner`, the control is re-enabled, and the list is unchanged |
|
|
54
|
+
| Late response | A response for an older request or an unmounted widget is ignored |
|
|
55
|
+
| Offline | A visible offline message accompanies Retry; no spinner that cannot finish |
|
|
56
|
+
| Long content | Lists, labels and actions stay usable |
|
|
57
|
+
| Narrow width | Information hierarchy survives; actions stay reachable |
|
|
58
|
+
|
|
59
|
+
For the fetch itself follow the [data widget cookbook](../cookbooks/build-a-data-widget.md). Cancel or ignore a request on unmount and on a context change.
|
|
60
|
+
|
|
61
|
+
## Template
|
|
62
|
+
|
|
63
|
+
A Template arranges `children`, so the matrix is about composition.
|
|
64
|
+
|
|
65
|
+
| State | Check |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| All regions populated | Reading order is clear |
|
|
68
|
+
| Optional region empty | Layout collapses or keeps space on purpose |
|
|
69
|
+
| Required region empty | The problem is visible, not a blank gap |
|
|
70
|
+
| One child unavailable or unsupported | The other regions keep working |
|
|
71
|
+
| Long child content | Wraps, scrolls or reflows predictably |
|
|
72
|
+
| Narrow width | Regions stack in the intended semantic order |
|
|
73
|
+
| Wide width | Extra space is handled without fixed positioning |
|
|
74
|
+
| All children of a region hidden | The region and its heading disappear; no empty titled section |
|
|
75
|
+
| Read-only parent | Children are forced to `readOnly` and `DISPLAY_ONLY`, and none show an input |
|
|
76
|
+
| Active tab becomes hidden or removed | Falls back to the first visible tab; no dangling id |
|
|
77
|
+
| Nested template | Inherits or overrides the parent column count on purpose |
|
|
78
|
+
| Missing or string config | `NumCols` as `'2'`, absent or non-numeric falls back to one column |
|
|
79
|
+
|
|
80
|
+
## Presentation
|
|
81
|
+
|
|
82
|
+
Use the Widget rows for the data the case view loads and the Template rows for its regions.
|
|
83
|
+
|
|
84
|
+
## AI-assisted content
|
|
85
|
+
|
|
86
|
+
Add these rows to a Widget or Field that shows or acts on generated content, in addition to the rows above. See the best-practices notes on GenAI integration in the API catalog.
|
|
87
|
+
|
|
88
|
+
| State | Check |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| Generating | A progress indication and partial output that can be read. Announce start and finish politely, not every update |
|
|
91
|
+
| Complete | The result is shown with a clear marker that it is machine-generated |
|
|
92
|
+
| Cancelled | The user can stop it, and the interface returns to a usable state with nothing half-applied |
|
|
93
|
+
| Failed or unavailable | An actionable message, a retry, and the rest of the component still works |
|
|
94
|
+
| Refused or blocked | A plain explanation instead of a blank or an error code |
|
|
95
|
+
| Low confidence or uncertain | Flagged, not presented as fact |
|
|
96
|
+
| Awaiting review | Nothing takes effect until a person accepts it, when the requirements say so |
|
|
97
|
+
| Feedback | The user can accept, reject or rate the result |
|
|
98
|
+
| Untrusted output | Rendered as plain text or sanitized; never as raw HTML |
|
|
99
|
+
|
|
100
|
+
## Recording the result
|
|
101
|
+
|
|
102
|
+
Write the matrix as a table in the plan you show the user, with a column for the story name that will demonstrate each row. After building, every row marked applicable must have a story and an assertion. If one cannot be built (for example a state the mocked PConnect cannot reproduce), say so in the report instead of dropping it.
|