@salesforce/ui-bundle-template-feature-angular-object-search 12.5.4

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 (289) hide show
  1. package/LICENSE.txt +82 -0
  2. package/README.md +101 -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/CHANGELOG.md +5238 -0
  8. package/dist/README.md +77 -0
  9. package/dist/config/project-scratch-def.json +13 -0
  10. package/dist/eslint.config.js +7 -0
  11. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/.forceignore +15 -0
  12. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/.graphqlrc.yml +2 -0
  13. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/.postcssrc.json +5 -0
  14. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/.prettierignore +8 -0
  15. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/.prettierrc +12 -0
  16. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/CHANGELOG.md +4 -0
  17. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/README.md +85 -0
  18. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/angular.json +98 -0
  19. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/codegen.yml +95 -0
  20. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/components.json +6 -0
  21. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/e2e/app.spec.ts +15 -0
  22. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/esbuild/api-version.mjs +17 -0
  23. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/esbuild/graphql-codegen.mjs +13 -0
  24. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/eslint-plugin-angular-graphql.js +148 -0
  25. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/eslint.config.js +76 -0
  26. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/feature-angular-object-search.uibundle-meta.xml +7 -0
  27. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/middleware/html.mjs +3 -0
  28. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/middleware/proxy.mjs +12 -0
  29. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/package.json +69 -0
  30. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/playwright.config.ts +25 -0
  31. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/public/favicon.ico +0 -0
  32. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/scripts/get-graphql-schema.mjs +69 -0
  33. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/scripts/rewrite-e2e-assets.mjs +30 -0
  34. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/api/account/account-search.service.ts +108 -0
  35. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/api/account/distinctAccountIndustries.ts +26 -0
  36. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/api/account/distinctAccountTypes.ts +26 -0
  37. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/api/account/getAccountDetail.ts +128 -0
  38. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/api/account/searchAccounts.ts +58 -0
  39. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/api/data-client.service.spec.ts +184 -0
  40. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/api/data-client.service.ts +74 -0
  41. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/api/graphql-operations-types.ts +29389 -0
  42. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/app.config.ts +20 -0
  43. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/app.html +1 -0
  44. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/app.routes.ts +32 -0
  45. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/app.spec.ts +18 -0
  46. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/app.ts +15 -0
  47. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/layout/app-layout/app-layout.html +51 -0
  48. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/layout/app-layout/app-layout.spec.ts +63 -0
  49. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/layout/app-layout/app-layout.ts +27 -0
  50. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/alert/alert.html +27 -0
  51. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/alert/alert.ts +41 -0
  52. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/button/button.html +27 -0
  53. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/button/button.ts +66 -0
  54. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/card/card.ts +100 -0
  55. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/collapsible/collapsible.html +38 -0
  56. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/collapsible/collapsible.ts +21 -0
  57. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/date-picker/date-picker.html +20 -0
  58. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/date-picker/date-picker.ts +49 -0
  59. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/date-range-picker/date-range-picker.html +20 -0
  60. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/date-range-picker/date-range-picker.ts +69 -0
  61. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/dialog/dialog.html +20 -0
  62. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/dialog/dialog.ts +40 -0
  63. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/dropdown-menu/dropdown-menu.html +20 -0
  64. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/dropdown-menu/dropdown-menu.ts +100 -0
  65. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/field/field.html +15 -0
  66. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/field/field.ts +28 -0
  67. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/field-appearance.ts +8 -0
  68. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/field-size.ts +8 -0
  69. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/icon/icon.ts +68 -0
  70. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/input/input.html +34 -0
  71. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/input/input.ts +79 -0
  72. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/label/label.ts +21 -0
  73. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/paginator/paginator.html +74 -0
  74. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/paginator/paginator.ts +93 -0
  75. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/paginator/types.ts +13 -0
  76. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/popover/popover.html +13 -0
  77. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/popover/popover.ts +37 -0
  78. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/select/select.html +36 -0
  79. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/select/select.ts +63 -0
  80. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/separator/separator.ts +31 -0
  81. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/skeleton/skeleton.ts +20 -0
  82. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/components/ui/spinner/spinner.ts +28 -0
  83. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/api/object-search.service.ts +94 -0
  84. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/breadcrumb/breadcrumb.html +34 -0
  85. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/breadcrumb/breadcrumb.ts +27 -0
  86. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/active-filters.html +23 -0
  87. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/active-filters.ts +78 -0
  88. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/date-filter.html +18 -0
  89. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/date-filter.ts +137 -0
  90. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/date-range-filter.html +12 -0
  91. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/date-range-filter.ts +60 -0
  92. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/filter-field-wrapper.html +13 -0
  93. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/filter-field-wrapper.ts +21 -0
  94. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/multi-select-filter.html +11 -0
  95. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/multi-select-filter.ts +58 -0
  96. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/numeric-range-filter.html +22 -0
  97. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/numeric-range-filter.ts +128 -0
  98. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/search-filter.html +8 -0
  99. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/search-filter.ts +78 -0
  100. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/select-filter.html +9 -0
  101. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/select-filter.ts +51 -0
  102. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/text-filter.html +9 -0
  103. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/filters/text-filter.ts +76 -0
  104. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/object-search-state.service.ts +232 -0
  105. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/pagination/pagination.html +8 -0
  106. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/pagination/pagination.ts +45 -0
  107. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/search-bar/search-bar.html +10 -0
  108. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/search-bar/search-bar.ts +28 -0
  109. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/sort-control/sort-control.html +24 -0
  110. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/sort-control/sort-control.ts +65 -0
  111. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/utils/debounce.ts +31 -0
  112. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/utils/field-utils.ts +54 -0
  113. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/utils/filter-utils.ts +354 -0
  114. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/utils/index.ts +12 -0
  115. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/features/object-search/utils/sort-utils.ts +39 -0
  116. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/pages/account-detail/account-detail-page.html +142 -0
  117. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/pages/account-detail/account-detail-page.ts +176 -0
  118. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/pages/account-search/account-search-page.html +93 -0
  119. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/pages/account-search/account-search-page.ts +196 -0
  120. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/pages/home/home.html +17 -0
  121. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/pages/home/home.spec.ts +25 -0
  122. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/pages/home/home.ts +65 -0
  123. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/pages/not-found/not-found.html +12 -0
  124. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/pages/not-found/not-found.spec.ts +33 -0
  125. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/pages/not-found/not-found.ts +15 -0
  126. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/alert/hlm-alert-action.ts +14 -0
  127. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/alert/hlm-alert-description.ts +17 -0
  128. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/alert/hlm-alert-title.ts +17 -0
  129. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/alert/hlm-alert.ts +35 -0
  130. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/alert/index.ts +16 -0
  131. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/button/hlm-button.token.ts +22 -0
  132. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/button/hlm-button.ts +72 -0
  133. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/button/index.ts +6 -0
  134. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/calendar/hlm-calendar-multi.ts +195 -0
  135. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/calendar/hlm-calendar-range.ts +194 -0
  136. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/calendar/hlm-calendar.ts +189 -0
  137. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/calendar/hlm-month-year-calendar.ts +119 -0
  138. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/calendar/index.ts +16 -0
  139. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/card/hlm-card-action.ts +12 -0
  140. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/card/hlm-card-avatar.ts +14 -0
  141. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/card/hlm-card-content.ts +12 -0
  142. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/card/hlm-card-description.ts +12 -0
  143. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/card/hlm-card-footer.ts +12 -0
  144. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/card/hlm-card-header.ts +15 -0
  145. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/card/hlm-card-title.ts +12 -0
  146. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/card/hlm-card.token.ts +19 -0
  147. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/card/hlm-card.ts +22 -0
  148. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/card/index.ts +28 -0
  149. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/collapsible/hlm-collapsible-content.ts +14 -0
  150. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/collapsible/hlm-collapsible-trigger.ts +9 -0
  151. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/collapsible/hlm-collapsible.ts +15 -0
  152. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/collapsible/index.ts +13 -0
  153. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-multi-input.ts +104 -0
  154. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-picker-anchor.ts +23 -0
  155. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-picker-input.ts +118 -0
  156. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-picker-multi.token.ts +109 -0
  157. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-picker-multi.ts +220 -0
  158. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-picker-trigger.ts +104 -0
  159. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-picker.token.ts +69 -0
  160. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-picker.ts +203 -0
  161. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-range-input.ts +120 -0
  162. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-range-picker.token.ts +86 -0
  163. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-date-range-picker.ts +252 -0
  164. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-month-year-input.ts +105 -0
  165. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-month-year-picker.token.ts +89 -0
  166. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/hlm-month-year-picker.ts +196 -0
  167. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/date-picker/index.ts +38 -0
  168. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog-close.ts +9 -0
  169. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog-content.ts +74 -0
  170. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog-description.ts +17 -0
  171. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog-footer.ts +15 -0
  172. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog-header.ts +12 -0
  173. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog-overlay.ts +27 -0
  174. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog-portal.ts +8 -0
  175. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog-title.ts +14 -0
  176. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog-trigger.ts +14 -0
  177. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog.service.ts +46 -0
  178. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/hlm-dialog.ts +24 -0
  179. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dialog/index.ts +35 -0
  180. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-checkbox-indicator.ts +21 -0
  181. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-checkbox.ts +54 -0
  182. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-focus-on-hover.ts +35 -0
  183. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-group.ts +14 -0
  184. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-item-sub-indicator.ts +19 -0
  185. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-item.ts +42 -0
  186. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-label.ts +20 -0
  187. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-radio-indicator.ts +21 -0
  188. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-radio.ts +49 -0
  189. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-separator.ts +12 -0
  190. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-shortcut.ts +15 -0
  191. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-sub-trigger.ts +52 -0
  192. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-sub.ts +53 -0
  193. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-token.ts +26 -0
  194. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu-trigger.ts +46 -0
  195. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/hlm-dropdown-menu.ts +57 -0
  196. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/dropdown-menu/index.ts +49 -0
  197. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/hlm-field-content.ts +12 -0
  198. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/hlm-field-description.ts +53 -0
  199. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/hlm-field-error.ts +100 -0
  200. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/hlm-field-group.ts +15 -0
  201. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/hlm-field-label.ts +17 -0
  202. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/hlm-field-legend.ts +19 -0
  203. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/hlm-field-separator.ts +24 -0
  204. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/hlm-field-set.ts +15 -0
  205. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/hlm-field-title.ts +15 -0
  206. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/hlm-field.ts +47 -0
  207. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/field/index.ts +34 -0
  208. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/input/hlm-input.ts +21 -0
  209. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/input/index.ts +5 -0
  210. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/input-group/hlm-input-group-addon.ts +40 -0
  211. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/input-group/hlm-input-group-button.ts +47 -0
  212. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/input-group/hlm-input-group-input.ts +17 -0
  213. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/input-group/hlm-input-group-text.ts +14 -0
  214. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/input-group/hlm-input-group.ts +18 -0
  215. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/input-group/index.ts +19 -0
  216. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/label/hlm-label.ts +17 -0
  217. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/label/index.ts +5 -0
  218. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/label/label.html +11 -0
  219. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/pagination/hlm-numbered-pagination-query-params.ts +191 -0
  220. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/pagination/hlm-numbered-pagination.ts +290 -0
  221. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/pagination/hlm-pagination-content.ts +12 -0
  222. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/pagination/hlm-pagination-ellipsis.ts +27 -0
  223. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/pagination/hlm-pagination-item.ts +7 -0
  224. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/pagination/hlm-pagination-link.ts +51 -0
  225. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/pagination/hlm-pagination-next.ts +65 -0
  226. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/pagination/hlm-pagination-previous.ts +65 -0
  227. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/pagination/hlm-pagination.ts +19 -0
  228. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/pagination/index.ts +31 -0
  229. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/popover/hlm-popover-content.ts +25 -0
  230. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/popover/hlm-popover-description.ts +12 -0
  231. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/popover/hlm-popover-header.ts +12 -0
  232. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/popover/hlm-popover-portal.ts +8 -0
  233. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/popover/hlm-popover-title.ts +12 -0
  234. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/popover/hlm-popover-trigger.ts +14 -0
  235. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/popover/hlm-popover.ts +23 -0
  236. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/popover/index.ts +25 -0
  237. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-content.ts +44 -0
  238. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-group.ts +14 -0
  239. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-item.ts +36 -0
  240. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-label.ts +14 -0
  241. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-multiple.ts +37 -0
  242. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-placeholder.ts +17 -0
  243. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-portal.ts +8 -0
  244. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-scroll-down.ts +22 -0
  245. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-scroll-up.ts +22 -0
  246. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-separator.ts +14 -0
  247. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-trigger.ts +59 -0
  248. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-value-template.ts +5 -0
  249. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-value.ts +18 -0
  250. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-values-content.ts +9 -0
  251. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select-values.ts +5 -0
  252. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/hlm-select.ts +37 -0
  253. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/select/index.ts +52 -0
  254. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/separator/hlm-separator.ts +19 -0
  255. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/separator/index.ts +5 -0
  256. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/skeleton/hlm-skeleton.ts +14 -0
  257. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/skeleton/index.ts +5 -0
  258. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/spinner/hlm-spinner.ts +26 -0
  259. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/spinner/index.ts +5 -0
  260. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/utils/hlm.ts +313 -0
  261. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/utils/index.ts +2 -0
  262. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/shared/utils/provide-spartan-hlm.ts +34 -0
  263. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/app/utils/async-data.ts +99 -0
  264. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/index.html +13 -0
  265. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/main.ts +5 -0
  266. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/styles.css +139 -0
  267. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/src/types/sf-globals.d.ts +9 -0
  268. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/tsconfig.app.json +11 -0
  269. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/tsconfig.json +36 -0
  270. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/tsconfig.spec.json +10 -0
  271. package/dist/force-app/main/default/uiBundles/feature-angular-object-search/ui-bundle.json +7 -0
  272. package/dist/jest.config.js +6 -0
  273. package/dist/package-lock.json +12554 -0
  274. package/dist/package.json +46 -0
  275. package/dist/scripts/apex/hello.apex +10 -0
  276. package/dist/scripts/gitignore-templates.json +4 -0
  277. package/dist/scripts/graphql-search.sh +191 -0
  278. package/dist/scripts/org-setup-config-schema.mjs +132 -0
  279. package/dist/scripts/org-setup-dev.mjs +114 -0
  280. package/dist/scripts/org-setup-url.mjs +108 -0
  281. package/dist/scripts/org-setup-utils.mjs +569 -0
  282. package/dist/scripts/org-setup-xml.mjs +278 -0
  283. package/dist/scripts/org-setup.config.json +5 -0
  284. package/dist/scripts/org-setup.mjs +2537 -0
  285. package/dist/scripts/sf-project-setup.mjs +103 -0
  286. package/dist/scripts/soql/account.soql +6 -0
  287. package/dist/scripts/validate-org-setup-config.mjs +38 -0
  288. package/dist/sfdx-project.json +12 -0
  289. package/package.json +51 -0
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { ChangeDetectionStrategy, Component, computed, inject, signal } from "@angular/core";
7
+ import { ActivatedRoute, Router } from "@angular/router";
8
+ import { toSignal } from "@angular/core/rxjs-interop";
9
+ import { map } from "rxjs/operators";
10
+ import { AlertComponent } from "../../components/ui/alert/alert";
11
+ import { IconComponent } from "../../components/ui/icon/icon";
12
+ import { ButtonComponent } from "../../components/ui/button/button";
13
+ import { CardComponent, CardContentComponent } from "../../components/ui/card/card";
14
+ import { CollapsibleComponent } from "../../components/ui/collapsible/collapsible";
15
+ import { SeparatorComponent } from "../../components/ui/separator/separator";
16
+ import { SkeletonComponent } from "../../components/ui/skeleton/skeleton";
17
+ import { ObjectBreadcrumbComponent } from "../../features/object-search/breadcrumb/breadcrumb";
18
+ import { createAsyncData } from "../../utils/async-data";
19
+ import {
20
+ fieldValue,
21
+ getAddressFieldLines,
22
+ formatDateTimeField,
23
+ } from "../../features/object-search/utils/field-utils";
24
+ import { AccountSearchService } from "../../api/account/account-search.service";
25
+
26
+ const DATE_TIME_OPTIONS: Intl.DateTimeFormatOptions = {
27
+ dateStyle: "medium",
28
+ timeStyle: "short",
29
+ };
30
+
31
+ interface Field {
32
+ label: string;
33
+ value: string | null;
34
+ /** `true` renders the value as a `tel:` link (Phone / Fax). */
35
+ telephone?: boolean;
36
+ }
37
+
38
+ @Component({
39
+ selector: "app-account-detail-page",
40
+ changeDetection: ChangeDetectionStrategy.OnPush,
41
+ imports: [
42
+ AlertComponent,
43
+ IconComponent,
44
+ ButtonComponent,
45
+ CardComponent,
46
+ CardContentComponent,
47
+ CollapsibleComponent,
48
+ SeparatorComponent,
49
+ SkeletonComponent,
50
+ ObjectBreadcrumbComponent,
51
+ ],
52
+ templateUrl: "./account-detail-page.html",
53
+ })
54
+ export class AccountDetailPageComponent {
55
+ private readonly service = inject(AccountSearchService);
56
+ private readonly route = inject(ActivatedRoute);
57
+ private readonly router = inject(Router);
58
+
59
+ // Reactive param so a client-side nav between two detail routes refetches.
60
+ private readonly recordId = toSignal(
61
+ this.route.paramMap.pipe(map((p) => p.get("recordId") ?? "")),
62
+ { initialValue: this.route.snapshot.paramMap.get("recordId") ?? "" },
63
+ );
64
+
65
+ private readonly result = createAsyncData(this.recordId, (id) =>
66
+ this.service.getAccountDetail(id),
67
+ );
68
+
69
+ protected readonly account = this.result.data;
70
+ protected readonly loading = this.result.loading;
71
+ protected readonly error = this.result.error;
72
+ protected readonly notFound = computed(() => !this.loading() && !this.error() && !this.account());
73
+
74
+ protected readonly additionalOpen = signal<boolean>(true);
75
+ protected readonly addressOpen = signal<boolean>(true);
76
+ protected readonly systemOpen = signal<boolean>(true);
77
+
78
+ protected readonly skeletonRows = [0, 1, 2];
79
+
80
+ // -- Breadcrumb leaf label -------------------------------------------------
81
+ protected readonly recordName = computed<string | undefined>(() => {
82
+ const a = this.account();
83
+ if (a) return fieldValue(a.Name) ?? "";
84
+ if (this.error()) return "Error";
85
+ if (this.loading()) return undefined;
86
+ return "Not Found";
87
+ });
88
+
89
+ // -- Header ----------------------------------------------------------------
90
+ protected readonly title = computed(() => fieldValue(this.account()?.Name ?? null) ?? "");
91
+
92
+ // -- Top field rows --------------------------------------------------------
93
+ protected readonly topRows = computed<Field[][]>(() => {
94
+ const a = this.account();
95
+ if (!a) return [];
96
+ return [
97
+ [
98
+ { label: "Account Owner", value: fieldValue(a.Owner?.Name) },
99
+ { label: "Phone", value: fieldValue(a.Phone), telephone: true },
100
+ ],
101
+ [
102
+ { label: "Account Name", value: fieldValue(a.Name) },
103
+ { label: "Fax", value: fieldValue(a.Fax), telephone: true },
104
+ ],
105
+ [
106
+ { label: "Parent Account", value: fieldValue(a.Parent?.Name) },
107
+ { label: "Website", value: fieldValue(a.Website) },
108
+ ],
109
+ ];
110
+ });
111
+
112
+ // -- Additional Information ------------------------------------------------
113
+ protected readonly additionalRows = computed<Field[][]>(() => {
114
+ const a = this.account();
115
+ if (!a) return [];
116
+ return [
117
+ [
118
+ { label: "Type", value: fieldValue(a.Type) },
119
+ { label: "Employees", value: fieldValue(a.NumberOfEmployees) },
120
+ ],
121
+ [
122
+ { label: "Industry", value: fieldValue(a.Industry) },
123
+ { label: "Annual Revenue", value: fieldValue(a.AnnualRevenue) },
124
+ ],
125
+ ];
126
+ });
127
+ protected readonly description = computed(() => fieldValue(this.account()?.Description ?? null));
128
+
129
+ // -- Address Information ---------------------------------------------------
130
+ protected readonly billingAddress = computed<string[] | null>(() => {
131
+ const a = this.account();
132
+ if (!a) return null;
133
+ return getAddressFieldLines({
134
+ street: fieldValue(a.BillingStreet),
135
+ city: fieldValue(a.BillingCity),
136
+ state: fieldValue(a.BillingState),
137
+ postalCode: fieldValue(a.BillingPostalCode),
138
+ country: fieldValue(a.BillingCountry),
139
+ });
140
+ });
141
+ protected readonly shippingAddress = computed<string[] | null>(() => {
142
+ const a = this.account();
143
+ if (!a) return null;
144
+ return getAddressFieldLines({
145
+ street: fieldValue(a.ShippingStreet),
146
+ city: fieldValue(a.ShippingCity),
147
+ state: fieldValue(a.ShippingState),
148
+ postalCode: fieldValue(a.ShippingPostalCode),
149
+ country: fieldValue(a.ShippingCountry),
150
+ });
151
+ });
152
+
153
+ // -- System Information ----------------------------------------------------
154
+ protected readonly createdBy = computed(() =>
155
+ this.joinNameAndDate(this.account()?.CreatedBy?.Name, this.account()?.CreatedDate),
156
+ );
157
+ protected readonly lastModifiedBy = computed(() =>
158
+ this.joinNameAndDate(this.account()?.LastModifiedBy?.Name, this.account()?.LastModifiedDate),
159
+ );
160
+
161
+ private joinNameAndDate(
162
+ name: { value?: unknown; displayValue?: string | null } | null | undefined,
163
+ date: { value?: unknown; displayValue?: string | null } | null | undefined,
164
+ ): string | null {
165
+ const formatted = formatDateTimeField(fieldValue(date ?? null), undefined, DATE_TIME_OPTIONS);
166
+ return [fieldValue(name ?? null), formatted].filter(Boolean).join(" ") || null;
167
+ }
168
+
169
+ protected goBack(): void {
170
+ void this.router.navigate(["/accounts"]);
171
+ }
172
+
173
+ protected reload(): void {
174
+ window.location.reload();
175
+ }
176
+ }
@@ -0,0 +1,93 @@
1
+ <div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
2
+ <app-object-breadcrumb listPath="/accounts" listLabel="Accounts" />
3
+
4
+ <h1 class="text-2xl font-bold mb-4">Search Accounts</h1>
5
+
6
+ <div class="flex flex-col lg:flex-row gap-6">
7
+ <aside class="w-full lg:w-80 shrink-0">
8
+ <app-collapsible title="Filters" [(open)]="filtersOpen">
9
+ <div class="space-y-1">
10
+ <app-search-filter [config]="searchConfig" />
11
+ <app-text-filter [config]="nameConfig" />
12
+ <app-select-filter [config]="industryConfig()" />
13
+ <app-multi-select-filter [config]="typeConfig()" />
14
+ <app-numeric-range-filter [config]="revenueConfig" />
15
+ <app-date-filter [config]="createdConfig" filterType="datetime" />
16
+ <app-date-range-filter [config]="lastModifiedConfig" filterType="datetimerange" />
17
+ </div>
18
+ </app-collapsible>
19
+ </aside>
20
+
21
+ <div class="flex-1 min-w-0">
22
+ <div class="flex flex-wrap items-center gap-2 mb-4">
23
+ <app-sort-control [sortFields]="sortConfigs" />
24
+ <app-active-filters />
25
+ </div>
26
+
27
+ <div class="min-h-132" [attr.aria-busy]="loading()">
28
+ @if (loading()) {
29
+ <app-skeleton class="h-5 w-30 mb-3" />
30
+ <div class="divide-y">
31
+ @for (row of skeletonRows(); track row) {
32
+ <div class="flex items-center justify-between py-3">
33
+ <div class="space-y-2">
34
+ <app-skeleton class="h-5 w-40" />
35
+ <app-skeleton class="h-4 w-28" />
36
+ </div>
37
+ <div class="space-y-2 flex flex-col items-end">
38
+ <app-skeleton class="h-4 w-24" />
39
+ <app-skeleton class="h-4 w-20" />
40
+ </div>
41
+ </div>
42
+ }
43
+ </div>
44
+ } @else if (error()) {
45
+ <p class="text-sm text-muted-foreground mb-3">0 accounts found</p>
46
+ <app-alert
47
+ variant="destructive"
48
+ icon="error"
49
+ title="Failed to load accounts"
50
+ description="Something went wrong while loading accounts. Please try again later."
51
+ />
52
+ } @else if (nodes().length > 0) {
53
+ <p class="text-sm text-muted-foreground mb-3">{{ resultCountLabel() }}</p>
54
+ <ul class="divide-y">
55
+ @for (node of nodes(); track node.Id) {
56
+ <li>
57
+ <a
58
+ [routerLink]="['/accounts', node.Id]"
59
+ class="flex items-center justify-between py-3 px-3 -mx-3 rounded-md transition-colors hover:bg-accent"
60
+ >
61
+ <div>
62
+ <span class="font-medium">{{ name(node) }}</span>
63
+ <p class="text-sm text-muted-foreground">{{ secondaryLine(node) }}</p>
64
+ </div>
65
+ <div class="text-right text-sm">
66
+ <p>{{ phone(node) }}</p>
67
+ <p class="text-muted-foreground">{{ ownerName(node) }}</p>
68
+ </div>
69
+ </a>
70
+ </li>
71
+ }
72
+ </ul>
73
+ } @else {
74
+ <div class="flex flex-col items-center justify-center py-16 text-center">
75
+ <app-icon name="noResults" size="3rem" class="text-muted-foreground mb-4" />
76
+ <h2 class="text-lg font-semibold mb-1">No accounts found</h2>
77
+ <p class="text-sm text-muted-foreground">
78
+ Try adjusting your filters or search criteria.
79
+ </p>
80
+ </div>
81
+ }
82
+ </div>
83
+
84
+ <app-pagination-controls
85
+ [totalCount]="totalCount()"
86
+ [hasNextPage]="hasNextPage()"
87
+ [endCursor]="endCursor()"
88
+ [pageSizeOptions]="pageSizeOptions"
89
+ [disabled]="controlsDisabled()"
90
+ />
91
+ </div>
92
+ </div>
93
+ </div>
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { ChangeDetectionStrategy, Component, computed, inject, signal } from "@angular/core";
7
+ import { RouterLink } from "@angular/router";
8
+ import { AlertComponent } from "../../components/ui/alert/alert";
9
+ import { IconComponent } from "../../components/ui/icon/icon";
10
+ import { CollapsibleComponent } from "../../components/ui/collapsible/collapsible";
11
+ import { SkeletonComponent } from "../../components/ui/skeleton/skeleton";
12
+ import { ObjectBreadcrumbComponent } from "../../features/object-search/breadcrumb/breadcrumb";
13
+ import { SortControlComponent } from "../../features/object-search/sort-control/sort-control";
14
+ import { ActiveFiltersComponent } from "../../features/object-search/filters/active-filters";
15
+ import { PaginationControlsComponent } from "../../features/object-search/pagination/pagination";
16
+ import { SearchFilterComponent } from "../../features/object-search/filters/search-filter";
17
+ import { TextFilterComponent } from "../../features/object-search/filters/text-filter";
18
+ import { SelectFilterComponent } from "../../features/object-search/filters/select-filter";
19
+ import { MultiSelectFilterComponent } from "../../features/object-search/filters/multi-select-filter";
20
+ import { NumericRangeFilterComponent } from "../../features/object-search/filters/numeric-range-filter";
21
+ import { DateFilterComponent } from "../../features/object-search/filters/date-filter";
22
+ import { DateRangeFilterComponent } from "../../features/object-search/filters/date-range-filter";
23
+ import {
24
+ ObjectSearchStateService,
25
+ type PaginationConfig,
26
+ } from "../../features/object-search/object-search-state.service";
27
+ import { createAsyncData } from "../../utils/async-data";
28
+ import { fieldValue } from "../../features/object-search/utils/field-utils";
29
+ import type { FilterFieldConfig } from "../../features/object-search/utils/filter-utils";
30
+ import type { SortFieldConfig } from "../../features/object-search/utils/sort-utils";
31
+ import {
32
+ AccountSearchService,
33
+ type AccountSearchNode,
34
+ type AccountSearchOptions,
35
+ } from "../../api/account/account-search.service";
36
+
37
+ const PAGINATION_CONFIG: PaginationConfig = {
38
+ defaultPageSize: 7,
39
+ validPageSizes: [7, 14, 28, 42],
40
+ };
41
+
42
+ // Single source of truth for URL (de)serialization and GraphQL `where`
43
+ // building. Picklist options for Industry / Type are filled in at runtime
44
+ // (see the component's computed configs) from the distinct-value queries.
45
+ const FILTER_CONFIGS: FilterFieldConfig[] = [
46
+ {
47
+ field: "search",
48
+ label: "Search",
49
+ type: "search",
50
+ searchFields: ["Name", "Phone", "Industry"],
51
+ placeholder: "Search by name, phone, or industry...",
52
+ },
53
+ { field: "Name", label: "Account Name", type: "text", placeholder: "Search by name..." },
54
+ { field: "Industry", label: "Industry", type: "picklist" },
55
+ { field: "Type", label: "Type", type: "multipicklist" },
56
+ { field: "AnnualRevenue", label: "Annual Revenue", type: "numeric" },
57
+ { field: "CreatedDate", label: "Created Date", type: "datetime", disableFuture: true },
58
+ {
59
+ field: "LastModifiedDate",
60
+ label: "Last Modified Date",
61
+ type: "datetimerange",
62
+ disableFuture: true,
63
+ },
64
+ ];
65
+
66
+ const ACCOUNT_SORT_CONFIGS: SortFieldConfig[] = [
67
+ { field: "Name", label: "Name" },
68
+ { field: "AnnualRevenue", label: "Annual Revenue" },
69
+ { field: "Industry", label: "Industry" },
70
+ { field: "CreatedDate", label: "Created Date" },
71
+ ];
72
+
73
+ // State lives in a page-scoped ObjectSearchStateService (provided here, NOT
74
+ // in root) so each search page owns its own filters / sort / cursor stack;
75
+ // the filter components projected into the sidebar inject that same instance.
76
+ @Component({
77
+ selector: "app-account-search-page",
78
+ changeDetection: ChangeDetectionStrategy.OnPush,
79
+ providers: [ObjectSearchStateService],
80
+ imports: [
81
+ RouterLink,
82
+ AlertComponent,
83
+ IconComponent,
84
+ CollapsibleComponent,
85
+ SkeletonComponent,
86
+ ObjectBreadcrumbComponent,
87
+ SortControlComponent,
88
+ ActiveFiltersComponent,
89
+ PaginationControlsComponent,
90
+ SearchFilterComponent,
91
+ TextFilterComponent,
92
+ SelectFilterComponent,
93
+ MultiSelectFilterComponent,
94
+ NumericRangeFilterComponent,
95
+ DateFilterComponent,
96
+ DateRangeFilterComponent,
97
+ ],
98
+ templateUrl: "./account-search-page.html",
99
+ })
100
+ export class AccountSearchPageComponent {
101
+ private readonly service = inject(AccountSearchService);
102
+ private readonly state = inject(ObjectSearchStateService);
103
+
104
+ protected readonly sortConfigs = ACCOUNT_SORT_CONFIGS;
105
+ protected readonly pageSizeOptions = PAGINATION_CONFIG.validPageSizes;
106
+
107
+ protected readonly filtersOpen = signal<boolean>(true);
108
+
109
+ private readonly query = this.state.init<
110
+ AccountSearchOptions["where"],
111
+ AccountSearchOptions["orderBy"]
112
+ >(FILTER_CONFIGS, PAGINATION_CONFIG);
113
+
114
+ protected readonly pageSize = this.state.pageSize;
115
+ protected readonly hasPreviousPage = this.state.hasPreviousPage;
116
+
117
+ // -- Distinct-value option loads (Industry / Type filters) -----------------
118
+ private readonly industries = createAsyncData(signal(0), () =>
119
+ this.service.fetchDistinctIndustries(),
120
+ );
121
+ private readonly types = createAsyncData(signal(0), () => this.service.fetchDistinctTypes());
122
+
123
+ // -- Per-filter configs (options merged in for the picklist filters) -------
124
+ protected readonly searchConfig = FILTER_CONFIGS[0];
125
+ protected readonly nameConfig = FILTER_CONFIGS[1];
126
+ protected readonly revenueConfig = FILTER_CONFIGS[4];
127
+ protected readonly createdConfig = FILTER_CONFIGS[5];
128
+ protected readonly lastModifiedConfig = FILTER_CONFIGS[6];
129
+ protected readonly industryConfig = computed<FilterFieldConfig>(() => ({
130
+ ...FILTER_CONFIGS[2],
131
+ options: this.industries.data() ?? [],
132
+ }));
133
+ protected readonly typeConfig = computed<FilterFieldConfig>(() => ({
134
+ ...FILTER_CONFIGS[3],
135
+ options: this.types.data() ?? [],
136
+ }));
137
+
138
+ // -- Search results --------------------------------------------------------
139
+ private readonly searchArgs = computed(() => ({
140
+ where: this.query.where(),
141
+ orderBy: this.query.orderBy(),
142
+ first: this.state.pageSize(),
143
+ after: this.state.afterCursor(),
144
+ }));
145
+ private readonly result = createAsyncData(this.searchArgs, (args) =>
146
+ this.service.searchAccounts(args),
147
+ );
148
+
149
+ protected readonly loading = this.result.loading;
150
+ protected readonly error = this.result.error;
151
+
152
+ private readonly pageInfo = computed(() => this.result.data()?.pageInfo);
153
+ protected readonly totalCount = computed(() => this.result.data()?.totalCount);
154
+ protected readonly hasNextPage = computed(() => this.pageInfo()?.hasNextPage ?? false);
155
+ protected readonly endCursor = computed(() => this.pageInfo()?.endCursor ?? undefined);
156
+
157
+ protected readonly nodes = computed<AccountSearchNode[]>(() => {
158
+ const edges = this.result.data()?.edges ?? [];
159
+ const out: AccountSearchNode[] = [];
160
+ for (const edge of edges) {
161
+ if (edge?.node) out.push(edge.node);
162
+ }
163
+ return out;
164
+ });
165
+
166
+ protected readonly controlsDisabled = computed(() => this.loading() || !!this.error());
167
+
168
+ protected readonly skeletonRows = computed(() =>
169
+ Array.from({ length: this.pageSize() }, (_, i) => i),
170
+ );
171
+
172
+ protected readonly resultCountLabel = computed(() => {
173
+ const total = this.totalCount();
174
+ const shown = this.nodes().length;
175
+ if (total != null && (this.hasNextPage() || this.hasPreviousPage())) {
176
+ return `${total} account${total !== 1 ? "s" : ""} found`;
177
+ }
178
+ return `Showing ${shown} account${shown !== 1 ? "s" : ""}`;
179
+ });
180
+
181
+ protected name(node: AccountSearchNode): string {
182
+ return fieldValue(node.Name) ?? "—";
183
+ }
184
+
185
+ protected secondaryLine(node: AccountSearchNode): string {
186
+ return [fieldValue(node.Industry), fieldValue(node.Type)].filter(Boolean).join(" · ") || "—";
187
+ }
188
+
189
+ protected phone(node: AccountSearchNode): string {
190
+ return fieldValue(node.Phone) ?? "";
191
+ }
192
+
193
+ protected ownerName(node: AccountSearchNode): string {
194
+ return fieldValue(node.Owner?.Name) ?? "";
195
+ }
196
+ }
@@ -0,0 +1,17 @@
1
+ <main class="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
2
+ <div class="flex items-center gap-6 mb-6">
3
+ <h1 class="text-2xl font-bold">Account Search</h1>
4
+ <app-button appearance="outlined" size="sm" (clicked)="browseAll()"
5
+ >Browse All Accounts</app-button
6
+ >
7
+ </div>
8
+ <form class="flex gap-2 items-end" (submit)="onSubmit($event)">
9
+ <app-search-bar
10
+ class="flex-1"
11
+ placeholder="Search by name, phone, or industry..."
12
+ ariaLabel="Search accounts"
13
+ [(value)]="term"
14
+ />
15
+ <app-button type="submit" [disabled]="!canSearch()">Search</app-button>
16
+ </form>
17
+ </main>
@@ -0,0 +1,25 @@
1
+ import { TestBed } from "@angular/core/testing";
2
+ import { provideRouter } from "@angular/router";
3
+ import { HomeComponent } from "./home";
4
+
5
+ describe("HomeComponent", () => {
6
+ beforeEach(async () => {
7
+ await TestBed.configureTestingModule({
8
+ imports: [HomeComponent],
9
+ providers: [provideRouter([])],
10
+ }).compileComponents();
11
+ });
12
+
13
+ it("should create the component", () => {
14
+ const fixture = TestBed.createComponent(HomeComponent);
15
+ const component = fixture.componentInstance;
16
+ expect(component).toBeTruthy();
17
+ });
18
+
19
+ it("should render main landmark", async () => {
20
+ const fixture = TestBed.createComponent(HomeComponent);
21
+ await fixture.whenStable();
22
+ const compiled = fixture.nativeElement as HTMLElement;
23
+ expect(compiled.querySelector("main")).toBeTruthy();
24
+ });
25
+ });
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { ChangeDetectionStrategy, Component, computed, inject, signal } from "@angular/core";
7
+ import { Router } from "@angular/router";
8
+ // Base-app UI wrappers, inherited (not recreated) by this feature. Post-compose
9
+ // they land at uiBundles/<target>/src/app/components/ui/{button,input}/..., three levels
10
+ // up from this page folder (app/pages/home/ -> app/components/ui/).
11
+ import { ButtonComponent } from "../../components/ui/button/button";
12
+ import { SearchBarComponent } from "../../features/object-search/search-bar/search-bar";
13
+
14
+ /**
15
+ * Account-search landing page. Mirrors the React `Home` page: a single search
16
+ * box plus a "Browse All Accounts" shortcut. Submitting navigates to the
17
+ * `accounts` list, carrying the typed term as the `q` query param so the search
18
+ * page's {@link ObjectSearchStateService} seeds the multi-field search filter.
19
+ *
20
+ * Named `HomeComponent` (selector `app-home`) so it overwrites the base app's
21
+ * placeholder home at compose, leaving the composed app with a single `home`
22
+ * component.
23
+ *
24
+ * Uses the presentational `app-search-bar` (icon + input) with its own local
25
+ * `term` signal and submit-to-navigate flow — Home has no shared search state;
26
+ * it just seeds `?q=` and routes into the search page.
27
+ */
28
+ @Component({
29
+ selector: "app-home",
30
+ changeDetection: ChangeDetectionStrategy.OnPush,
31
+ imports: [ButtonComponent, SearchBarComponent],
32
+ templateUrl: "./home.html",
33
+ })
34
+ export class HomeComponent {
35
+ private readonly router = inject(Router);
36
+
37
+ /** Minimum characters required before a search can be submitted. */
38
+ private static readonly MIN_SEARCH_LENGTH = 3;
39
+
40
+ /** Bound to the search input; forwarded as `?q=` on submit. */
41
+ protected readonly term = signal<string>("");
42
+
43
+ /** True once the trimmed term meets the minimum length — gates the Search button. */
44
+ protected readonly canSearch = computed(
45
+ () => this.term().trim().length >= HomeComponent.MIN_SEARCH_LENGTH,
46
+ );
47
+
48
+ /**
49
+ * Navigate to the search page, seeding the search term. No-op unless the
50
+ * trimmed term meets the minimum length (covers both the button click and the
51
+ * Enter/submit path).
52
+ */
53
+ protected onSubmit(event: Event): void {
54
+ event.preventDefault();
55
+ if (!this.canSearch()) return;
56
+ this.browseAll(this.term().trim());
57
+ }
58
+
59
+ /** Go to the accounts list, optionally with a seeded search term. */
60
+ protected browseAll(q?: string): void {
61
+ void this.router.navigate(["/accounts"], {
62
+ queryParams: q ? { q } : {},
63
+ });
64
+ }
65
+ }
@@ -0,0 +1,12 @@
1
+ <main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
2
+ <div class="text-center">
3
+ <h1 class="text-4xl font-bold text-gray-900 mb-4">404</h1>
4
+ <p class="text-lg text-gray-600 mb-8">Page not found</p>
5
+ <a
6
+ routerLink="/"
7
+ class="inline-block px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
8
+ >
9
+ Go to Home
10
+ </a>
11
+ </div>
12
+ </main>
@@ -0,0 +1,33 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+ import { provideRouter } from '@angular/router';
3
+ import { NotFoundComponent } from './not-found';
4
+
5
+ describe('NotFoundComponent', () => {
6
+ beforeEach(async () => {
7
+ await TestBed.configureTestingModule({
8
+ imports: [NotFoundComponent],
9
+ providers: [provideRouter([])],
10
+ }).compileComponents();
11
+ });
12
+
13
+ it('should create the component', () => {
14
+ const fixture = TestBed.createComponent(NotFoundComponent);
15
+ const component = fixture.componentInstance;
16
+ expect(component).toBeTruthy();
17
+ });
18
+
19
+ it('should render main landmark', async () => {
20
+ const fixture = TestBed.createComponent(NotFoundComponent);
21
+ await fixture.whenStable();
22
+ const compiled = fixture.nativeElement as HTMLElement;
23
+ expect(compiled.querySelector('main')).toBeTruthy();
24
+ });
25
+
26
+ it('should have a link to home', async () => {
27
+ const fixture = TestBed.createComponent(NotFoundComponent);
28
+ await fixture.whenStable();
29
+ const compiled = fixture.nativeElement as HTMLElement;
30
+ const link = compiled.querySelector('a');
31
+ expect(link?.getAttribute('href')).toBe('/');
32
+ });
33
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { ChangeDetectionStrategy, Component } from '@angular/core';
7
+ import { RouterLink } from '@angular/router';
8
+
9
+ @Component({
10
+ selector: 'app-not-found',
11
+ changeDetection: ChangeDetectionStrategy.OnPush,
12
+ imports: [RouterLink],
13
+ templateUrl: './not-found.html',
14
+ })
15
+ export class NotFoundComponent {}
@@ -0,0 +1,14 @@
1
+ import { Directive } from '@angular/core';
2
+ import { classes } from '@spartan-ng/styles/utils';
3
+
4
+ @Directive({
5
+ selector: '[hlmAlertAction]',
6
+ host: {
7
+ 'data-slot': 'alert-action',
8
+ },
9
+ })
10
+ export class HlmAlertAction {
11
+ constructor() {
12
+ classes(() => 'absolute end-2 top-2');
13
+ }
14
+ }
@@ -0,0 +1,17 @@
1
+ import { Directive } from '@angular/core';
2
+ import { classes } from '@spartan-ng/styles/utils';
3
+
4
+ @Directive({
5
+ selector: '[hlmAlertDescription]',
6
+ host: {
7
+ 'data-slot': 'alert-description',
8
+ },
9
+ })
10
+ export class HlmAlertDescription {
11
+ constructor() {
12
+ classes(
13
+ () =>
14
+ 'text-sm text-balance md:text-pretty group-has-[>ng-icon]/alert:col-start-2 [&_p:not(:last-child)]:mb-4 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3',
15
+ );
16
+ }
17
+ }