@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,354 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+
7
+ /**
8
+ * filter-utils.ts
9
+ *
10
+ * Centralizes filter-related transformations for the object-search feature:
11
+ *
12
+ * 1. **URL serialization** — filter/sort/pagination state <-> URLSearchParams so
13
+ * a search can be bookmarked, shared, and restored on reload. Unlike the
14
+ * React reference, the cursor (`after`) is serialized too, so a deep-linked
15
+ * or refreshed page renders the exact same result page rather than page 1's
16
+ * data under a later page number.
17
+ *
18
+ * 2. **GraphQL query building** — the same state -> the `where` clause shape the
19
+ * GraphQL API expects.
20
+ *
21
+ * Both operate on the shared {@link ActiveFilterValue} type.
22
+ */
23
+
24
+ import type { SortState } from "./sort-utils";
25
+
26
+ export type FilterFieldType =
27
+ | "text"
28
+ | "picklist"
29
+ | "numeric"
30
+ | "boolean"
31
+ | "date"
32
+ | "daterange"
33
+ | "datetime"
34
+ | "datetimerange"
35
+ | "multipicklist"
36
+ | "search";
37
+
38
+ export interface FilterFieldConfig<TFieldName extends string = string> {
39
+ field: TFieldName;
40
+ label: string;
41
+ type: FilterFieldType;
42
+ placeholder?: string;
43
+ /** Required for picklist type. */
44
+ options?: Array<{ value: string; label: string }>;
45
+ helpText?: string;
46
+ /** Required for search type — the fields to match against with `or`. */
47
+ searchFields?: string[];
48
+ /**
49
+ * For date / datetime / range types: cap the picker at today so future
50
+ * dates (which can never match a `CreatedDate` / `LastModifiedDate`) can't
51
+ * be selected.
52
+ */
53
+ disableFuture?: boolean;
54
+ }
55
+
56
+ export interface ActiveFilterValue<TFieldName extends string = string> {
57
+ field: TFieldName;
58
+ label: string;
59
+ type: FilterFieldType;
60
+ value?: string;
61
+ min?: string;
62
+ max?: string;
63
+ }
64
+
65
+ // ---------------------------------------------------------------------------
66
+ // URL Serialization
67
+ // ---------------------------------------------------------------------------
68
+
69
+ /** Namespaces filter params so they don't collide with pagination/flags. */
70
+ const FILTER_PREFIX = "f.";
71
+ /** URL param key for the multi-field search term. */
72
+ const SEARCH_KEY = "q";
73
+ /** URL param key for the currently sorted field name. */
74
+ const SORT_KEY = "sort";
75
+ /** URL param key for the sort direction (ASC or DESC). */
76
+ const DIR_KEY = "dir";
77
+ /** URL param key for the page size preference. */
78
+ const PAGE_SIZE_KEY = "ps";
79
+ /** URL param key for the 1-based page number. */
80
+ const PAGE_KEY = "page";
81
+ /** URL param key for the opaque cursor of the current page's first row. */
82
+ const CURSOR_KEY = "after";
83
+
84
+ /** Snapshot of filter/sort/pagination state used to build a URL query string. */
85
+ export interface SearchParamsState {
86
+ filters: ActiveFilterValue[];
87
+ sort: SortState | null;
88
+ pageSize?: number;
89
+ pageIndex?: number;
90
+ /** Opaque `after` cursor for the current page (undefined on page 1). */
91
+ afterCursor?: string;
92
+ }
93
+
94
+ /** The state recovered from a URL query string on load. */
95
+ export interface ParsedSearchParams {
96
+ filters: ActiveFilterValue[];
97
+ sort: SortState | null;
98
+ pageSize: number | undefined;
99
+ pageIndex: number;
100
+ afterCursor: string | undefined;
101
+ }
102
+
103
+ /**
104
+ * Serializes filter/sort/pagination state into a `Params` object suitable for
105
+ * Angular Router `queryParams`.
106
+ *
107
+ * Encoding:
108
+ * - simple values: `f.<field>=<value>`
109
+ * - range values: `f.<field>.min=<min>` / `f.<field>.max=<max>`
110
+ * - search term: `q=<value>`
111
+ * - sort: `sort=<field>&dir=ASC|DESC`
112
+ * - pagination: `ps=<size>&page=<1-based>&after=<cursor>`
113
+ */
114
+ export function filtersToQueryParams(state: SearchParamsState): Record<string, string> {
115
+ const { filters, sort, pageSize, pageIndex, afterCursor } = state;
116
+ const params: Record<string, string> = {};
117
+
118
+ for (const filter of filters) {
119
+ if (filter.type === "search") {
120
+ if (filter.value) params[SEARCH_KEY] = filter.value;
121
+ continue;
122
+ }
123
+ if (filter.value !== undefined && filter.value !== "") {
124
+ params[`${FILTER_PREFIX}${filter.field}`] = filter.value;
125
+ }
126
+ if (filter.min !== undefined && filter.min !== "") {
127
+ params[`${FILTER_PREFIX}${filter.field}.min`] = filter.min;
128
+ }
129
+ if (filter.max !== undefined && filter.max !== "") {
130
+ params[`${FILTER_PREFIX}${filter.field}.max`] = filter.max;
131
+ }
132
+ }
133
+
134
+ if (sort) {
135
+ params[SORT_KEY] = sort.field;
136
+ params[DIR_KEY] = sort.direction;
137
+ }
138
+
139
+ if (pageSize !== undefined) {
140
+ params[PAGE_SIZE_KEY] = String(pageSize);
141
+ }
142
+
143
+ if (pageIndex !== undefined && pageIndex > 0) {
144
+ params[PAGE_KEY] = String(pageIndex + 1);
145
+ // The cursor is only meaningful past page 1. Persisting it (the fix over
146
+ // the React reference) lets a refreshed/shared deep link fetch the right
147
+ // page instead of page 1's rows under a higher page number.
148
+ if (afterCursor) params[CURSOR_KEY] = afterCursor;
149
+ }
150
+
151
+ return params;
152
+ }
153
+
154
+ /**
155
+ * Deserializes a URL param map back into filter/sort/pagination state.
156
+ *
157
+ * Requires the filter configs so it knows which params to look for and their
158
+ * types. Unknown params are ignored, making this safe against stale or
159
+ * hand-edited URLs.
160
+ */
161
+ export function queryParamsToFilters(
162
+ params: Record<string, string | undefined>,
163
+ configs: FilterFieldConfig[],
164
+ ): ParsedSearchParams {
165
+ const get = (key: string): string | undefined => {
166
+ const v = params[key];
167
+ return v === undefined || v === null ? undefined : String(v);
168
+ };
169
+
170
+ const filters: ActiveFilterValue[] = [];
171
+
172
+ for (const config of configs) {
173
+ const { field, label, type } = config;
174
+
175
+ if (type === "search") {
176
+ const q = get(SEARCH_KEY);
177
+ if (q) filters.push({ field, label, type: "search", value: q });
178
+ continue;
179
+ }
180
+
181
+ const value = get(`${FILTER_PREFIX}${field}`);
182
+ const min = get(`${FILTER_PREFIX}${field}.min`);
183
+ const max = get(`${FILTER_PREFIX}${field}.max`);
184
+
185
+ const hasValue = value !== undefined && value !== "";
186
+ const hasRange = (min !== undefined && min !== "") || (max !== undefined && max !== "");
187
+
188
+ if (hasValue || hasRange) {
189
+ filters.push({ field, label, type, value, min, max });
190
+ }
191
+ }
192
+
193
+ let sort: SortState | null = null;
194
+ const sortField = get(SORT_KEY);
195
+ const sortDir = get(DIR_KEY);
196
+ if (sortField) {
197
+ sort = { field: sortField, direction: sortDir === "DESC" ? "DESC" : "ASC" };
198
+ }
199
+
200
+ const pageSizeRaw = get(PAGE_SIZE_KEY);
201
+ const pageSize = pageSizeRaw ? parseInt(pageSizeRaw, 10) : undefined;
202
+
203
+ const pageRaw = get(PAGE_KEY);
204
+ const page = pageRaw ? parseInt(pageRaw, 10) : 1;
205
+ const pageIndex = !isNaN(page) && page > 1 ? page - 1 : 0;
206
+
207
+ // Cursor only applies past page 1; ignore a stray cursor on page 1.
208
+ const afterCursor = pageIndex > 0 ? get(CURSOR_KEY) : undefined;
209
+
210
+ return {
211
+ filters,
212
+ sort,
213
+ pageSize: pageSize && !isNaN(pageSize) ? pageSize : undefined,
214
+ pageIndex,
215
+ afterCursor,
216
+ };
217
+ }
218
+
219
+ // ---------------------------------------------------------------------------
220
+ // GraphQL Filter Building
221
+ // ---------------------------------------------------------------------------
222
+
223
+ /**
224
+ * Converts active filters into a GraphQL `where` clause. Each filter becomes a
225
+ * clause via {@link buildSingleFilter}; multiple clauses combine under a
226
+ * top-level `and` (intersection semantics).
227
+ *
228
+ * @returns The `where` object, or `undefined` when no filters are active.
229
+ */
230
+ export function buildFilter<TFilter>(
231
+ filters: ActiveFilterValue[],
232
+ configs: FilterFieldConfig[],
233
+ ): TFilter | undefined {
234
+ const configMap = new Map(configs.map((c) => [c.field, c]));
235
+ const clauses: TFilter[] = [];
236
+
237
+ for (const filter of filters) {
238
+ const clause = buildSingleFilter<TFilter>(filter, configMap.get(filter.field));
239
+ if (clause) clauses.push(clause);
240
+ }
241
+
242
+ if (clauses.length === 0) return undefined;
243
+ if (clauses.length === 1) return clauses[0];
244
+ return { and: clauses } as TFilter;
245
+ }
246
+
247
+ /** YYYY-MM-DD -> ISO-8601 midnight UTC (inclusive lower bound). */
248
+ function toStartOfDay(dateStr: string): string {
249
+ return `${dateStr}T00:00:00.000Z`;
250
+ }
251
+
252
+ /** YYYY-MM-DD -> ISO-8601 last millisecond UTC (inclusive upper bound). */
253
+ function toEndOfDay(dateStr: string): string {
254
+ return `${dateStr}T23:59:59.999Z`;
255
+ }
256
+
257
+ /**
258
+ * Converts a single active filter into a GraphQL filter clause.
259
+ *
260
+ * | Type | Operator(s) | Example |
261
+ * |-----------------|----------------|-----------------------------------------------------|
262
+ * | text | like | `{ Name: { like: "%Acme%" } }` |
263
+ * | picklist | eq | `{ Industry: { eq: "Technology" } }` |
264
+ * | multipicklist | eq or in | `{ Type: { in: ["A", "B"] } }` |
265
+ * | numeric | gte / lte | `{ Revenue: { gte: 1000, lte: 5000 } }` |
266
+ * | boolean | eq | `{ IsActive: { eq: true } }` |
267
+ * | date/datetime | dynamic op | `{ CreatedDate: { gte: { value: "..." } } }` |
268
+ * | daterange | gte + lte | combined with `and` when both bounds set |
269
+ * | search | like + or | `{ or: [{ Name: {like} }, { Phone: {like} }] }` |
270
+ *
271
+ * @returns A single clause, or `null` if the filter has no meaningful value.
272
+ */
273
+ function buildSingleFilter<TFilter>(
274
+ filter: ActiveFilterValue,
275
+ config?: FilterFieldConfig,
276
+ ): TFilter | null {
277
+ const { field, type, value, min, max } = filter;
278
+
279
+ switch (type) {
280
+ case "text": {
281
+ if (!value) return null;
282
+ return { [field]: { like: `%${value}%` } } as TFilter;
283
+ }
284
+ case "picklist": {
285
+ if (!value) return null;
286
+ return { [field]: { eq: value } } as TFilter;
287
+ }
288
+ case "numeric": {
289
+ if (!min && !max) return null;
290
+ const ops: Record<string, number> = {};
291
+ if (min) ops["gte"] = Number(min);
292
+ if (max) ops["lte"] = Number(max);
293
+ return { [field]: ops } as TFilter;
294
+ }
295
+ case "boolean": {
296
+ if (value === undefined || value === "") return null;
297
+ return { [field]: { eq: value === "true" } } as TFilter;
298
+ }
299
+ case "multipicklist": {
300
+ if (!value) return null;
301
+ const values = value.split(",");
302
+ if (values.length === 1) {
303
+ return { [field]: { eq: values[0] } } as TFilter;
304
+ }
305
+ return { [field]: { in: values } } as TFilter;
306
+ }
307
+ case "date": {
308
+ if (!min && !max) return null;
309
+ const op = value ?? (min ? "gte" : "lte");
310
+ const dateStr = min ?? max;
311
+ return { [field]: { [op]: { value: dateStr } } } as TFilter;
312
+ }
313
+ case "daterange": {
314
+ if (!min && !max) return null;
315
+ const clauses: TFilter[] = [];
316
+ if (min) clauses.push({ [field]: { gte: { value: min } } } as TFilter);
317
+ if (max) clauses.push({ [field]: { lte: { value: max } } } as TFilter);
318
+ return clauses.length === 1 ? clauses[0] : ({ and: clauses } as TFilter);
319
+ }
320
+ case "datetime": {
321
+ if (!min && !max) return null;
322
+ const op = value ?? (min ? "gte" : "lte");
323
+ const dateStr = (min ?? max)!;
324
+ const isoStr = op === "gte" || op === "gt" ? toStartOfDay(dateStr) : toEndOfDay(dateStr);
325
+ return { [field]: { [op]: { value: isoStr } } } as TFilter;
326
+ }
327
+ case "datetimerange": {
328
+ if (!min && !max) return null;
329
+ const clauses: TFilter[] = [];
330
+ if (min) clauses.push({ [field]: { gte: { value: toStartOfDay(min) } } } as TFilter);
331
+ if (max) clauses.push({ [field]: { lte: { value: toEndOfDay(max) } } } as TFilter);
332
+ return clauses.length === 1 ? clauses[0] : ({ and: clauses } as TFilter);
333
+ }
334
+ case "search": {
335
+ if (!value) return null;
336
+ const searchFields = config?.searchFields ?? [];
337
+ if (searchFields.length === 0) return null;
338
+ // Dot-notation for relationship fields (e.g. "Owner.Name") builds
339
+ // nested objects: { Owner: { Name: { like: "%x%" } } }.
340
+ const clauses = searchFields.map((f) => {
341
+ const parts = f.split(".");
342
+ let clause: Record<string, unknown> = { like: `%${value}%` };
343
+ for (let i = parts.length - 1; i >= 0; i--) {
344
+ clause = { [parts[i]]: clause };
345
+ }
346
+ return clause as TFilter;
347
+ });
348
+ if (clauses.length === 1) return clauses[0];
349
+ return { or: clauses } as TFilter;
350
+ }
351
+ default:
352
+ return null;
353
+ }
354
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ export * from "./debounce";
7
+ export * from "./field-utils";
8
+ export * from "./sort-utils";
9
+ export * from "./filter-utils";
10
+ // `createAsyncData` now lives in base-angular-app (`app/utils/async-data.ts`)
11
+ // and is consumed via the `utils/__inherit__async-data` stub — not re-exported
12
+ // here, so this feature barrel stays free of base-inherited symbols.
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+
7
+ import { ResultOrder, NullOrder } from "../../../api/graphql-operations-types";
8
+
9
+ export interface SortFieldConfig<TFieldName extends string = string> {
10
+ field: TFieldName;
11
+ label: string;
12
+ }
13
+
14
+ export interface SortState<TFieldName extends string = string> {
15
+ field: TFieldName;
16
+ direction: "ASC" | "DESC";
17
+ }
18
+
19
+ /**
20
+ * Converts a {@link SortState} into a GraphQL order-by object.
21
+ *
22
+ * @typeParam TOrderBy - The GraphQL order-by input type (e.g. `Account_OrderBy`).
23
+ * @param sort - The current sort state from the UI, or `null` if no sort is applied.
24
+ * @returns An order-by object for the query's `orderBy` variable, or `undefined`
25
+ * when no sort is active (defers to the API's default ordering).
26
+ *
27
+ * @example
28
+ * buildOrderBy({ field: 'Name', direction: 'ASC' })
29
+ * // => { Name: { order: 'ASC', nulls: 'LAST' } }
30
+ */
31
+ export function buildOrderBy<TOrderBy>(sort: SortState | null): TOrderBy | undefined {
32
+ if (!sort) return undefined;
33
+ return {
34
+ [sort.field]: {
35
+ order: sort.direction === "ASC" ? ResultOrder.Asc : ResultOrder.Desc,
36
+ nulls: NullOrder.Last,
37
+ },
38
+ } as TOrderBy;
39
+ }
@@ -0,0 +1,142 @@
1
+ <div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-6" [attr.aria-busy]="loading()">
2
+ <app-object-breadcrumb
3
+ listPath="/accounts"
4
+ listLabel="Accounts"
5
+ [loading]="loading()"
6
+ [recordName]="recordName()"
7
+ />
8
+
9
+ @if (loading()) {
10
+ <app-skeleton class="h-8 w-56 mb-4" />
11
+ <app-card>
12
+ <app-card-content class="space-y-8">
13
+ <div class="space-y-4">
14
+ @for (row of skeletonRows; track row) {
15
+ <div class="grid grid-cols-2 gap-x-8 gap-y-4">
16
+ <div>
17
+ <app-skeleton class="h-4 w-24 mb-1.5" />
18
+ <app-skeleton class="h-5 w-40" />
19
+ </div>
20
+ <div>
21
+ <app-skeleton class="h-4 w-24 mb-1.5" />
22
+ <app-skeleton class="h-5 w-40" />
23
+ </div>
24
+ </div>
25
+ }
26
+ </div>
27
+ <app-separator />
28
+ <div class="space-y-4">
29
+ <app-skeleton class="h-7 w-48 py-2" />
30
+ <div class="grid grid-cols-2 gap-x-8 gap-y-4">
31
+ <app-skeleton class="h-12 w-full" />
32
+ <app-skeleton class="h-12 w-full" />
33
+ </div>
34
+ </div>
35
+ </app-card-content>
36
+ </app-card>
37
+ } @else if (error()) {
38
+ <app-alert
39
+ variant="destructive"
40
+ icon="error"
41
+ title="Failed to load account"
42
+ description="Something went wrong while loading this account. Please try again later."
43
+ />
44
+ <div class="mt-4 flex gap-3">
45
+ <app-button appearance="outlined" (clicked)="goBack()">← Back</app-button>
46
+ <app-button appearance="outlined" (clicked)="reload()">Retry</app-button>
47
+ </div>
48
+ } @else if (notFound()) {
49
+ <app-card>
50
+ <app-card-content class="flex flex-col items-center justify-center py-16 text-center">
51
+ <app-icon name="notFound" size="3rem" class="text-muted-foreground mb-4" />
52
+ <h2 class="text-lg font-semibold mb-1">Account not found</h2>
53
+ <p class="text-sm text-muted-foreground mb-6">
54
+ The account you're looking for doesn't exist or may have been deleted.
55
+ </p>
56
+ <app-button appearance="outlined" (clicked)="goBack()">← Go back</app-button>
57
+ </app-card-content>
58
+ </app-card>
59
+ } @else if (account()) {
60
+ <h1 class="text-2xl font-bold mb-4">Account: {{ title() }}</h1>
61
+
62
+ <app-card>
63
+ <app-card-content class="space-y-8">
64
+ <!-- Top section -->
65
+ <div class="space-y-4">
66
+ @for (row of topRows(); track $index) {
67
+ <div class="grid grid-cols-2 gap-x-8 gap-y-4">
68
+ @for (field of row; track field.label) {
69
+ <div>
70
+ <dt class="text-sm text-muted-foreground">{{ field.label }}</dt>
71
+ <dd class="mt-0.5">
72
+ @if (field.value && field.telephone) {
73
+ <a [href]="'tel:' + field.value" class="underline">{{ field.value }}</a>
74
+ } @else { {{ field.value ?? "—" }} }
75
+ </dd>
76
+ </div>
77
+ }
78
+ </div>
79
+ }
80
+ </div>
81
+
82
+ <app-separator />
83
+
84
+ <app-collapsible title="Additional Information" [(open)]="additionalOpen">
85
+ <div class="space-y-4">
86
+ @for (row of additionalRows(); track $index) {
87
+ <div class="grid grid-cols-2 gap-x-8 gap-y-4">
88
+ @for (field of row; track field.label) {
89
+ <div>
90
+ <dt class="text-sm text-muted-foreground">{{ field.label }}</dt>
91
+ <dd class="mt-0.5">{{ field.value ?? "—" }}</dd>
92
+ </div>
93
+ }
94
+ </div>
95
+ }
96
+ <div>
97
+ <dt class="text-sm text-muted-foreground">Description</dt>
98
+ <dd class="mt-0.5">{{ description() ?? "—" }}</dd>
99
+ </div>
100
+ </div>
101
+ </app-collapsible>
102
+ <div class="space-y-4"></div>
103
+ <app-separator />
104
+
105
+ <app-collapsible title="Address Information" [(open)]="addressOpen">
106
+ <div class="grid grid-cols-2 gap-x-8 gap-y-4">
107
+ <div>
108
+ <dt class="text-sm text-muted-foreground">Billing Address</dt>
109
+ <dd class="mt-0.5">
110
+ @if (billingAddress()) { @for (line of billingAddress(); track $index) {
111
+ <div>{{ line }}</div>
112
+ } } @else { — }
113
+ </dd>
114
+ </div>
115
+ <div>
116
+ <dt class="text-sm text-muted-foreground">Shipping Address</dt>
117
+ <dd class="mt-0.5">
118
+ @if (shippingAddress()) { @for (line of shippingAddress(); track $index) {
119
+ <div>{{ line }}</div>
120
+ } } @else { — }
121
+ </dd>
122
+ </div>
123
+ </div>
124
+ </app-collapsible>
125
+ <div class="space-y-4"></div>
126
+ <app-separator />
127
+ <app-collapsible title="System Information" [(open)]="systemOpen">
128
+ <div class="grid grid-cols-2 gap-x-8 gap-y-4">
129
+ <div>
130
+ <dt class="text-sm text-muted-foreground">Created By</dt>
131
+ <dd class="mt-0.5">{{ createdBy() ?? "—" }}</dd>
132
+ </div>
133
+ <div>
134
+ <dt class="text-sm text-muted-foreground">Last Modified By</dt>
135
+ <dd class="mt-0.5">{{ lastModifiedBy() ?? "—" }}</dd>
136
+ </div>
137
+ </div>
138
+ </app-collapsible>
139
+ </app-card-content>
140
+ </app-card>
141
+ }
142
+ </div>