@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,76 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import {
7
+ ChangeDetectionStrategy,
8
+ Component,
9
+ DestroyRef,
10
+ effect,
11
+ inject,
12
+ input,
13
+ signal,
14
+ } from "@angular/core";
15
+ import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
16
+ import { Subject } from "rxjs";
17
+ import { debounceTime } from "rxjs/operators";
18
+ import { InputComponent } from "../../../components/ui/input/input";
19
+ import { ObjectSearchStateService } from "../object-search-state.service";
20
+ import { FILTER_DEBOUNCE_MS } from "../utils/debounce";
21
+ import type { FilterFieldConfig } from "../utils/filter-utils";
22
+ import { FilterFieldWrapperComponent } from "./filter-field-wrapper";
23
+
24
+ /**
25
+ * Text filter — free-text input that writes a `like %value%` clause via
26
+ * {@link ObjectSearchStateService.setFilter}. Keystrokes update the local
27
+ * signal immediately and flush to shared state on a
28
+ * {@link FILTER_DEBOUNCE_MS}ms trailing debounce.
29
+ */
30
+ @Component({
31
+ selector: "app-text-filter",
32
+ changeDetection: ChangeDetectionStrategy.OnPush,
33
+ imports: [InputComponent, FilterFieldWrapperComponent],
34
+ templateUrl: "./text-filter.html",
35
+ })
36
+ export class TextFilterComponent {
37
+ private readonly state = inject(ObjectSearchStateService);
38
+ private readonly destroyRef = inject(DestroyRef);
39
+
40
+ readonly config = input.required<FilterFieldConfig>();
41
+
42
+ protected readonly localValue = signal<string>("");
43
+ private readonly commit$ = new Subject<string>();
44
+
45
+ constructor() {
46
+ this.commit$
47
+ .pipe(debounceTime(FILTER_DEBOUNCE_MS), takeUntilDestroyed(this.destroyRef))
48
+ .subscribe((v) => this.commit(v));
49
+
50
+ // Sync the input with shared state (URL restore, reset-all, ...).
51
+ effect(() => {
52
+ const cfg = this.config();
53
+ const external = this.state.filterFor(cfg.field)?.value ?? "";
54
+ this.localValue.set(external);
55
+ });
56
+ }
57
+
58
+ protected onValueChange(v: string): void {
59
+ this.localValue.set(v);
60
+ this.commit$.next(v);
61
+ }
62
+
63
+ private commit(v: string): void {
64
+ const cfg = this.config();
65
+ if (v) {
66
+ this.state.setFilter(cfg.field, {
67
+ field: cfg.field,
68
+ label: cfg.label,
69
+ type: "text",
70
+ value: v,
71
+ });
72
+ } else {
73
+ this.state.removeFilter(cfg.field);
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { computed, DestroyRef, inject, Injectable, signal, type Signal } from "@angular/core";
7
+ import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
8
+ import { ActivatedRoute, Router } from "@angular/router";
9
+ import { Subject } from "rxjs";
10
+ import { debounceTime } from "rxjs/operators";
11
+ import {
12
+ buildFilter,
13
+ filtersToQueryParams,
14
+ queryParamsToFilters,
15
+ type ActiveFilterValue,
16
+ type FilterFieldConfig,
17
+ } from "./utils/filter-utils";
18
+ import { buildOrderBy, type SortState } from "./utils/sort-utils";
19
+
20
+ /** How long to wait before flushing state changes to the URL. */
21
+ const URL_SYNC_DEBOUNCE_MS = 300;
22
+
23
+ /** Cursor-pagination configuration for an object-search page. */
24
+ export interface PaginationConfig {
25
+ defaultPageSize: number;
26
+ validPageSizes: number[];
27
+ }
28
+
29
+ /** Derived, API-ready query signals returned from {@link ObjectSearchStateService.init}. */
30
+ export interface ObjectSearchQuery<TFilter, TOrderBy> {
31
+ where: Signal<TFilter | undefined>;
32
+ orderBy: Signal<TOrderBy | undefined>;
33
+ }
34
+
35
+ /**
36
+ * Filter / sort / cursor-pagination state for one object-search page — the
37
+ * Angular analogue of the React `useObjectSearchParams` hook plus
38
+ * `FilterContext`.
39
+ *
40
+ * ## State model
41
+ * Signals drive instant UI updates. The URL query params are the durable source
42
+ * of truth so a refresh or shared link restores the same view. URL writes are
43
+ * debounced (300 ms) to avoid history spam.
44
+ *
45
+ * Unlike the React reference, the pagination cursor (`after`) is part of the URL
46
+ * (see {@link filtersToQueryParams}), so a deep-linked page N fetches page N's
47
+ * rows rather than page 1's rows shown under a higher page number.
48
+ *
49
+ * ## Scope
50
+ * Provide per route/component (`providers: [ObjectSearchStateService]`), NOT in
51
+ * root — each search page owns its own state and cursor stack.
52
+ *
53
+ * ## Usage
54
+ * Call {@link init} once from the hosting component with the field/pagination
55
+ * config, then read the exposed signals and call the mutators.
56
+ */
57
+ @Injectable()
58
+ export class ObjectSearchStateService {
59
+ private readonly router = inject(Router);
60
+ private readonly route = inject(ActivatedRoute);
61
+ private readonly destroyRef = inject(DestroyRef);
62
+
63
+ private filterConfigs: FilterFieldConfig[] = [];
64
+ private defaultPageSize = 10;
65
+ private validPageSizes: number[] = [10];
66
+ private initialized = false;
67
+
68
+ // -- Core state signals -----------------------------------------------------
69
+ private readonly _filters = signal<ActiveFilterValue[]>([]);
70
+ private readonly _sort = signal<SortState | null>(null);
71
+ private readonly _pageSize = signal<number>(10);
72
+ private readonly _pageIndex = signal<number>(0);
73
+ private readonly _afterCursor = signal<string | undefined>(undefined);
74
+
75
+ /** Cursor stack for "previous page" — mirrors the React ref-held stack. */
76
+ private cursorStack: string[] = [];
77
+ /** Coalesces rapid state changes into a single debounced URL write. */
78
+ private readonly urlSync$ = new Subject<void>();
79
+
80
+ // -- Public read signals -----------------------------------------------------
81
+ readonly filters: Signal<ActiveFilterValue[]> = this._filters.asReadonly();
82
+ readonly sort: Signal<SortState | null> = this._sort.asReadonly();
83
+ readonly pageSize: Signal<number> = this._pageSize.asReadonly();
84
+ readonly pageIndex: Signal<number> = this._pageIndex.asReadonly();
85
+ readonly afterCursor: Signal<string | undefined> = this._afterCursor.asReadonly();
86
+ readonly hasActiveFilters = computed(() => this._filters().length > 0);
87
+ readonly hasPreviousPage = computed(() => this._pageIndex() > 0);
88
+
89
+ constructor() {
90
+ this.urlSync$
91
+ .pipe(debounceTime(URL_SYNC_DEBOUNCE_MS), takeUntilDestroyed(this.destroyRef))
92
+ .subscribe(() => this.flushToUrl());
93
+ }
94
+
95
+ /**
96
+ * Initializes the service from the given config and seeds state from the
97
+ * current URL. Safe to call once; subsequent calls only recompute the
98
+ * derived query signals.
99
+ */
100
+ init<TFilter, TOrderBy>(
101
+ filterConfigs: FilterFieldConfig[],
102
+ paginationConfig?: PaginationConfig,
103
+ ): ObjectSearchQuery<TFilter, TOrderBy> {
104
+ if (!this.initialized) {
105
+ this.initialized = true;
106
+ this.filterConfigs = filterConfigs;
107
+ this.defaultPageSize = paginationConfig?.defaultPageSize ?? 10;
108
+ this.validPageSizes = paginationConfig?.validPageSizes ?? [this.defaultPageSize];
109
+ this.seedFromUrl();
110
+ }
111
+
112
+ const where = computed(() => buildFilter<TFilter>(this._filters(), this.filterConfigs));
113
+ const orderBy = computed(() => buildOrderBy<TOrderBy>(this._sort()));
114
+ return { where, orderBy };
115
+ }
116
+
117
+ // -- Filter mutators ---------------------------------------------------------
118
+
119
+ /** Adds or replaces the filter for `field`; `undefined` removes it. */
120
+ setFilter(field: string, value: ActiveFilterValue | undefined): void {
121
+ this._filters.update((prev) => {
122
+ const next = prev.filter((f) => f.field !== field);
123
+ if (value) next.push(value);
124
+ return next;
125
+ });
126
+ this.resetPagination();
127
+ this.urlSync$.next();
128
+ }
129
+
130
+ /** Removes the active filter for `field`, if any. */
131
+ removeFilter(field: string): void {
132
+ this._filters.update((prev) => prev.filter((f) => f.field !== field));
133
+ this.resetPagination();
134
+ this.urlSync$.next();
135
+ }
136
+
137
+ /** Reads the active filter value for a field (for filter components). */
138
+ filterFor(field: string): ActiveFilterValue | undefined {
139
+ return this._filters().find((f) => f.field === field);
140
+ }
141
+
142
+ // -- Sort mutator ------------------------------------------------------------
143
+
144
+ /** Sets (or clears) the sort; resets pagination to the first page. */
145
+ setSort(sort: SortState | null): void {
146
+ this._sort.set(sort);
147
+ this.resetPagination();
148
+ this.urlSync$.next();
149
+ }
150
+
151
+ // -- Pagination mutators -----------------------------------------------------
152
+
153
+ /** Advances to the next page using the supplied `endCursor`. */
154
+ goToNextPage(endCursor: string): void {
155
+ this.cursorStack = [...this.cursorStack, endCursor];
156
+ this._afterCursor.set(endCursor);
157
+ this._pageIndex.update((i) => i + 1);
158
+ this.urlSync$.next();
159
+ }
160
+
161
+ /** Returns to the previous page by popping the cursor stack. */
162
+ goToPreviousPage(): void {
163
+ this.cursorStack = this.cursorStack.slice(0, -1);
164
+ const prev =
165
+ this.cursorStack.length > 0 ? this.cursorStack[this.cursorStack.length - 1] : undefined;
166
+ this._afterCursor.set(prev);
167
+ this._pageIndex.update((i) => Math.max(0, i - 1));
168
+ this.urlSync$.next();
169
+ }
170
+
171
+ /** Sets a validated page size and resets pagination. */
172
+ setPageSize(size: number): void {
173
+ this._pageSize.set(this.getValidPageSize(size));
174
+ this.resetPagination();
175
+ this.urlSync$.next();
176
+ }
177
+
178
+ // -- Reset -------------------------------------------------------------------
179
+
180
+ /** Clears all filters, sort, and pagination in one call (flushed at once). */
181
+ resetAll(): void {
182
+ this._filters.set([]);
183
+ this._sort.set(null);
184
+ this._pageSize.set(this.defaultPageSize);
185
+ this.resetPagination();
186
+ this.flushToUrl();
187
+ }
188
+
189
+ // -- Internals ---------------------------------------------------------------
190
+
191
+ private resetPagination(): void {
192
+ this._pageIndex.set(0);
193
+ this._afterCursor.set(undefined);
194
+ this.cursorStack = [];
195
+ }
196
+
197
+ private getValidPageSize(size: number): number {
198
+ return this.validPageSizes.includes(size) ? size : this.defaultPageSize;
199
+ }
200
+
201
+ private seedFromUrl(): void {
202
+ const params = this.route.snapshot.queryParams as Record<string, string | undefined>;
203
+ const parsed = queryParamsToFilters(params, this.filterConfigs);
204
+ this._filters.set(parsed.filters);
205
+ this._sort.set(parsed.sort);
206
+ this._pageSize.set(this.getValidPageSize(parsed.pageSize ?? this.defaultPageSize));
207
+ this._pageIndex.set(parsed.pageIndex);
208
+ this._afterCursor.set(parsed.afterCursor);
209
+ // Rebuild a minimal cursor stack so "previous" works after a deep link.
210
+ // Pages before the current one are unknown, so pad the stack with the
211
+ // current cursor; going back drains it and eventually returns to page 1.
212
+ if (parsed.pageIndex > 0 && parsed.afterCursor) {
213
+ this.cursorStack = Array<string>(parsed.pageIndex).fill(parsed.afterCursor);
214
+ }
215
+ }
216
+
217
+ private flushToUrl(): void {
218
+ const queryParams = filtersToQueryParams({
219
+ filters: this._filters(),
220
+ sort: this._sort(),
221
+ pageSize: this._pageSize(),
222
+ pageIndex: this._pageIndex(),
223
+ afterCursor: this._afterCursor(),
224
+ });
225
+ void this.router.navigate([], {
226
+ relativeTo: this.route,
227
+ queryParams,
228
+ // Replace so filter typing doesn't flood browser history.
229
+ replaceUrl: true,
230
+ });
231
+ }
232
+ }
@@ -0,0 +1,8 @@
1
+ <app-paginator
2
+ [length]="totalCount() ?? 0"
3
+ [pageIndex]="pageIndex()"
4
+ [pageSize]="pageSize()"
5
+ [pageSizeOptions]="pageSizeOptions()"
6
+ [disabled]="disabled()"
7
+ (page)="onPage($event)"
8
+ />
@@ -0,0 +1,45 @@
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, inject, input } from "@angular/core";
7
+ import { PaginatorComponent } from "../../../components/ui/paginator/paginator";
8
+ import type { PageEvent } from "../../../components/ui/paginator/types";
9
+ import { ObjectSearchStateService } from "../object-search-state.service";
10
+
11
+ /**
12
+ * Cursor-pagination bridge. Feeds shared cursor state into {@link PaginatorComponent}
13
+ * and translates its offset-style `(page)` event back into the cursor walk the
14
+ * state service understands.
15
+ */
16
+ @Component({
17
+ selector: "app-pagination-controls",
18
+ changeDetection: ChangeDetectionStrategy.OnPush,
19
+ imports: [PaginatorComponent],
20
+ templateUrl: "./pagination.html",
21
+ })
22
+ export class PaginationControlsComponent {
23
+ readonly totalCount = input<number | undefined>(undefined);
24
+ readonly hasNextPage = input<boolean>(false);
25
+ readonly endCursor = input<string | undefined>(undefined);
26
+ readonly pageSizeOptions = input.required<readonly number[]>();
27
+ readonly disabled = input<boolean>(false);
28
+
29
+ private readonly state = inject(ObjectSearchStateService);
30
+ protected readonly pageIndex = this.state.pageIndex;
31
+ protected readonly pageSize = this.state.pageSize;
32
+
33
+ protected onPage(event: PageEvent): void {
34
+ if (event.pageSize !== this.pageSize()) {
35
+ this.state.setPageSize(event.pageSize);
36
+ return;
37
+ }
38
+ if (event.pageIndex > this.pageIndex()) {
39
+ const cursor = this.endCursor();
40
+ if (cursor && this.hasNextPage()) this.state.goToNextPage(cursor);
41
+ } else if (event.pageIndex < this.pageIndex()) {
42
+ this.state.goToPreviousPage();
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,10 @@
1
+ <app-input
2
+ class="block"
3
+ type="search"
4
+ icon="search"
5
+ [label]="label()"
6
+ [placeholder]="placeholder()"
7
+ [ariaLabel]="ariaLabel()"
8
+ [id]="inputId()"
9
+ [(value)]="value"
10
+ />
@@ -0,0 +1,28 @@
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, input, model } from "@angular/core";
7
+ import { InputComponent } from "../../../components/ui/input/input";
8
+
9
+ /**
10
+ * Presentational search box: a text input with a leading search icon inside
11
+ * its border, purely controlled via `value` with no search state of its own.
12
+ * Reused by the Home landing form and by `app-search-filter` (which adds the
13
+ * debounce + shared-state wiring around it).
14
+ */
15
+ @Component({
16
+ selector: "app-search-bar",
17
+ changeDetection: ChangeDetectionStrategy.OnPush,
18
+ imports: [InputComponent],
19
+ host: { class: "flex-1 block" },
20
+ templateUrl: "./search-bar.html",
21
+ })
22
+ export class SearchBarComponent {
23
+ readonly value = model<string>("");
24
+ readonly placeholder = input<string>("");
25
+ readonly label = input<string>("");
26
+ readonly ariaLabel = input<string>("");
27
+ readonly inputId = input<string>("");
28
+ }
@@ -0,0 +1,24 @@
1
+ <div class="flex items-center gap-2">
2
+ <span class="text-sm text-muted-foreground whitespace-nowrap">{{ label() }}</span>
3
+ <app-select
4
+ class="w-[160px]"
5
+ [options]="options()"
6
+ [value]="selectedValue()"
7
+ (valueChange)="onFieldChange($event)"
8
+ placeholder="Default"
9
+ />
10
+ @if (sort(); as active) {
11
+ <app-button
12
+ appearance="text"
13
+ size="icon-sm"
14
+ [ariaLabel]="'Sort ' + (active.direction === 'ASC' ? 'descending' : 'ascending')"
15
+ (clicked)="toggleDirection()"
16
+ >
17
+ @if (active.direction === "ASC") {
18
+ <app-icon name="arrowUp" />
19
+ } @else {
20
+ <app-icon name="arrowDown" />
21
+ }
22
+ </app-button>
23
+ }
24
+ </div>
@@ -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, input } from "@angular/core";
7
+ import { ButtonComponent } from "../../../components/ui/button/button";
8
+ import { IconComponent } from "../../../components/ui/icon/icon";
9
+ import {
10
+ SelectComponent,
11
+ type AppSelectOption,
12
+ } from "../../../components/ui/select/select";
13
+ import { ObjectSearchStateService } from "../object-search-state.service";
14
+ import type { SortFieldConfig, SortState } from "../utils/sort-utils";
15
+
16
+ /** Sentinel value used in the select to represent "no sort". */
17
+ const NONE_VALUE = "__none__";
18
+
19
+ /**
20
+ * Sort field + direction toggle. Choosing a field applies ASC by default; the
21
+ * direction button flips ASC/DESC and only appears while a sort is active.
22
+ * Selecting `Default` clears the sort (`setSort(null)`).
23
+ */
24
+ @Component({
25
+ selector: "app-sort-control",
26
+ changeDetection: ChangeDetectionStrategy.OnPush,
27
+ imports: [ButtonComponent, IconComponent, SelectComponent],
28
+ templateUrl: "./sort-control.html",
29
+ })
30
+ export class SortControlComponent {
31
+ readonly sortFields = input.required<SortFieldConfig[]>();
32
+ readonly label = input<string>("Sort by");
33
+
34
+ private readonly state = inject(ObjectSearchStateService);
35
+ protected readonly sort = this.state.sort;
36
+
37
+ protected readonly options = computed<AppSelectOption[]>(() => [
38
+ { value: NONE_VALUE, label: "Default" },
39
+ ...this.sortFields().map((c) => ({ value: c.field, label: c.label })),
40
+ ]);
41
+
42
+ protected readonly selectedValue = computed(() => this.sort()?.field ?? NONE_VALUE);
43
+
44
+ protected onFieldChange(field: string): void {
45
+ if (field === NONE_VALUE) {
46
+ this.state.setSort(null);
47
+ return;
48
+ }
49
+ const current = this.sort();
50
+ const next: SortState = {
51
+ field,
52
+ direction: current?.direction ?? "ASC",
53
+ };
54
+ this.state.setSort(next);
55
+ }
56
+
57
+ protected toggleDirection(): void {
58
+ const current = this.sort();
59
+ if (!current) return;
60
+ this.state.setSort({
61
+ field: current.field,
62
+ direction: current.direction === "ASC" ? "DESC" : "ASC",
63
+ });
64
+ }
65
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+
7
+ /** Default debounce delay for keystroke-driven filter inputs (search, text, numeric). */
8
+ export const FILTER_DEBOUNCE_MS = 300;
9
+
10
+ /**
11
+ * Creates a debounced version of the provided function.
12
+ *
13
+ * Each call to the returned function resets the internal timer. The wrapped
14
+ * function is only invoked once the timer expires without being reset. This
15
+ * makes it ideal for rate-limiting high-frequency events like input changes.
16
+ *
17
+ * @typeParam T - The function signature to debounce.
18
+ * @param fn - The function to debounce.
19
+ * @param ms - The debounce delay in milliseconds.
20
+ * @returns A new function with the same signature that delays execution.
21
+ */
22
+ export function debounce<T extends (...args: never[]) => void>(
23
+ fn: T,
24
+ ms: number,
25
+ ): (...args: Parameters<T>) => void {
26
+ let timer: ReturnType<typeof setTimeout> | undefined;
27
+ return (...args: Parameters<T>) => {
28
+ clearTimeout(timer);
29
+ timer = setTimeout(() => fn(...args), ms);
30
+ };
31
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+
7
+ /** A Salesforce GraphQL scalar field: `{ value, displayValue }`. */
8
+ export interface UiField {
9
+ displayValue?: string | null;
10
+ value?: unknown;
11
+ }
12
+
13
+ /**
14
+ * Extracts a human-readable string from a Salesforce GraphQL scalar field,
15
+ * preferring the server-formatted `displayValue` over the raw `value`.
16
+ *
17
+ * @returns The display string, or `null` when the field is empty.
18
+ */
19
+ export function fieldValue(field: UiField | null | undefined): string | null {
20
+ if (field?.displayValue != null) return field.displayValue;
21
+ if (field?.value != null) return String(field.value);
22
+ return null;
23
+ }
24
+
25
+ /**
26
+ * Formats a Salesforce address into display lines (street / city-state-zip /
27
+ * country), omitting empty parts. Returns `null` when nothing is present.
28
+ */
29
+ export function getAddressFieldLines(address: {
30
+ street?: string | null;
31
+ city?: string | null;
32
+ state?: string | null;
33
+ postalCode?: string | null;
34
+ country?: string | null;
35
+ }): string[] | null {
36
+ const cityStateZip = [address.city, address.state].filter(Boolean).join(", ");
37
+ const cityStateZipLine = [cityStateZip, address.postalCode].filter(Boolean).join(" ");
38
+ const lines = [address.street, cityStateZipLine, address.country].filter(Boolean) as string[];
39
+ if (lines.length === 0) return null;
40
+ return lines;
41
+ }
42
+
43
+ /**
44
+ * Formats an ISO datetime string via `Intl`/`toLocaleString`. Returns `null`
45
+ * for empty input so callers can fall back cleanly.
46
+ */
47
+ export function formatDateTimeField(
48
+ value: string | null | undefined,
49
+ locales?: Intl.LocalesArgument,
50
+ options?: Intl.DateTimeFormatOptions,
51
+ ): string | null {
52
+ if (!value) return null;
53
+ return new Date(value).toLocaleString(locales, options);
54
+ }