@salesforce/ui-bundle-template-feature-react-global-search 1.117.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.
Files changed (231) hide show
  1. package/LICENSE.txt +82 -0
  2. package/README.md +250 -0
  3. package/dist/.forceignore +15 -0
  4. package/dist/.husky/pre-commit +4 -0
  5. package/dist/.prettierignore +11 -0
  6. package/dist/.prettierrc +17 -0
  7. package/dist/AGENT.md +193 -0
  8. package/dist/CHANGELOG.md +2128 -0
  9. package/dist/README.md +28 -0
  10. package/dist/config/project-scratch-def.json +13 -0
  11. package/dist/eslint.config.js +7 -0
  12. package/dist/force-app/main/default/uiBundles/feature-react-global-search/.forceignore +15 -0
  13. package/dist/force-app/main/default/uiBundles/feature-react-global-search/.graphqlrc.yml +2 -0
  14. package/dist/force-app/main/default/uiBundles/feature-react-global-search/.prettierignore +9 -0
  15. package/dist/force-app/main/default/uiBundles/feature-react-global-search/.prettierrc +11 -0
  16. package/dist/force-app/main/default/uiBundles/feature-react-global-search/CHANGELOG.md +10 -0
  17. package/dist/force-app/main/default/uiBundles/feature-react-global-search/README.md +75 -0
  18. package/dist/force-app/main/default/uiBundles/feature-react-global-search/codegen.yml +95 -0
  19. package/dist/force-app/main/default/uiBundles/feature-react-global-search/components.json +18 -0
  20. package/dist/force-app/main/default/uiBundles/feature-react-global-search/e2e/app.spec.ts +17 -0
  21. package/dist/force-app/main/default/uiBundles/feature-react-global-search/eslint.config.js +169 -0
  22. package/dist/force-app/main/default/uiBundles/feature-react-global-search/feature-react-global-search.uibundle-meta.xml +7 -0
  23. package/dist/force-app/main/default/uiBundles/feature-react-global-search/index.html +12 -0
  24. package/dist/force-app/main/default/uiBundles/feature-react-global-search/package.json +70 -0
  25. package/dist/force-app/main/default/uiBundles/feature-react-global-search/playwright.config.ts +24 -0
  26. package/dist/force-app/main/default/uiBundles/feature-react-global-search/scripts/get-graphql-schema.mjs +68 -0
  27. package/dist/force-app/main/default/uiBundles/feature-react-global-search/scripts/rewrite-e2e-assets.mjs +23 -0
  28. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/api/graphqlClient.ts +25 -0
  29. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/app.tsx +17 -0
  30. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/appLayout.tsx +83 -0
  31. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/assets/icons/book.svg +3 -0
  32. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/assets/icons/copy.svg +4 -0
  33. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/assets/icons/rocket.svg +3 -0
  34. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/assets/icons/star.svg +3 -0
  35. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/assets/images/codey-1.png +0 -0
  36. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/assets/images/codey-2.png +0 -0
  37. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/assets/images/codey-3.png +0 -0
  38. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/assets/images/vibe-codey.svg +194 -0
  39. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/alerts/status-alert.tsx +49 -0
  40. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/layouts/card-layout.tsx +29 -0
  41. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/alert.tsx +76 -0
  42. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/badge.tsx +48 -0
  43. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/breadcrumb.tsx +109 -0
  44. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/button.tsx +67 -0
  45. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/calendar.tsx +232 -0
  46. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/card.tsx +103 -0
  47. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/checkbox.tsx +32 -0
  48. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/collapsible.tsx +33 -0
  49. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/datePicker.tsx +127 -0
  50. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/dialog.tsx +162 -0
  51. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/field.tsx +237 -0
  52. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/index.ts +84 -0
  53. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/input.tsx +19 -0
  54. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/label.tsx +22 -0
  55. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/pagination.tsx +132 -0
  56. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/popover.tsx +89 -0
  57. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/select.tsx +193 -0
  58. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/separator.tsx +26 -0
  59. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/skeleton.tsx +14 -0
  60. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/sonner.tsx +20 -0
  61. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/spinner.tsx +16 -0
  62. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/table.tsx +114 -0
  63. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/tabs.tsx +88 -0
  64. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/api/objectDetailService.ts +102 -0
  65. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/api/objectInfoGraphQLService.ts +137 -0
  66. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/api/objectInfoService.ts +95 -0
  67. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/api/recordListGraphQLService.ts +364 -0
  68. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/DetailFields.tsx +55 -0
  69. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/DetailForm.tsx +146 -0
  70. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/DetailHeader.tsx +34 -0
  71. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/DetailLayoutSections.tsx +80 -0
  72. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/Section.tsx +108 -0
  73. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/SectionRow.tsx +20 -0
  74. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/UiApiDetailForm.tsx +140 -0
  75. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FieldValueDisplay.tsx +73 -0
  76. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FormattedAddress.tsx +29 -0
  77. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FormattedEmail.tsx +17 -0
  78. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FormattedPhone.tsx +24 -0
  79. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FormattedText.tsx +11 -0
  80. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FormattedUrl.tsx +29 -0
  81. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/filters/FilterField.tsx +54 -0
  82. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/filters/FilterInput.tsx +55 -0
  83. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/filters/FilterSelect.tsx +72 -0
  84. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/filters/FiltersPanel.tsx +380 -0
  85. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/forms/filters-form.tsx +114 -0
  86. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/forms/submit-button.tsx +47 -0
  87. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/GlobalSearchInput.tsx +114 -0
  88. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/ResultCardFields.tsx +71 -0
  89. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/SearchHeader.tsx +31 -0
  90. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/SearchPagination.tsx +144 -0
  91. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/SearchResultCard.tsx +138 -0
  92. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/SearchResultsPanel.tsx +197 -0
  93. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/shared/LoadingFallback.tsx +61 -0
  94. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/constants.ts +39 -0
  95. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/filters/FilterInput.tsx +55 -0
  96. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/filters/FilterSelect.tsx +72 -0
  97. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/hooks/form.tsx +209 -0
  98. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/hooks/useObjectInfoBatch.ts +72 -0
  99. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/hooks/useObjectSearchData.ts +174 -0
  100. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/hooks/useRecordDetailLayout.ts +137 -0
  101. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/hooks/useRecordListGraphQL.ts +135 -0
  102. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/pages/DetailPage.tsx +109 -0
  103. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/pages/GlobalSearch.tsx +235 -0
  104. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/filters/filters.ts +121 -0
  105. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/filters/picklist.ts +6 -0
  106. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/objectInfo/objectInfo.ts +49 -0
  107. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/recordDetail/recordDetail.ts +61 -0
  108. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/schema.d.ts +200 -0
  109. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/search/searchResults.ts +229 -0
  110. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/apiUtils.ts +59 -0
  111. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/cacheUtils.ts +76 -0
  112. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/debounce.ts +90 -0
  113. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/fieldUtils.ts +354 -0
  114. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/fieldValueExtractor.ts +67 -0
  115. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/filterUtils.ts +32 -0
  116. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/formDataTransformUtils.ts +260 -0
  117. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/formUtils.ts +142 -0
  118. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/graphQLNodeFieldUtils.ts +186 -0
  119. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/graphQLObjectInfoAdapter.ts +77 -0
  120. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/graphQLRecordAdapter.ts +90 -0
  121. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/layoutTransformUtils.ts +236 -0
  122. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/linkUtils.ts +14 -0
  123. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/paginationUtils.ts +49 -0
  124. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/recordUtils.ts +159 -0
  125. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/sanitizationUtils.ts +50 -0
  126. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/index.ts +120 -0
  127. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/lib/utils.ts +6 -0
  128. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/navigationMenu.tsx +80 -0
  129. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/pages/Home.tsx +13 -0
  130. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/pages/NotFound.tsx +18 -0
  131. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/router-utils.tsx +35 -0
  132. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/routes.tsx +44 -0
  133. package/dist/force-app/main/default/uiBundles/feature-react-global-search/src/styles/global.css +135 -0
  134. package/dist/force-app/main/default/uiBundles/feature-react-global-search/tsconfig.json +42 -0
  135. package/dist/force-app/main/default/uiBundles/feature-react-global-search/tsconfig.node.json +13 -0
  136. package/dist/force-app/main/default/uiBundles/feature-react-global-search/ui-bundle.json +7 -0
  137. package/dist/force-app/main/default/uiBundles/feature-react-global-search/vite-env.d.ts +1 -0
  138. package/dist/force-app/main/default/uiBundles/feature-react-global-search/vite.config.ts +106 -0
  139. package/dist/force-app/main/default/uiBundles/feature-react-global-search/vitest-env.d.ts +2 -0
  140. package/dist/force-app/main/default/uiBundles/feature-react-global-search/vitest.config.ts +11 -0
  141. package/dist/force-app/main/default/uiBundles/feature-react-global-search/vitest.setup.ts +1 -0
  142. package/dist/jest.config.js +6 -0
  143. package/dist/package-lock.json +9995 -0
  144. package/dist/package.json +40 -0
  145. package/dist/scripts/apex/hello.apex +10 -0
  146. package/dist/scripts/graphql-search.sh +191 -0
  147. package/dist/scripts/prepare-import-unique-fields.js +122 -0
  148. package/dist/scripts/setup-cli.mjs +563 -0
  149. package/dist/scripts/sf-project-setup.mjs +66 -0
  150. package/dist/scripts/soql/account.soql +6 -0
  151. package/dist/sfdx-project.json +12 -0
  152. package/package.json +53 -0
  153. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/__inherit__appLayout.tsx +9 -0
  154. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/alerts/__inherit__status-alert.tsx +27 -0
  155. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/layouts/__inherit__card-layout.tsx +9 -0
  156. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/__inherit__alert.tsx +41 -0
  157. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/__inherit__button.tsx +45 -0
  158. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/__inherit__card.tsx +33 -0
  159. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/__inherit__field.tsx +62 -0
  160. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/__inherit__input.tsx +5 -0
  161. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/__inherit__label.tsx +8 -0
  162. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/__inherit__pagination.tsx +47 -0
  163. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/__inherit__select.tsx +57 -0
  164. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/__inherit__skeleton.tsx +5 -0
  165. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/components/ui/__inherit__spinner.tsx +7 -0
  166. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/api/objectDetailService.ts +102 -0
  167. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/api/objectInfoGraphQLService.ts +137 -0
  168. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/api/objectInfoService.ts +95 -0
  169. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/api/recordListGraphQLService.ts +364 -0
  170. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/DetailFields.tsx +55 -0
  171. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/DetailForm.tsx +146 -0
  172. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/DetailHeader.tsx +34 -0
  173. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/DetailLayoutSections.tsx +80 -0
  174. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/Section.tsx +108 -0
  175. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/SectionRow.tsx +20 -0
  176. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/UiApiDetailForm.tsx +140 -0
  177. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FieldValueDisplay.tsx +73 -0
  178. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FormattedAddress.tsx +29 -0
  179. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FormattedEmail.tsx +17 -0
  180. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FormattedPhone.tsx +24 -0
  181. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FormattedText.tsx +11 -0
  182. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/detail/formatted/FormattedUrl.tsx +29 -0
  183. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/filters/FilterField.tsx +54 -0
  184. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/filters/FilterInput.tsx +55 -0
  185. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/filters/FilterSelect.tsx +72 -0
  186. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/filters/FiltersPanel.tsx +380 -0
  187. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/forms/filters-form.tsx +114 -0
  188. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/forms/submit-button.tsx +47 -0
  189. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/GlobalSearchInput.tsx +114 -0
  190. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/ResultCardFields.tsx +71 -0
  191. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/SearchHeader.tsx +31 -0
  192. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/SearchPagination.tsx +144 -0
  193. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/SearchResultCard.tsx +138 -0
  194. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/search/SearchResultsPanel.tsx +197 -0
  195. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/shared/LoadingFallback.tsx +61 -0
  196. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/constants.ts +39 -0
  197. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/filters/FilterInput.tsx +55 -0
  198. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/filters/FilterSelect.tsx +72 -0
  199. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/hooks/form.tsx +209 -0
  200. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/hooks/useObjectInfoBatch.ts +72 -0
  201. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/hooks/useObjectSearchData.ts +174 -0
  202. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/hooks/useRecordDetailLayout.ts +137 -0
  203. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/hooks/useRecordListGraphQL.ts +135 -0
  204. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/pages/DetailPage.tsx +109 -0
  205. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/pages/GlobalSearch.tsx +235 -0
  206. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/filters/filters.ts +121 -0
  207. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/filters/picklist.ts +6 -0
  208. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/objectInfo/objectInfo.ts +49 -0
  209. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/recordDetail/recordDetail.ts +61 -0
  210. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/schema.d.ts +200 -0
  211. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/types/search/searchResults.ts +229 -0
  212. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/apiUtils.ts +59 -0
  213. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/cacheUtils.ts +76 -0
  214. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/debounce.ts +90 -0
  215. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/fieldUtils.ts +354 -0
  216. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/fieldValueExtractor.ts +67 -0
  217. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/filterUtils.ts +32 -0
  218. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/formDataTransformUtils.ts +260 -0
  219. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/formUtils.ts +142 -0
  220. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/graphQLNodeFieldUtils.ts +186 -0
  221. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/graphQLObjectInfoAdapter.ts +77 -0
  222. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/graphQLRecordAdapter.ts +90 -0
  223. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/layoutTransformUtils.ts +236 -0
  224. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/linkUtils.ts +14 -0
  225. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/paginationUtils.ts +49 -0
  226. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/recordUtils.ts +159 -0
  227. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/utils/sanitizationUtils.ts +50 -0
  228. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/index.ts +120 -0
  229. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/lib/__inherit__utils.ts +5 -0
  230. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/pages/Home.tsx +13 -0
  231. package/src/force-app/main/default/uiBundles/feature-react-global-search/src/routes.tsx +52 -0
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@salesforce/ui-bundle-template-feature-react-global-search",
3
+ "version": "1.117.2",
4
+ "description": "Global search feature for Salesforce objects with filtering and pagination",
5
+ "license": "SEE LICENSE IN LICENSE.txt",
6
+ "author": "",
7
+ "main": "src/force-app/main/default/uiBundles/feature-react-global-search/src/index.ts",
8
+ "types": "index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./index.d.ts",
12
+ "import": "./src/force-app/main/default/uiBundles/feature-react-global-search/src/index.ts",
13
+ "default": "./src/force-app/main/default/uiBundles/feature-react-global-search/src/index.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "src"
19
+ ],
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "scripts": {
24
+ "clean": "rm -rf dist"
25
+ },
26
+ "devDependencies": {
27
+ "@types/react": "^19.2.7",
28
+ "@types/react-dom": "^19.2.3",
29
+ "@types/react-router-dom": "^5.3.3",
30
+ "class-variance-authority": "^0.7.1",
31
+ "lucide-react": "^0.468.0",
32
+ "react-dom": "^19.2.1",
33
+ "react-router": "^7.10.1",
34
+ "react-router-dom": "^7.10.1",
35
+ "zod": "^3.24.1"
36
+ },
37
+ "nx": {
38
+ "targets": {
39
+ "build": {
40
+ "executor": "@salesforce/ui-bundle-template-cli:apply-patches"
41
+ },
42
+ "watch": {
43
+ "executor": "@salesforce/ui-bundle-template-cli:watch-patches"
44
+ },
45
+ "build:dist-app": {
46
+ "executor": "@salesforce/ui-bundle-template-cli:build-dist-app"
47
+ },
48
+ "dev": {
49
+ "executor": "@salesforce/ui-bundle-template-cli:dev-server"
50
+ }
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,9 @@
1
+ import { Outlet } from "react-router";
2
+
3
+ export default function AppLayout() {
4
+ return (
5
+ <>
6
+ <Outlet />
7
+ </>
8
+ );
9
+ }
@@ -0,0 +1,27 @@
1
+ import { cva, type VariantProps } from "class-variance-authority";
2
+
3
+ const statusAlertVariants = cva("", {
4
+ variants: {
5
+ variant: {
6
+ error: "",
7
+ success: "",
8
+ },
9
+ },
10
+ defaultVariants: {
11
+ variant: "error",
12
+ },
13
+ });
14
+
15
+ interface StatusAlertProps extends VariantProps<typeof statusAlertVariants> {
16
+ children?: React.ReactNode;
17
+ /** Alert variant type. @default "error" */
18
+ variant?: "error" | "success";
19
+ }
20
+
21
+ /**
22
+ * Status alert component for displaying error or success messages.
23
+ * Returns null if no children are provided.
24
+ */
25
+ export function StatusAlert({}: StatusAlertProps) {
26
+ return <></>;
27
+ }
@@ -0,0 +1,9 @@
1
+ interface CardLayoutProps {
2
+ title: string;
3
+ description?: string;
4
+ children: React.ReactNode;
5
+ }
6
+
7
+ export function CardLayout({}: CardLayoutProps) {
8
+ return <></>;
9
+ }
@@ -0,0 +1,41 @@
1
+ import { cva, type VariantProps } from "class-variance-authority";
2
+
3
+ const alertVariants = cva(
4
+ "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
5
+ {
6
+ variants: {
7
+ variant: {
8
+ default: "bg-card text-card-foreground",
9
+ destructive:
10
+ "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
11
+ },
12
+ },
13
+ defaultVariants: {
14
+ variant: "default",
15
+ },
16
+ },
17
+ );
18
+
19
+ function Alert({
20
+ className,
21
+ variant,
22
+ role,
23
+ ...props
24
+ }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
25
+ return <> </>;
26
+ }
27
+
28
+ // Maintenance/A11y: Added 'asChild' pattern or a simple 'as' prop
29
+ // to allow rendering semantic headings (h1-h6).
30
+ interface AlertTitleProps extends React.ComponentProps<"div"> {
31
+ as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "div" | "p";
32
+ }
33
+ function AlertTitle({ className, as: Component = "div", ...props }: AlertTitleProps) {
34
+ return <></>;
35
+ }
36
+
37
+ function AlertDescription({ className, ...props }: React.ComponentProps<"div">) {
38
+ return <></>;
39
+ }
40
+
41
+ export { Alert, AlertTitle, AlertDescription };
@@ -0,0 +1,45 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ const buttonVariants = cva(
5
+ "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
6
+ {
7
+ variants: {
8
+ variant: {
9
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
10
+ outline:
11
+ "border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground",
12
+ secondary:
13
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
14
+ ghost:
15
+ "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
16
+ destructive:
17
+ "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
18
+ link: "text-primary underline-offset-4 hover:underline",
19
+ },
20
+ size: {
21
+ default:
22
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
23
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
24
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
25
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
26
+ icon: "size-8",
27
+ "icon-xs":
28
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
29
+ "icon-sm":
30
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
31
+ "icon-lg": "size-9",
32
+ },
33
+ },
34
+ defaultVariants: {
35
+ variant: "default",
36
+ size: "default",
37
+ },
38
+ },
39
+ );
40
+
41
+ function Button({}: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants>) {
42
+ return <> </>;
43
+ }
44
+
45
+ export { Button, buttonVariants };
@@ -0,0 +1,33 @@
1
+ function Card({ className, ...props }: React.ComponentProps<"div">) {
2
+ return <> </>;
3
+ }
4
+
5
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
6
+ return <> </>;
7
+ }
8
+
9
+ function CardTitle({
10
+ className,
11
+ as: Component = "h3",
12
+ ...props
13
+ }: React.ComponentProps<"div"> & { as?: any }) {
14
+ return <> </>;
15
+ }
16
+
17
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
18
+ return <></>;
19
+ }
20
+
21
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
22
+ return <></>;
23
+ }
24
+
25
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
26
+ return <></>;
27
+ }
28
+
29
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
30
+ return <></>;
31
+ }
32
+
33
+ export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };
@@ -0,0 +1,62 @@
1
+ import * as React from "react";
2
+
3
+ import { Label } from "./__inherit__label";
4
+
5
+ function Field({
6
+ className,
7
+ orientation = "vertical",
8
+ ...props
9
+ }: React.ComponentProps<"div"> & {
10
+ orientation?: "horizontal" | "vertical";
11
+ }) {
12
+ return <> </>;
13
+ }
14
+
15
+ function FieldLabel({ className, ...props }: React.ComponentProps<typeof Label>) {
16
+ return <> </>;
17
+ }
18
+
19
+ function FieldDescription({ className, ...props }: React.ComponentProps<"p">) {
20
+ return <> </>;
21
+ }
22
+
23
+ function FieldError({
24
+ className,
25
+ errors,
26
+ ...props
27
+ }: React.ComponentProps<"p"> & { errors?: (Error | undefined | null)[] }) {
28
+ const errorMessages = errors?.filter(Boolean).map((e) => e?.message);
29
+
30
+ if (!errorMessages?.length) {
31
+ return null;
32
+ }
33
+
34
+ return <></>;
35
+ }
36
+
37
+ function FieldGroup({ className, ...props }: React.ComponentProps<"div">) {
38
+ return <> </>;
39
+ }
40
+
41
+ function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {
42
+ return <> </>;
43
+ }
44
+
45
+ function FieldLegend({ className, ...props }: React.ComponentProps<"legend">) {
46
+ return <> </>;
47
+ }
48
+
49
+ function FieldSeparator({ className, ...props }: React.ComponentProps<"div">) {
50
+ return <></>;
51
+ }
52
+
53
+ export {
54
+ Field,
55
+ FieldDescription,
56
+ FieldError,
57
+ FieldGroup,
58
+ FieldLabel,
59
+ FieldLegend,
60
+ FieldSeparator,
61
+ FieldSet,
62
+ };
@@ -0,0 +1,5 @@
1
+ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
2
+ return <> </>;
3
+ }
4
+
5
+ export { Input };
@@ -0,0 +1,8 @@
1
+ import * as React from "react";
2
+ import * as LabelPrimitive from "@radix-ui/react-label";
3
+
4
+ function Label({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) {
5
+ return <> </>;
6
+ }
7
+
8
+ export { Label };
@@ -0,0 +1,47 @@
1
+ import * as React from "react";
2
+ import { Button } from "./__inherit__button";
3
+
4
+ const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => <></>;
5
+ Pagination.displayName = "Pagination";
6
+
7
+ const PaginationContent = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>(
8
+ ({ className, ...props }, ref) => <></>,
9
+ );
10
+ PaginationContent.displayName = "PaginationContent";
11
+
12
+ const PaginationItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>(
13
+ ({ className, ...props }, ref) => <></>,
14
+ );
15
+ PaginationItem.displayName = "PaginationItem";
16
+
17
+ type PaginationLinkProps = {
18
+ isActive?: boolean;
19
+ } & React.ComponentProps<"button">;
20
+
21
+ const PaginationLink = ({ className, isActive, disabled, ...props }: PaginationLinkProps) => <></>;
22
+ PaginationLink.displayName = "PaginationLink";
23
+
24
+ const PaginationPrevious = ({
25
+ className,
26
+ disabled,
27
+ ...props
28
+ }: React.ComponentProps<typeof Button>) => <></>;
29
+ PaginationPrevious.displayName = "PaginationPrevious";
30
+
31
+ const PaginationNext = ({ className, disabled, ...props }: React.ComponentProps<typeof Button>) => (
32
+ <></>
33
+ );
34
+ PaginationNext.displayName = "PaginationNext";
35
+
36
+ const PaginationEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => <></>;
37
+ PaginationEllipsis.displayName = "PaginationEllipsis";
38
+
39
+ export {
40
+ Pagination,
41
+ PaginationContent,
42
+ PaginationEllipsis,
43
+ PaginationItem,
44
+ PaginationLink,
45
+ PaginationNext,
46
+ PaginationPrevious,
47
+ };
@@ -0,0 +1,57 @@
1
+ import * as React from "react";
2
+ import { Select as SelectPrimitive } from "radix-ui";
3
+
4
+ function Select({}: React.ComponentProps<typeof SelectPrimitive.Root>) {
5
+ return <></>;
6
+ }
7
+
8
+ function SelectGroup({}: React.ComponentProps<typeof SelectPrimitive.Group>) {
9
+ return <></>;
10
+ }
11
+
12
+ function SelectValue({}: React.ComponentProps<typeof SelectPrimitive.Value>) {
13
+ return <></>;
14
+ }
15
+
16
+ function SelectTrigger({}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
17
+ size?: "sm" | "default";
18
+ }) {
19
+ return <></>;
20
+ }
21
+
22
+ function SelectContent({}: React.ComponentProps<typeof SelectPrimitive.Content>) {
23
+ return <></>;
24
+ }
25
+
26
+ function SelectLabel({}: React.ComponentProps<typeof SelectPrimitive.Label>) {
27
+ return <></>;
28
+ }
29
+
30
+ function SelectItem({}: React.ComponentProps<typeof SelectPrimitive.Item>) {
31
+ return <></>;
32
+ }
33
+
34
+ function SelectSeparator({}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
35
+ return <></>;
36
+ }
37
+
38
+ function SelectScrollUpButton({}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
39
+ return <></>;
40
+ }
41
+
42
+ function SelectScrollDownButton({}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
43
+ return <></>;
44
+ }
45
+
46
+ export {
47
+ Select,
48
+ SelectContent,
49
+ SelectGroup,
50
+ SelectItem,
51
+ SelectLabel,
52
+ SelectScrollDownButton,
53
+ SelectScrollUpButton,
54
+ SelectSeparator,
55
+ SelectTrigger,
56
+ SelectValue,
57
+ };
@@ -0,0 +1,5 @@
1
+ function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
2
+ return <></>;
3
+ }
4
+
5
+ export { Skeleton };
@@ -0,0 +1,7 @@
1
+ import { LoaderIcon } from "lucide-react";
2
+
3
+ function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
4
+ return <> </>;
5
+ }
6
+
7
+ export { Spinner };
@@ -0,0 +1,102 @@
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/ui-bundle/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
+ export async function getLayout(
40
+ objectApiName: string,
41
+ recordTypeId: string = DEFAULT_RECORD_TYPE_ID,
42
+ ): Promise<LayoutResponse> {
43
+ const params = new URLSearchParams({
44
+ layoutType: "Full",
45
+ mode: "View",
46
+ recordTypeId,
47
+ });
48
+ return fetchAndValidate(
49
+ () => uiApiClient.get(`/layout/${safeEncodePath(objectApiName)}?${params.toString()}`),
50
+ {
51
+ schema: LayoutResponseSchema,
52
+ errorContext: `layout for ${objectApiName}`,
53
+ },
54
+ );
55
+ }
56
+
57
+ export interface RecordDetailResult {
58
+ layout: LayoutResponse;
59
+ record: GraphQLRecordNode;
60
+ objectMetadata: ObjectInfoResult;
61
+ }
62
+
63
+ /**
64
+ * Converts layout-derived optionalFields (field API names) to Column[] for GraphQL node selection.
65
+ * Uses unqualified names (no entity prefix) so the GraphQL query matches UI API shape.
66
+ * Other Column fields (label, searchable, sortable) are only required by the type; GraphQL selection uses fieldApiName only.
67
+ */
68
+ function optionalFieldsToColumns(optionalFields: string[]): Column[] {
69
+ return optionalFields.map((fieldApiName) => ({
70
+ fieldApiName,
71
+ label: "",
72
+ searchable: false,
73
+ sortable: false,
74
+ }));
75
+ }
76
+
77
+ export async function getRecordDetail(
78
+ objectApiName: string,
79
+ recordId: string,
80
+ recordTypeId: string = DEFAULT_RECORD_TYPE_ID,
81
+ ): Promise<RecordDetailResult> {
82
+ const layout = await getLayout(objectApiName, recordTypeId);
83
+ const objectMetadata = await objectInfoService.getObjectInfoBatch(objectApiName);
84
+ const firstResult = objectMetadata?.results?.[0]?.result;
85
+ if (!firstResult) {
86
+ throw new Error(`Object metadata not found for ${objectApiName}`);
87
+ }
88
+ // Layout-driven optionalFields (fields shown on the detail layout), not list columns
89
+ const [optionalFields] = calculateFieldsToFetch(firstResult, layout, false);
90
+ const columns = optionalFieldsToColumns(optionalFields);
91
+ const record = await getRecordByIdGraphQL(objectApiName, recordId, columns);
92
+ if (!record) {
93
+ throw new Error(`Record not found: ${recordId}`);
94
+ }
95
+ return { layout, record, objectMetadata: firstResult };
96
+ }
97
+
98
+ export const objectDetailService = {
99
+ extractFieldsFromLayout,
100
+ getLayout,
101
+ getRecordDetail,
102
+ };
@@ -0,0 +1,137 @@
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 { createDataSDK, gql } from "@salesforce/sdk-data";
11
+ import type {
12
+ GetObjectInfosQuery,
13
+ GetObjectInfosQueryVariables,
14
+ GetPicklistValuesQuery,
15
+ GetPicklistValuesQueryVariables,
16
+ ObjectInfoInput,
17
+ } from "../types/schema";
18
+
19
+ /**
20
+ * Builds objectInfos query (metadata only). Uses apiNames only — do not pass objectInfoInputs.
21
+ */
22
+ const OBJECT_INFOS_QUERY = gql`
23
+ query GetObjectInfos($apiNames: [String!]!) {
24
+ uiapi {
25
+ objectInfos(apiNames: $apiNames) {
26
+ ApiName
27
+ label
28
+ labelPlural
29
+ nameFields
30
+ defaultRecordTypeId
31
+ keyPrefix
32
+ layoutable
33
+ queryable
34
+ searchable
35
+ updateable
36
+ deletable
37
+ createable
38
+ custom
39
+ mruEnabled
40
+ feedEnabled
41
+ fields {
42
+ ApiName
43
+ label
44
+ dataType
45
+ relationshipName
46
+ reference
47
+ compound
48
+ compoundFieldName
49
+ compoundComponentName
50
+ controllingFields
51
+ controllerName
52
+ referenceToInfos {
53
+ ApiName
54
+ nameFields
55
+ }
56
+ }
57
+ recordTypeInfos {
58
+ recordTypeId
59
+ name
60
+ master
61
+ available
62
+ defaultRecordTypeMapping
63
+ }
64
+ themeInfo {
65
+ color
66
+ iconUrl
67
+ }
68
+ childRelationships {
69
+ relationshipName
70
+ fieldName
71
+ childObjectApiName
72
+ }
73
+ dependentFields {
74
+ controllingField
75
+ }
76
+ }
77
+ }
78
+ }
79
+ `;
80
+
81
+ /**
82
+ * Builds objectInfos query with picklist values (API v65.0+).
83
+ * Schema requires objectInfos to be called with either apiNames or objectInfoInputs, not both.
84
+ * This query uses objectInfoInputs only.
85
+ * Optimized to only fetch fields used by extractPicklistValuesFromGraphQLObjectInfo.
86
+ */
87
+ const PICKLIST_VALUES_QUERY = gql`
88
+ query GetPicklistValues($objectInfoInputs: [ObjectInfoInput!]!) {
89
+ uiapi {
90
+ objectInfos(objectInfoInputs: $objectInfoInputs) {
91
+ ApiName
92
+ fields {
93
+ ApiName
94
+ ... on PicklistField {
95
+ picklistValuesByRecordTypeIDs {
96
+ recordTypeID
97
+ defaultValue {
98
+ value
99
+ }
100
+ picklistValues {
101
+ label
102
+ value
103
+ validFor
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ `;
112
+
113
+ export async function queryForObjectInfos(apiNames: string[]): Promise<GetObjectInfosQuery> {
114
+ return runQuery<GetObjectInfosQuery, GetObjectInfosQueryVariables>(OBJECT_INFOS_QUERY, {
115
+ apiNames,
116
+ });
117
+ }
118
+
119
+ export async function queryForPicklistValues(
120
+ objectInfoInputs: ObjectInfoInput[],
121
+ ): Promise<GetPicklistValuesQuery> {
122
+ return runQuery<GetPicklistValuesQuery, GetPicklistValuesQueryVariables>(PICKLIST_VALUES_QUERY, {
123
+ objectInfoInputs,
124
+ });
125
+ }
126
+
127
+ async function runQuery<Q, V>(query: string, variables: V): Promise<Q> {
128
+ const data = await createDataSDK();
129
+ const response = await data.graphql?.<Q, V>(query, variables);
130
+
131
+ if (response?.errors?.length) {
132
+ const errorMessages = response.errors.map((e) => e.message).join("; ");
133
+ throw new Error(`GraphQL Error: ${errorMessages}`);
134
+ }
135
+
136
+ return response?.data ?? ({} as Q);
137
+ }