@salesforce/templates 66.3.0 → 66.3.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/lib/templates/flexipage/RecordPage/_flexipage.flexipage-meta.xml +0 -24
- package/lib/templates/project/reactb2e/.a4drules/{graphql.md → features/feature-graphql-graphql-data-access-rule.md} +186 -125
- package/lib/templates/project/reactb2e/.a4drules/features/feature-react-agentforce-conversation-client-embedded-agent-rule.md +32 -0
- package/lib/templates/project/reactb2e/.a4drules/features/feature-react-chart-analytics-charts-rule.md +27 -0
- package/lib/templates/project/reactb2e/.a4drules/skills/feature-graphql-graphql-data-access/SKILL.md +155 -0
- package/lib/templates/project/{reactb2x/.a4drules/graphql/tools/knowledge/lds-explore-graphql-schema.md → reactb2e/.a4drules/skills/feature-graphql-graphql-data-access/docs/explore-schema.md} +58 -29
- package/lib/templates/project/{reactb2x/.a4drules/graphql/tools/knowledge/lds-generate-graphql-mutationquery.md → reactb2e/.a4drules/skills/feature-graphql-graphql-data-access/docs/generate-mutation-query.md} +52 -42
- package/lib/templates/project/{reactb2x/.a4drules/graphql/tools/knowledge/lds-generate-graphql-readquery.md → reactb2e/.a4drules/skills/feature-graphql-graphql-data-access/docs/generate-read-query.md} +32 -22
- package/lib/templates/project/{reactb2x/.a4drules/graphql/tools/schemas/shared.graphqls → reactb2e/.a4drules/skills/feature-graphql-graphql-data-access/docs/shared-schema.graphqls} +1 -1
- package/lib/templates/project/reactb2e/.a4drules/skills/feature-micro-frontend-micro-frontend/SKILL.md +137 -0
- package/lib/templates/project/reactb2e/.a4drules/skills/feature-react-agentforce-conversation-client-embedded-agent/SKILL.md +108 -0
- package/lib/templates/project/reactb2e/.a4drules/skills/feature-react-agentforce-conversation-client-embedded-agent/docs/embed-examples.md +182 -0
- package/lib/templates/project/reactb2e/.a4drules/skills/feature-react-chart-analytics-charts/SKILL.md +41 -0
- package/lib/templates/project/reactb2e/.a4drules/skills/feature-react-chart-analytics-charts/docs/schema-mapping.md +4 -0
- package/lib/templates/project/reactb2e/.a4drules/webapp-code-quality.md +136 -0
- package/lib/templates/project/reactb2e/.a4drules/{images.md → webapp-images.md} +6 -4
- package/lib/templates/project/reactb2e/.a4drules/webapp-no-node-e.md +3 -2
- package/lib/templates/project/reactb2e/.a4drules/webapp-react.md +149 -0
- package/lib/templates/project/reactb2e/.a4drules/{typescript.md → webapp-typescript.md} +10 -29
- package/lib/templates/project/reactb2e/.a4drules/webapp.md +60 -45
- package/lib/templates/project/reactb2e/AGENT.md +1 -1
- package/lib/templates/project/reactb2e/CHANGELOG.md +377 -0
- package/lib/templates/project/reactb2e/README.md +38 -4
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/CHANGELOG.md +10 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/README.md +35 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/package.json +17 -7
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/appLayout.tsx +76 -10
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/__inherit_AgentforceConversationClient.tsx +3 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/alerts/status-alert.tsx +49 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/layouts/card-layout.tsx +29 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/alert.tsx +76 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/button.tsx +67 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/card.tsx +103 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/dialog.tsx +162 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/field.tsx +237 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/index.ts +84 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/input.tsx +19 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/label.tsx +22 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/pagination.tsx +132 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/select.tsx +193 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/separator.tsx +26 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/skeleton.tsx +14 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/spinner.tsx +16 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/table.tsx +114 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/ui/tabs.tsx +88 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components.json +18 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/constants.ts +39 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/api/index.ts +19 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/api/objectDetailService.ts +125 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/api/objectInfoGraphQLService.ts +194 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/api/objectInfoService.ts +199 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/api/recordListGraphQLService.ts +365 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/DetailFields.tsx +55 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/DetailForm.tsx +146 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/DetailHeader.tsx +34 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/DetailLayoutSections.tsx +80 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/Section.tsx +108 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/SectionRow.tsx +20 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/UiApiDetailForm.tsx +140 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/formatted/FieldValueDisplay.tsx +73 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/formatted/FormattedAddress.tsx +29 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/formatted/FormattedEmail.tsx +17 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/formatted/FormattedPhone.tsx +24 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/formatted/FormattedText.tsx +11 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/formatted/FormattedUrl.tsx +29 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/detail/formatted/index.ts +6 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/filters/FilterField.tsx +54 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/filters/FilterInput.tsx +55 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/filters/FilterSelect.tsx +72 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/filters/FiltersPanel.tsx +380 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/forms/filters-form.tsx +114 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/forms/submit-button.tsx +47 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/search/GlobalSearchInput.tsx +114 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/search/ResultCardFields.tsx +71 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/search/SearchHeader.tsx +31 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/search/SearchPagination.tsx +144 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/search/SearchResultCard.tsx +136 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/search/SearchResultsPanel.tsx +197 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/components/shared/LoadingFallback.tsx +61 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/filters/FilterInput.tsx +55 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/filters/FilterSelect.tsx +72 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/hooks/form.tsx +209 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/hooks/index.ts +22 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/hooks/useObjectInfoBatch.ts +65 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/hooks/useObjectSearchData.ts +395 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/hooks/useRecordDetailLayout.ts +156 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/hooks/useRecordListGraphQL.ts +135 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/pages/DetailPage.tsx +109 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/pages/GlobalSearch.tsx +229 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/types/filters/filters.ts +120 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/types/filters/picklist.ts +32 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/types/index.ts +4 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/types/objectInfo/objectInfo.ts +166 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/types/recordDetail/recordDetail.ts +61 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/types/search/searchResults.ts +229 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/apiUtils.ts +125 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/cacheUtils.ts +76 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/debounce.ts +89 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/fieldUtils.ts +354 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/fieldValueExtractor.ts +67 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/filterUtils.ts +32 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/formDataTransformUtils.ts +260 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/formUtils.ts +142 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/graphQLNodeFieldUtils.ts +186 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/graphQLObjectInfoAdapter.ts +319 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/graphQLRecordAdapter.ts +90 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/index.ts +59 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/layoutTransformUtils.ts +236 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/linkUtils.ts +14 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/paginationUtils.ts +49 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/recordUtils.ts +159 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/features/global-search/utils/sanitizationUtils.ts +49 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/lib/utils.ts +6 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/pages/Home.tsx +11 -10
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/pages/TestAccPage.tsx +19 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/routes.tsx +28 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/styles/global.css +122 -0
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/vite.config.ts +2 -1
- package/lib/templates/project/reactb2e/package.json +1 -1
- package/lib/templates/project/reactb2x/.a4drules/{graphql.md → features/feature-graphql-graphql-data-access-rule.md} +186 -125
- package/lib/templates/project/reactb2x/.a4drules/features/feature-react-agentforce-conversation-client-embedded-agent-rule.md +32 -0
- package/lib/templates/project/reactb2x/.a4drules/features/feature-react-chart-analytics-charts-rule.md +27 -0
- package/lib/templates/project/reactb2x/.a4drules/skills/feature-graphql-graphql-data-access/SKILL.md +155 -0
- package/lib/templates/project/{reactb2e/.a4drules/graphql/tools/knowledge/lds-explore-graphql-schema.md → reactb2x/.a4drules/skills/feature-graphql-graphql-data-access/docs/explore-schema.md} +58 -29
- package/lib/templates/project/{reactb2e/.a4drules/graphql/tools/knowledge/lds-generate-graphql-mutationquery.md → reactb2x/.a4drules/skills/feature-graphql-graphql-data-access/docs/generate-mutation-query.md} +52 -42
- package/lib/templates/project/{reactb2e/.a4drules/graphql/tools/knowledge/lds-generate-graphql-readquery.md → reactb2x/.a4drules/skills/feature-graphql-graphql-data-access/docs/generate-read-query.md} +32 -22
- package/lib/templates/project/{reactb2e/.a4drules/graphql/tools/schemas/shared.graphqls → reactb2x/.a4drules/skills/feature-graphql-graphql-data-access/docs/shared-schema.graphqls} +1 -1
- package/lib/templates/project/reactb2x/.a4drules/skills/feature-micro-frontend-micro-frontend/SKILL.md +137 -0
- package/lib/templates/project/reactb2x/.a4drules/skills/feature-react-agentforce-conversation-client-embedded-agent/SKILL.md +108 -0
- package/lib/templates/project/reactb2x/.a4drules/skills/feature-react-agentforce-conversation-client-embedded-agent/docs/embed-examples.md +182 -0
- package/lib/templates/project/reactb2x/.a4drules/skills/feature-react-chart-analytics-charts/SKILL.md +41 -0
- package/lib/templates/project/reactb2x/.a4drules/skills/feature-react-chart-analytics-charts/docs/schema-mapping.md +4 -0
- package/lib/templates/project/reactb2x/.a4drules/webapp-code-quality.md +136 -0
- package/lib/templates/project/reactb2x/.a4drules/{images.md → webapp-images.md} +6 -4
- package/lib/templates/project/reactb2x/.a4drules/webapp-no-node-e.md +3 -2
- package/lib/templates/project/reactb2x/.a4drules/webapp-react.md +149 -0
- package/lib/templates/project/reactb2x/.a4drules/{typescript.md → webapp-typescript.md} +10 -29
- package/lib/templates/project/reactb2x/.a4drules/webapp.md +60 -45
- package/lib/templates/project/reactb2x/AGENT.md +1 -1
- package/lib/templates/project/reactb2x/CHANGELOG.md +377 -0
- package/lib/templates/project/reactb2x/README.md +58 -4
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/CHANGELOG.md +10 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/README.md +35 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/package.json +8 -7
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/appLayout.tsx +75 -3
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/alerts/status-alert.tsx +36 -32
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/layouts/card-layout.tsx +29 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/alert.tsx +61 -54
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/button.tsx +57 -57
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/card.tsx +86 -75
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/dialog.tsx +129 -110
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/field.tsx +208 -193
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/index.ts +65 -53
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/input.tsx +14 -14
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/label.tsx +17 -14
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/pagination.tsx +108 -88
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/select.tsx +156 -146
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/separator.tsx +19 -19
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/skeleton.tsx +10 -10
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/spinner.tsx +12 -11
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/table.tsx +96 -69
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/tabs.tsx +71 -61
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components.json +1 -1
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/constants.ts +39 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{context → features/authentication/context}/AuthContext.tsx +1 -1
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/authentication}/footers/footer-link.tsx +1 -1
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/authentication}/forms/auth-form.tsx +4 -4
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/authentication}/forms/submit-button.tsx +4 -4
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{hooks → features/authentication/hooks}/form.tsx +13 -9
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/authentication}/layout/card-skeleton.tsx +2 -2
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/authentication}/layout/centered-page-layout.tsx +2 -3
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{layouts → features/authentication/layouts}/AuthAppLayout.tsx +2 -2
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components/auth → features/authentication/layouts}/authenticationRouteLayout.tsx +2 -2
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components/auth → features/authentication/layouts}/privateRouteLayout.tsx +2 -2
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{pages → features/authentication/pages}/ChangePassword.tsx +6 -6
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{pages → features/authentication/pages}/ForgotPassword.tsx +5 -5
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{pages → features/authentication/pages}/Login.tsx +6 -6
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{pages → features/authentication/pages}/Profile.tsx +22 -13
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{pages → features/authentication/pages}/Register.tsx +6 -11
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{pages → features/authentication/pages}/ResetPassword.tsx +8 -8
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components/auth → features/authentication}/sessionTimeout/SessionTimeoutValidator.tsx +6 -6
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/index.ts +19 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/objectDetailService.ts +125 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/objectInfoGraphQLService.ts +194 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/objectInfoService.ts +199 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/recordListGraphQLService.ts +365 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/DetailFields.tsx +55 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/DetailForm.tsx +146 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/DetailHeader.tsx +34 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/DetailLayoutSections.tsx +80 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/Section.tsx +108 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/SectionRow.tsx +20 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/UiApiDetailForm.tsx +140 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FieldValueDisplay.tsx +73 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FormattedAddress.tsx +29 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FormattedEmail.tsx +17 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FormattedPhone.tsx +24 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FormattedText.tsx +11 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FormattedUrl.tsx +29 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/index.ts +6 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/filters/FilterField.tsx +54 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/filters/FilterInput.tsx +55 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/filters/FilterSelect.tsx +72 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/filters/FiltersPanel.tsx +380 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/forms/filters-form.tsx +114 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/forms/submit-button.tsx +47 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/GlobalSearchInput.tsx +114 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/ResultCardFields.tsx +71 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/SearchHeader.tsx +31 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/SearchPagination.tsx +144 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/SearchResultCard.tsx +136 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/SearchResultsPanel.tsx +197 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/shared/LoadingFallback.tsx +61 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/filters/FilterInput.tsx +55 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/filters/FilterSelect.tsx +72 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/form.tsx +209 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/index.ts +22 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useObjectInfoBatch.ts +65 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useObjectSearchData.ts +395 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useRecordDetailLayout.ts +156 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useRecordListGraphQL.ts +135 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/pages/DetailPage.tsx +109 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/pages/GlobalSearch.tsx +229 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/filters/filters.ts +120 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/filters/picklist.ts +32 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/index.ts +4 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/objectInfo/objectInfo.ts +166 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/recordDetail/recordDetail.ts +61 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/search/searchResults.ts +229 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/apiUtils.ts +125 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/cacheUtils.ts +76 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/debounce.ts +89 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/fieldUtils.ts +354 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/fieldValueExtractor.ts +67 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/filterUtils.ts +32 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/formDataTransformUtils.ts +260 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/formUtils.ts +142 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/graphQLNodeFieldUtils.ts +186 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/graphQLObjectInfoAdapter.ts +319 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/graphQLRecordAdapter.ts +90 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/index.ts +59 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/layoutTransformUtils.ts +236 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/linkUtils.ts +14 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/paginationUtils.ts +49 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/recordUtils.ts +159 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/sanitizationUtils.ts +49 -0
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/lib/utils.ts +3 -3
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/Home.tsx +11 -10
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/routes.tsx +33 -11
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/styles/global.css +107 -107
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/vite.config.ts +2 -1
- package/lib/templates/project/reactb2x/package.json +1 -1
- package/lib/templates/webapplication/reactbasic/CHANGELOG.md +10 -0
- package/lib/templates/webapplication/reactbasic/README.md +75 -0
- package/lib/templates/webapplication/reactbasic/package.json +13 -5
- package/lib/templates/webapplication/reactbasic/src/appLayout.tsx +75 -3
- package/lib/templates/webapplication/reactbasic/src/components/alerts/status-alert.tsx +49 -0
- package/lib/templates/webapplication/reactbasic/src/components/layouts/card-layout.tsx +29 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/alert.tsx +76 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/button.tsx +67 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/card.tsx +103 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/dialog.tsx +162 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/field.tsx +237 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/index.ts +84 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/input.tsx +19 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/label.tsx +22 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/pagination.tsx +132 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/select.tsx +193 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/separator.tsx +26 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/skeleton.tsx +14 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/spinner.tsx +16 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/table.tsx +114 -0
- package/lib/templates/webapplication/reactbasic/src/components/ui/tabs.tsx +88 -0
- package/lib/templates/webapplication/reactbasic/src/components.json +18 -0
- package/lib/templates/webapplication/reactbasic/src/lib/utils.ts +6 -0
- package/lib/templates/webapplication/reactbasic/src/styles/global.css +122 -0
- package/lib/templates/webapplication/reactbasic/vite.config.ts +2 -1
- package/lib/templates/webapplication/webappbasic/README.md +15 -0
- package/lib/utils/webappTemplateUtils.d.ts +10 -0
- package/lib/utils/webappTemplateUtils.js +55 -7
- package/lib/utils/webappTemplateUtils.js.map +1 -1
- package/package.json +5 -5
- package/lib/templates/project/reactb2e/.a4drules/README.md +0 -35
- package/lib/templates/project/reactb2e/.a4drules/a4d-webapp-generate.md +0 -27
- package/lib/templates/project/reactb2e/.a4drules/build-validation.md +0 -78
- package/lib/templates/project/reactb2e/.a4drules/code-quality.md +0 -137
- package/lib/templates/project/reactb2e/.a4drules/graphql/tools/knowledge/lds-guide-graphql.md +0 -205
- package/lib/templates/project/reactb2e/.a4drules/react.md +0 -387
- package/lib/templates/project/reactb2e/.a4drules/react_image_processing.md +0 -45
- package/lib/templates/project/reactb2e/.a4drules/ui-layout.md +0 -23
- package/lib/templates/project/reactb2e/.a4drules/webapp-nav-and-placeholders.md +0 -33
- package/lib/templates/project/reactb2e/.a4drules/webapp-ui-first.md +0 -32
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/build/vite.config.d.ts +0 -2
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/build/vite.config.js +0 -93
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/package-lock.json +0 -14392
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/api/graphql-operations-types.ts +0 -116
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/api/utils/accounts.ts +0 -33
- package/lib/templates/project/reactb2e/force-app/main/default/webapplications/appreacttemplateb2e/src/api/utils/query/highRevenueAccountsQuery.graphql +0 -29
- package/lib/templates/project/reactb2x/.a4drules/README.md +0 -35
- package/lib/templates/project/reactb2x/.a4drules/a4d-webapp-generate.md +0 -27
- package/lib/templates/project/reactb2x/.a4drules/build-validation.md +0 -78
- package/lib/templates/project/reactb2x/.a4drules/code-quality.md +0 -137
- package/lib/templates/project/reactb2x/.a4drules/graphql/tools/knowledge/lds-guide-graphql.md +0 -205
- package/lib/templates/project/reactb2x/.a4drules/react.md +0 -387
- package/lib/templates/project/reactb2x/.a4drules/react_image_processing.md +0 -45
- package/lib/templates/project/reactb2x/.a4drules/ui-layout.md +0 -23
- package/lib/templates/project/reactb2x/.a4drules/webapp-nav-and-placeholders.md +0 -33
- package/lib/templates/project/reactb2x/.a4drules/webapp-ui-first.md +0 -32
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/build/vite.config.d.ts +0 -2
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/build/vite.config.js +0 -93
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/package-lock.json +0 -18408
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/api/graphql-operations-types.ts +0 -116
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/api/utils/accounts.ts +0 -33
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/api/utils/query/highRevenueAccountsQuery.graphql +0 -29
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/layout/card-layout.tsx +0 -23
- package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/lib/data-sdk.ts +0 -21
- package/lib/templates/webapplication/reactbasic/build/vite.config.d.ts +0 -2
- package/lib/templates/webapplication/reactbasic/build/vite.config.js +0 -93
- package/lib/templates/webapplication/reactbasic/package-lock.json +0 -14373
- package/lib/templates/webapplication/reactbasic/src/api/graphql-operations-types.ts +0 -116
- package/lib/templates/webapplication/reactbasic/src/api/utils/accounts.ts +0 -33
- package/lib/templates/webapplication/reactbasic/src/api/utils/query/highRevenueAccountsQuery.graphql +0 -29
- /package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components/auth → features/authentication}/authHelpers.ts +0 -0
- /package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components/auth → features/authentication}/authenticationConfig.ts +0 -0
- /package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{hooks → features/authentication/hooks}/useCountdownTimer.ts +0 -0
- /package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{hooks → features/authentication/hooks}/useRetryWithBackoff.ts +0 -0
- /package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components/auth → features/authentication}/sessionTimeout/sessionTimeService.ts +0 -0
- /package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{components/auth → features/authentication}/sessionTimeout/sessionTimeoutConfig.ts +0 -0
- /package/lib/templates/project/reactb2x/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/authentication/utils}/helpers.ts +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
3
|
+
import { Tabs as TabsPrimitive } from 'radix-ui';
|
|
4
|
+
|
|
5
|
+
import { cn } from '../../lib/utils';
|
|
6
|
+
|
|
7
|
+
function Tabs({
|
|
8
|
+
className,
|
|
9
|
+
orientation = 'horizontal',
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
|
12
|
+
return (
|
|
13
|
+
<TabsPrimitive.Root
|
|
14
|
+
data-slot="tabs"
|
|
15
|
+
data-orientation={orientation}
|
|
16
|
+
className={cn(
|
|
17
|
+
'gap-2 group/tabs flex data-horizontal:flex-col',
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const tabsListVariants = cva(
|
|
26
|
+
'rounded-lg p-[3px] group-data-horizontal/tabs:h-8 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col',
|
|
27
|
+
{
|
|
28
|
+
variants: {
|
|
29
|
+
variant: {
|
|
30
|
+
default: 'bg-muted',
|
|
31
|
+
line: 'gap-1 bg-transparent',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
variant: 'default',
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
function TabsList({
|
|
41
|
+
className,
|
|
42
|
+
variant = 'default',
|
|
43
|
+
...props
|
|
44
|
+
}: React.ComponentProps<typeof TabsPrimitive.List> &
|
|
45
|
+
VariantProps<typeof tabsListVariants>) {
|
|
46
|
+
return (
|
|
47
|
+
<TabsPrimitive.List
|
|
48
|
+
data-slot="tabs-list"
|
|
49
|
+
data-variant={variant}
|
|
50
|
+
className={cn(tabsListVariants({ variant }), className)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function TabsTrigger({
|
|
57
|
+
className,
|
|
58
|
+
...props
|
|
59
|
+
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
|
60
|
+
return (
|
|
61
|
+
<TabsPrimitive.Trigger
|
|
62
|
+
data-slot="tabs-trigger"
|
|
63
|
+
className={cn(
|
|
64
|
+
"gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg:not([class*='size-'])]:size-4 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
65
|
+
'group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent',
|
|
66
|
+
'data-active:bg-background dark:data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 data-active:text-foreground',
|
|
67
|
+
'after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100',
|
|
68
|
+
className
|
|
69
|
+
)}
|
|
70
|
+
{...props}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function TabsContent({
|
|
76
|
+
className,
|
|
77
|
+
...props
|
|
78
|
+
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
|
79
|
+
return (
|
|
80
|
+
<TabsPrimitive.Content
|
|
81
|
+
data-slot="tabs-content"
|
|
82
|
+
className={cn('text-sm flex-1 outline-none', className)}
|
|
83
|
+
{...props}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"style": "new-york",
|
|
3
|
+
"rsc": true,
|
|
4
|
+
"tailwind": {
|
|
5
|
+
"config": "",
|
|
6
|
+
"css": "styles/global.css",
|
|
7
|
+
"baseColor": "neutral",
|
|
8
|
+
"cssVariables": true
|
|
9
|
+
},
|
|
10
|
+
"iconLibrary": "lucide",
|
|
11
|
+
"aliases": {
|
|
12
|
+
"components": "@/components",
|
|
13
|
+
"utils": "@/lib/utils",
|
|
14
|
+
"ui": "@/components/ui",
|
|
15
|
+
"lib": "@/lib",
|
|
16
|
+
"hooks": "@/hooks"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application-wide Constants
|
|
3
|
+
*
|
|
4
|
+
* Defines constants used throughout the global search feature.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Object API names to search across in the global search feature.
|
|
9
|
+
* Currently supports single object search.
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* - Array of Salesforce object API names
|
|
13
|
+
* - First element is used as the primary search object
|
|
14
|
+
* - Can be extended to support multiple objects in the future
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const objectApiName = OBJECT_API_NAMES[0]; // 'Account'
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const OBJECT_API_NAMES = ["Account"] as const;
|
|
22
|
+
|
|
23
|
+
/** Fallback title when record display name cannot be resolved (e.g. before load or no name field). */
|
|
24
|
+
export const DEFAULT_DETAIL_PAGE_TITLE = "Untitled";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Default page size for search results pagination.
|
|
28
|
+
* This should match one of the values in PAGE_SIZE_OPTIONS from paginationUtils.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* - Default value is 20 (second option in PAGE_SIZE_OPTIONS)
|
|
32
|
+
* - Can be changed by user via pagination controls
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE);
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export const DEFAULT_PAGE_SIZE = 20;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API layer: object metadata (GraphQL), layout + record detail (REST layout + GraphQL record), record list/single (GraphQL).
|
|
3
|
+
*/
|
|
4
|
+
export { objectInfoService } from "./objectInfoService";
|
|
5
|
+
export { objectDetailService, extractFieldsFromLayout } from "./objectDetailService";
|
|
6
|
+
export type { RecordDetailResult } from "./objectDetailService";
|
|
7
|
+
export {
|
|
8
|
+
getRecordsGraphQL,
|
|
9
|
+
getRecordByIdGraphQL,
|
|
10
|
+
buildGetRecordsQuery,
|
|
11
|
+
buildWhereFromCriteria,
|
|
12
|
+
buildOrderByFromSort,
|
|
13
|
+
} from "./recordListGraphQLService";
|
|
14
|
+
export type {
|
|
15
|
+
RecordListGraphQLResult,
|
|
16
|
+
RecordListGraphQLVariables,
|
|
17
|
+
RecordListGraphQLOptions,
|
|
18
|
+
GraphQLRecordNode,
|
|
19
|
+
} from "./recordListGraphQLService";
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record detail service: layout (REST), object metadata (GraphQL), single record (GraphQL).
|
|
3
|
+
*
|
|
4
|
+
* getRecordDetail orchestrates layout + objectInfoBatch + getRecordByIdGraphQL for the detail page.
|
|
5
|
+
* Layout is still REST (uiApiClient); record and object info are GraphQL-backed.
|
|
6
|
+
*
|
|
7
|
+
* @module api/objectDetailService
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { uiApiClient } from "@salesforce/webapp-experimental/api";
|
|
11
|
+
import type { LayoutResponse } from "../types/recordDetail/recordDetail";
|
|
12
|
+
import { LayoutResponseSchema } from "../types/recordDetail/recordDetail";
|
|
13
|
+
import { fetchAndValidate, safeEncodePath } from "../utils/apiUtils";
|
|
14
|
+
import { objectInfoService } from "./objectInfoService";
|
|
15
|
+
import type { ObjectInfoResult } from "../types/objectInfo/objectInfo";
|
|
16
|
+
import { getRecordByIdGraphQL, type GraphQLRecordNode } from "./recordListGraphQLService";
|
|
17
|
+
import type { Column } from "../types/search/searchResults";
|
|
18
|
+
import { calculateFieldsToFetch } from "../utils/recordUtils";
|
|
19
|
+
|
|
20
|
+
/** Fallback when record type is unknown. Prefer recordTypeId from the record (e.g. from search or record response) when available. */
|
|
21
|
+
const DEFAULT_RECORD_TYPE_ID = "012000000000000AAA";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Returns field API names to request for a record from the given layout and object metadata.
|
|
25
|
+
* Used to derive GraphQL columns from layout (detail view). Delegates to recordUtils.calculateFieldsToFetch.
|
|
26
|
+
*
|
|
27
|
+
* @param objectMetadata - Object info (fields, relationshipName, etc.).
|
|
28
|
+
* @param layout - Layout response (sections, layoutItems, layoutComponents).
|
|
29
|
+
* @returns Array of field API names (e.g. ["Name", "OwnerId", "Owner", "CreatedDate"]).
|
|
30
|
+
*/
|
|
31
|
+
export function extractFieldsFromLayout(
|
|
32
|
+
objectMetadata: ObjectInfoResult,
|
|
33
|
+
layout: LayoutResponse,
|
|
34
|
+
): string[] {
|
|
35
|
+
const [optionalFields] = calculateFieldsToFetch(objectMetadata, layout, false);
|
|
36
|
+
return optionalFields;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Fetches the Full/View layout for an object (REST). Used by detail view to render sections/rows/items.
|
|
41
|
+
*
|
|
42
|
+
* @param objectApiName - Object API name.
|
|
43
|
+
* @param recordTypeId - Record type Id (default master).
|
|
44
|
+
* @param signal - Optional abort signal.
|
|
45
|
+
*/
|
|
46
|
+
export async function getLayout(
|
|
47
|
+
objectApiName: string,
|
|
48
|
+
recordTypeId: string = DEFAULT_RECORD_TYPE_ID,
|
|
49
|
+
signal?: AbortSignal,
|
|
50
|
+
): Promise<LayoutResponse> {
|
|
51
|
+
const params = new URLSearchParams({
|
|
52
|
+
layoutType: "Full",
|
|
53
|
+
mode: "View",
|
|
54
|
+
recordTypeId,
|
|
55
|
+
});
|
|
56
|
+
return fetchAndValidate(
|
|
57
|
+
(abortSignal) =>
|
|
58
|
+
uiApiClient.get(`/layout/${safeEncodePath(objectApiName)}?${params.toString()}`, {
|
|
59
|
+
signal: abortSignal,
|
|
60
|
+
}),
|
|
61
|
+
{
|
|
62
|
+
schema: LayoutResponseSchema,
|
|
63
|
+
errorContext: `layout for ${objectApiName}`,
|
|
64
|
+
signal,
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface RecordDetailResult {
|
|
70
|
+
layout: LayoutResponse;
|
|
71
|
+
record: GraphQLRecordNode;
|
|
72
|
+
objectMetadata: ObjectInfoResult;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Converts layout-derived optionalFields (field API names) to Column[] for GraphQL node selection.
|
|
77
|
+
* Uses unqualified names (no entity prefix) so the GraphQL query matches UI API shape.
|
|
78
|
+
* Other Column fields (label, searchable, sortable) are only required by the type; GraphQL selection uses fieldApiName only.
|
|
79
|
+
*/
|
|
80
|
+
function optionalFieldsToColumns(optionalFields: string[]): Column[] {
|
|
81
|
+
return optionalFields.map((fieldApiName) => ({
|
|
82
|
+
fieldApiName,
|
|
83
|
+
label: "",
|
|
84
|
+
searchable: false,
|
|
85
|
+
sortable: false,
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Fetches everything needed for the detail page: layout (REST), object metadata (GraphQL), single record (GraphQL).
|
|
91
|
+
* Layout drives which fields are requested; getRecordByIdGraphQL fetches that field set by Id.
|
|
92
|
+
*
|
|
93
|
+
* @param objectApiName - Object API name.
|
|
94
|
+
* @param recordId - Record Id.
|
|
95
|
+
* @param recordTypeId - Record type (default master).
|
|
96
|
+
* @param signal - Optional abort signal.
|
|
97
|
+
* @returns { layout, record, objectMetadata } for DetailForm / UiApiDetailForm.
|
|
98
|
+
*/
|
|
99
|
+
export async function getRecordDetail(
|
|
100
|
+
objectApiName: string,
|
|
101
|
+
recordId: string,
|
|
102
|
+
recordTypeId: string = DEFAULT_RECORD_TYPE_ID,
|
|
103
|
+
signal?: AbortSignal,
|
|
104
|
+
): Promise<RecordDetailResult> {
|
|
105
|
+
const layout = await getLayout(objectApiName, recordTypeId, signal);
|
|
106
|
+
const objectMetadata = await objectInfoService.getObjectInfoBatch(objectApiName, signal);
|
|
107
|
+
const firstResult = objectMetadata?.results?.[0]?.result;
|
|
108
|
+
if (!firstResult) {
|
|
109
|
+
throw new Error(`Object metadata not found for ${objectApiName}`);
|
|
110
|
+
}
|
|
111
|
+
// Layout-driven optionalFields (fields shown on the detail layout), not list columns
|
|
112
|
+
const [optionalFields] = calculateFieldsToFetch(firstResult, layout, false);
|
|
113
|
+
const columns = optionalFieldsToColumns(optionalFields);
|
|
114
|
+
const record = await getRecordByIdGraphQL(objectApiName, recordId, columns);
|
|
115
|
+
if (!record) {
|
|
116
|
+
throw new Error(`Record not found: ${recordId}`);
|
|
117
|
+
}
|
|
118
|
+
return { layout, record, objectMetadata: firstResult };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export const objectDetailService = {
|
|
122
|
+
extractFieldsFromLayout,
|
|
123
|
+
getLayout,
|
|
124
|
+
getRecordDetail,
|
|
125
|
+
};
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object metadata GraphQL service (uiapi.objectInfos).
|
|
3
|
+
*
|
|
4
|
+
* Single endpoint for object describe and picklist values. Used by objectInfoService
|
|
5
|
+
* to implement getObjectInfoBatch and getPicklistValues. Not used directly by UI.
|
|
6
|
+
*
|
|
7
|
+
* @module api/objectInfoGraphQLService
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { getDataSDK } from "@salesforce/sdk-data";
|
|
11
|
+
|
|
12
|
+
/** GraphQL objectInfoInputs for requesting picklist values (API v65.0+). Only apiName and fieldNames are sent; record type filtering is done from the response. */
|
|
13
|
+
export interface ObjectInfoInput {
|
|
14
|
+
apiName: string;
|
|
15
|
+
fieldNames?: string[] | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Raw GraphQL response shape for uiapi.objectInfos (flexible for schema casing). */
|
|
19
|
+
export interface ObjectInfosGraphQLResponse {
|
|
20
|
+
uiapi?: {
|
|
21
|
+
objectInfos?: Array<Record<string, unknown>>;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Builds objectInfos query (metadata only). Uses apiNames only — do not pass objectInfoInputs.
|
|
27
|
+
*/
|
|
28
|
+
function buildObjectInfosQuery(): string {
|
|
29
|
+
return `query GetObjectInfos($apiNames: [String!]!) {
|
|
30
|
+
uiapi {
|
|
31
|
+
objectInfos(apiNames: $apiNames) {
|
|
32
|
+
ApiName
|
|
33
|
+
label
|
|
34
|
+
labelPlural
|
|
35
|
+
nameFields
|
|
36
|
+
defaultRecordTypeId
|
|
37
|
+
keyPrefix
|
|
38
|
+
layoutable
|
|
39
|
+
queryable
|
|
40
|
+
searchable
|
|
41
|
+
updateable
|
|
42
|
+
deletable
|
|
43
|
+
createable
|
|
44
|
+
custom
|
|
45
|
+
mruEnabled
|
|
46
|
+
feedEnabled
|
|
47
|
+
fields {
|
|
48
|
+
ApiName
|
|
49
|
+
label
|
|
50
|
+
dataType
|
|
51
|
+
relationshipName
|
|
52
|
+
reference
|
|
53
|
+
compound
|
|
54
|
+
compoundFieldName
|
|
55
|
+
compoundComponentName
|
|
56
|
+
controllingFields
|
|
57
|
+
controllerName
|
|
58
|
+
referenceToInfos {
|
|
59
|
+
ApiName
|
|
60
|
+
nameFields
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
recordTypeInfos {
|
|
64
|
+
recordTypeId
|
|
65
|
+
name
|
|
66
|
+
master
|
|
67
|
+
available
|
|
68
|
+
defaultRecordTypeMapping
|
|
69
|
+
}
|
|
70
|
+
themeInfo {
|
|
71
|
+
color
|
|
72
|
+
iconUrl
|
|
73
|
+
}
|
|
74
|
+
childRelationships {
|
|
75
|
+
relationshipName
|
|
76
|
+
fieldName
|
|
77
|
+
childObjectApiName
|
|
78
|
+
}
|
|
79
|
+
dependentFields {
|
|
80
|
+
controllingField
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Builds objectInfos query with picklist values (API v65.0+).
|
|
89
|
+
* Schema requires objectInfos to be called with either apiNames or objectInfoInputs, not both.
|
|
90
|
+
* This query uses objectInfoInputs only.
|
|
91
|
+
*/
|
|
92
|
+
function buildObjectInfosWithPicklistsQuery(): string {
|
|
93
|
+
return `query GetPicklistValues($objectInfoInputs: [ObjectInfoInput!]!) {
|
|
94
|
+
uiapi {
|
|
95
|
+
objectInfos(objectInfoInputs: $objectInfoInputs) {
|
|
96
|
+
ApiName
|
|
97
|
+
label
|
|
98
|
+
labelPlural
|
|
99
|
+
nameFields
|
|
100
|
+
defaultRecordTypeId
|
|
101
|
+
keyPrefix
|
|
102
|
+
layoutable
|
|
103
|
+
queryable
|
|
104
|
+
searchable
|
|
105
|
+
updateable
|
|
106
|
+
deletable
|
|
107
|
+
createable
|
|
108
|
+
custom
|
|
109
|
+
mruEnabled
|
|
110
|
+
feedEnabled
|
|
111
|
+
fields {
|
|
112
|
+
ApiName
|
|
113
|
+
label
|
|
114
|
+
dataType
|
|
115
|
+
relationshipName
|
|
116
|
+
reference
|
|
117
|
+
compound
|
|
118
|
+
compoundFieldName
|
|
119
|
+
compoundComponentName
|
|
120
|
+
controllingFields
|
|
121
|
+
controllerName
|
|
122
|
+
referenceToInfos {
|
|
123
|
+
ApiName
|
|
124
|
+
nameFields
|
|
125
|
+
}
|
|
126
|
+
... on PicklistField {
|
|
127
|
+
picklistValuesByRecordTypeIDs {
|
|
128
|
+
recordTypeID
|
|
129
|
+
defaultValue {
|
|
130
|
+
value
|
|
131
|
+
}
|
|
132
|
+
picklistValues {
|
|
133
|
+
label
|
|
134
|
+
value
|
|
135
|
+
validFor
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
recordTypeInfos {
|
|
141
|
+
recordTypeId
|
|
142
|
+
name
|
|
143
|
+
master
|
|
144
|
+
available
|
|
145
|
+
defaultRecordTypeMapping
|
|
146
|
+
}
|
|
147
|
+
themeInfo {
|
|
148
|
+
color
|
|
149
|
+
iconUrl
|
|
150
|
+
}
|
|
151
|
+
childRelationships {
|
|
152
|
+
relationshipName
|
|
153
|
+
fieldName
|
|
154
|
+
childObjectApiName
|
|
155
|
+
}
|
|
156
|
+
dependentFields {
|
|
157
|
+
controllingField
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Fetches object metadata for the given objects via GraphQL.
|
|
166
|
+
*
|
|
167
|
+
* @param apiNames - Object API names (e.g. ["Account", "Contact"]).
|
|
168
|
+
* @param options.objectInfoInputs - When set, picklist values for specified fields are included (API v65.0+).
|
|
169
|
+
* @param options.signal - Optional abort signal.
|
|
170
|
+
* @returns Raw uiapi.objectInfos response (adapt to REST shape via graphQLObjectInfosToBatchResponse).
|
|
171
|
+
*/
|
|
172
|
+
export async function getObjectInfosGraphQL(
|
|
173
|
+
apiNames: string[],
|
|
174
|
+
options?: {
|
|
175
|
+
objectInfoInputs?: ObjectInfoInput[] | null;
|
|
176
|
+
signal?: AbortSignal;
|
|
177
|
+
},
|
|
178
|
+
): Promise<ObjectInfosGraphQLResponse> {
|
|
179
|
+
const names = apiNames.length ? apiNames : [];
|
|
180
|
+
const hasInputs = options?.objectInfoInputs != null && options.objectInfoInputs.length > 0;
|
|
181
|
+
const query = hasInputs ? buildObjectInfosWithPicklistsQuery() : buildObjectInfosQuery();
|
|
182
|
+
const variables: Record<string, unknown> = hasInputs
|
|
183
|
+
? { objectInfoInputs: options!.objectInfoInputs }
|
|
184
|
+
: { apiNames: names };
|
|
185
|
+
const data = await getDataSDK();
|
|
186
|
+
const response = await data.graphql?.<ObjectInfosGraphQLResponse>(query, variables);
|
|
187
|
+
|
|
188
|
+
if (response?.errors?.length) {
|
|
189
|
+
const errorMessages = response.errors.map((e) => e.message).join("; ");
|
|
190
|
+
throw new Error(`GraphQL Error: ${errorMessages}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return response?.data ?? ({} as ObjectInfosGraphQLResponse);
|
|
194
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { uiApiClient } from "@salesforce/webapp-experimental/api";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { SearchResultsResponse, KeywordSearchResult } from "../types/search/searchResults";
|
|
4
|
+
import { SearchResultsResponseSchema } from "../types/search/searchResults";
|
|
5
|
+
import { FilterCriteriaArraySchema } from "../types/filters/filters";
|
|
6
|
+
import type { Filter } from "../types/filters/filters";
|
|
7
|
+
import { FilterArraySchema } from "../types/filters/filters";
|
|
8
|
+
import type { PicklistValue } from "../types/filters/picklist";
|
|
9
|
+
import type { ObjectInfoBatchResponse } from "../types/objectInfo/objectInfo";
|
|
10
|
+
import { fetchAndValidate, safeEncodePath } from "../utils/apiUtils";
|
|
11
|
+
import { getObjectInfosGraphQL } from "./objectInfoGraphQLService";
|
|
12
|
+
import {
|
|
13
|
+
graphQLObjectInfosToBatchResponse,
|
|
14
|
+
extractPicklistValuesFromGraphQLObjectInfo,
|
|
15
|
+
} from "../utils/graphQLObjectInfoAdapter";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Object info and search service.
|
|
19
|
+
*
|
|
20
|
+
* - getObjectInfoBatch / getPicklistValues: GraphQL (objectInfoGraphQLService).
|
|
21
|
+
* - getObjectListFilters, searchResults: REST (search-info, search/results).
|
|
22
|
+
* Hooks use this service; components do not call it directly.
|
|
23
|
+
*
|
|
24
|
+
* @module api/objectInfoService
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** Cache key: sorted, comma-joined object API names. */
|
|
28
|
+
function getObjectInfoBatchCacheKey(objectApiNames: string): string {
|
|
29
|
+
const names = objectApiNames
|
|
30
|
+
.split(",")
|
|
31
|
+
.map((s) => s.trim())
|
|
32
|
+
.filter(Boolean);
|
|
33
|
+
return [...names].sort().join(",");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const objectInfoBatchCache = new Map<string, ObjectInfoBatchResponse>();
|
|
37
|
+
const objectInfoBatchInFlight = new Map<string, Promise<ObjectInfoBatchResponse>>();
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Fetches batch object information for the specified objects via GraphQL (uiapi.objectInfos).
|
|
41
|
+
* Results are cached by object set so List, Home, and Detail views share one request.
|
|
42
|
+
*
|
|
43
|
+
* @param objectApiNames - Comma-separated list of object API names (e.g., "Account,AccountBrand")
|
|
44
|
+
* @param signal - Optional AbortSignal to cancel the request
|
|
45
|
+
* @returns Promise resolving to the object info batch response (REST-compatible shape)
|
|
46
|
+
*/
|
|
47
|
+
export async function getObjectInfoBatch(
|
|
48
|
+
objectApiNames: string,
|
|
49
|
+
signal?: AbortSignal,
|
|
50
|
+
): Promise<ObjectInfoBatchResponse> {
|
|
51
|
+
const names = objectApiNames
|
|
52
|
+
.split(",")
|
|
53
|
+
.map((s) => s.trim())
|
|
54
|
+
.filter(Boolean);
|
|
55
|
+
if (names.length === 0) {
|
|
56
|
+
return { results: [] };
|
|
57
|
+
}
|
|
58
|
+
const key = getObjectInfoBatchCacheKey(objectApiNames);
|
|
59
|
+
const cached = objectInfoBatchCache.get(key);
|
|
60
|
+
if (cached) return Promise.resolve(cached);
|
|
61
|
+
const inFlight = objectInfoBatchInFlight.get(key);
|
|
62
|
+
if (inFlight) return inFlight;
|
|
63
|
+
const promise = (async () => {
|
|
64
|
+
try {
|
|
65
|
+
const response = await getObjectInfosGraphQL(names, { signal });
|
|
66
|
+
const nodes = response?.uiapi?.objectInfos ?? [];
|
|
67
|
+
const result = graphQLObjectInfosToBatchResponse(nodes, names);
|
|
68
|
+
objectInfoBatchCache.set(key, result);
|
|
69
|
+
return result;
|
|
70
|
+
} finally {
|
|
71
|
+
objectInfoBatchInFlight.delete(key);
|
|
72
|
+
}
|
|
73
|
+
})();
|
|
74
|
+
objectInfoBatchInFlight.set(key, promise);
|
|
75
|
+
return promise;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Fetches list filters for a specific object.
|
|
80
|
+
* Salesforce Search supports "Search Filters" (refinements) which are configured per object.
|
|
81
|
+
* This API returns the available filters (e.g., "Close Date", "Stage") that the user
|
|
82
|
+
* can use to narrow down the search results.
|
|
83
|
+
* @param objectApiName - The API name of the object (e.g., "Account")
|
|
84
|
+
* @param signal - Optional AbortSignal to cancel the request
|
|
85
|
+
* @returns Promise resolving to the search filters array
|
|
86
|
+
*/
|
|
87
|
+
export async function getObjectListFilters(
|
|
88
|
+
objectApiName: string,
|
|
89
|
+
signal?: AbortSignal,
|
|
90
|
+
): Promise<Filter[]> {
|
|
91
|
+
return fetchAndValidate(
|
|
92
|
+
(abortSignal) =>
|
|
93
|
+
uiApiClient.get(`/search-info/${safeEncodePath(objectApiName)}/filters`, {
|
|
94
|
+
signal: abortSignal,
|
|
95
|
+
}),
|
|
96
|
+
{
|
|
97
|
+
schema: FilterArraySchema,
|
|
98
|
+
errorContext: `filters for ${objectApiName}`,
|
|
99
|
+
extractData: (data: unknown) => {
|
|
100
|
+
if (!data) return [];
|
|
101
|
+
return Array.isArray(data) ? data : (data as { filters?: unknown }).filters || [];
|
|
102
|
+
},
|
|
103
|
+
signal,
|
|
104
|
+
},
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Fetches picklist values for a specific field via GraphQL (uiapi.objectInfos with objectInfoInputs).
|
|
110
|
+
*
|
|
111
|
+
* @param objectApiName - The API name of the object (e.g., "Account")
|
|
112
|
+
* @param fieldName - The API name of the field (e.g., "Type")
|
|
113
|
+
* @param recordTypeId - Optional record type ID (defaults to "012000000000000AAA" which is the default/master record type)
|
|
114
|
+
* @param signal - Optional AbortSignal to cancel the request
|
|
115
|
+
* @returns Promise resolving to an array of picklist values
|
|
116
|
+
*/
|
|
117
|
+
export async function getPicklistValues(
|
|
118
|
+
objectApiName: string,
|
|
119
|
+
fieldName: string,
|
|
120
|
+
recordTypeId: string = "012000000000000AAA",
|
|
121
|
+
signal?: AbortSignal,
|
|
122
|
+
): Promise<PicklistValue[]> {
|
|
123
|
+
const response = await getObjectInfosGraphQL([objectApiName], {
|
|
124
|
+
objectInfoInputs: [
|
|
125
|
+
{
|
|
126
|
+
apiName: objectApiName,
|
|
127
|
+
fieldNames: [fieldName],
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
signal,
|
|
131
|
+
});
|
|
132
|
+
const nodes = response?.uiapi?.objectInfos ?? [];
|
|
133
|
+
const node = nodes[0];
|
|
134
|
+
if (!node) return [];
|
|
135
|
+
return extractPicklistValuesFromGraphQLObjectInfo(node, fieldName, recordTypeId);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Zod Schema for Search Parameters
|
|
139
|
+
const SearchParamsSchema = z.object({
|
|
140
|
+
filters: FilterCriteriaArraySchema.optional(),
|
|
141
|
+
pageSize: z.number().optional(),
|
|
142
|
+
pageToken: z.string().optional(),
|
|
143
|
+
sortBy: z.string().optional(),
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Search parameters for keyword search
|
|
148
|
+
*/
|
|
149
|
+
export type SearchParams = z.infer<typeof SearchParamsSchema>;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Performs a keyword search on a specific object.
|
|
153
|
+
* Returns records that match the text query along with pagination information.
|
|
154
|
+
*
|
|
155
|
+
* @param query - The search query string
|
|
156
|
+
* @param objectApiName - The API name of the object to search (e.g., "Account")
|
|
157
|
+
* @param params - Optional search parameters (pageSize, pageToken, filters, sortBy)
|
|
158
|
+
* @param signal - Optional AbortSignal to cancel the request
|
|
159
|
+
* @returns Promise resolving to the keyword search result with records and pagination tokens
|
|
160
|
+
*/
|
|
161
|
+
export async function searchResults(
|
|
162
|
+
query: string,
|
|
163
|
+
objectApiName: string,
|
|
164
|
+
params?: SearchParams,
|
|
165
|
+
signal?: AbortSignal,
|
|
166
|
+
): Promise<KeywordSearchResult> {
|
|
167
|
+
const searchParams = new URLSearchParams({
|
|
168
|
+
q: query,
|
|
169
|
+
objectApiName: objectApiName,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const body = {
|
|
173
|
+
filters: params?.filters ?? [],
|
|
174
|
+
pageSize: params?.pageSize ?? 50,
|
|
175
|
+
pageToken: params?.pageToken ?? "0",
|
|
176
|
+
sortBy: params?.sortBy ?? "",
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const response = await fetchAndValidate<SearchResultsResponse>(
|
|
180
|
+
(abortSignal) =>
|
|
181
|
+
uiApiClient.post(`/search/results/keyword?${searchParams.toString()}`, body, {
|
|
182
|
+
signal: abortSignal,
|
|
183
|
+
}),
|
|
184
|
+
{
|
|
185
|
+
schema: SearchResultsResponseSchema,
|
|
186
|
+
errorContext: `search results for ${objectApiName} with query "${query}"`,
|
|
187
|
+
signal,
|
|
188
|
+
},
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
return response.keywordSearchResult;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export const objectInfoService = {
|
|
195
|
+
getObjectInfoBatch,
|
|
196
|
+
getObjectListFilters,
|
|
197
|
+
getPicklistValues,
|
|
198
|
+
searchResults,
|
|
199
|
+
};
|