@salesforce/ui-bundle-template-app-angular-template-b2x 11.30.0

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 (211) hide show
  1. package/LICENSE.txt +82 -0
  2. package/dist/.forceignore +15 -0
  3. package/dist/.husky/pre-commit +4 -0
  4. package/dist/.prettierignore +11 -0
  5. package/dist/.prettierrc +17 -0
  6. package/dist/CHANGELOG.md +3966 -0
  7. package/dist/README.md +77 -0
  8. package/dist/config/project-scratch-def.json +13 -0
  9. package/dist/eslint.config.js +7 -0
  10. package/dist/force-app/main/default/classes/UIBundleAuthUtils.cls +68 -0
  11. package/dist/force-app/main/default/classes/UIBundleAuthUtils.cls-meta.xml +5 -0
  12. package/dist/force-app/main/default/classes/UIBundleChangePassword.cls +77 -0
  13. package/dist/force-app/main/default/classes/UIBundleChangePassword.cls-meta.xml +5 -0
  14. package/dist/force-app/main/default/classes/UIBundleForgotPassword.cls +71 -0
  15. package/dist/force-app/main/default/classes/UIBundleForgotPassword.cls-meta.xml +5 -0
  16. package/dist/force-app/main/default/classes/UIBundleLogin.cls +105 -0
  17. package/dist/force-app/main/default/classes/UIBundleLogin.cls-meta.xml +5 -0
  18. package/dist/force-app/main/default/classes/UIBundleRegistration.cls +162 -0
  19. package/dist/force-app/main/default/classes/UIBundleRegistration.cls-meta.xml +5 -0
  20. package/dist/force-app/main/default/digitalExperienceConfigs/angularexternalapp1.digitalExperienceConfig-meta.xml +8 -0
  21. package/dist/force-app/main/default/digitalExperiences/site/angularexternalapp1/angularexternalapp1.digitalExperience-meta.xml +11 -0
  22. package/dist/force-app/main/default/digitalExperiences/site/angularexternalapp1/sfdc_cms__site/angularexternalapp1/_meta.json +5 -0
  23. package/dist/force-app/main/default/digitalExperiences/site/angularexternalapp1/sfdc_cms__site/angularexternalapp1/content.json +10 -0
  24. package/dist/force-app/main/default/networks/angularexternalapp.network-meta.xml +60 -0
  25. package/dist/force-app/main/default/package.xml +24 -0
  26. package/dist/force-app/main/default/permissionsets/angularexternalapp_Guest_User_Api_Access.permissionset-meta.xml +9 -0
  27. package/dist/force-app/main/default/sites/angularexternalapp.site-meta.xml +31 -0
  28. package/dist/force-app/main/default/uiBundles/angularexternalapp/.forceignore +15 -0
  29. package/dist/force-app/main/default/uiBundles/angularexternalapp/.postcssrc.json +5 -0
  30. package/dist/force-app/main/default/uiBundles/angularexternalapp/.prettierignore +8 -0
  31. package/dist/force-app/main/default/uiBundles/angularexternalapp/.prettierrc +12 -0
  32. package/dist/force-app/main/default/uiBundles/angularexternalapp/CHANGELOG.md +4 -0
  33. package/dist/force-app/main/default/uiBundles/angularexternalapp/README.md +85 -0
  34. package/dist/force-app/main/default/uiBundles/angularexternalapp/angular.json +98 -0
  35. package/dist/force-app/main/default/uiBundles/angularexternalapp/angularexternalapp.uibundle-meta.xml +8 -0
  36. package/dist/force-app/main/default/uiBundles/angularexternalapp/e2e/app.spec.ts +15 -0
  37. package/dist/force-app/main/default/uiBundles/angularexternalapp/esbuild/api-version.mjs +17 -0
  38. package/dist/force-app/main/default/uiBundles/angularexternalapp/eslint.config.js +60 -0
  39. package/dist/force-app/main/default/uiBundles/angularexternalapp/middleware/html.mjs +3 -0
  40. package/dist/force-app/main/default/uiBundles/angularexternalapp/middleware/proxy.mjs +12 -0
  41. package/dist/force-app/main/default/uiBundles/angularexternalapp/package.json +56 -0
  42. package/dist/force-app/main/default/uiBundles/angularexternalapp/playwright.config.ts +25 -0
  43. package/dist/force-app/main/default/uiBundles/angularexternalapp/public/favicon.ico +0 -0
  44. package/dist/force-app/main/default/uiBundles/angularexternalapp/scripts/rewrite-e2e-assets.mjs +30 -0
  45. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/api/account/account-search.service.ts +196 -0
  46. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/api/account/distinctAccountIndustries.ts +26 -0
  47. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/api/account/distinctAccountTypes.ts +26 -0
  48. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/api/account/getAccountDetail.ts +128 -0
  49. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/api/account/searchAccounts.ts +58 -0
  50. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/api/data-client.service.spec.ts +184 -0
  51. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/api/data-client.service.ts +74 -0
  52. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/api/user-profile.service.ts +126 -0
  53. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/app.config.ts +22 -0
  54. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/app.html +1 -0
  55. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/app.routes.ts +77 -0
  56. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/app.spec.ts +18 -0
  57. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/app.ts +15 -0
  58. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/layout/app-layout/app-layout.component.html +53 -0
  59. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/layout/app-layout/app-layout.component.spec.ts +89 -0
  60. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/layout/app-layout/app-layout.component.ts +81 -0
  61. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/_field-size.scss +42 -0
  62. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/alert/alert.component.html +31 -0
  63. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/alert/alert.component.ts +53 -0
  64. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/button/button.component.html +18 -0
  65. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/button/button.component.scss +112 -0
  66. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/button/button.component.ts +57 -0
  67. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/card/card.component.scss +34 -0
  68. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/card/card.component.ts +110 -0
  69. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/collapsible/collapsible.component.html +10 -0
  70. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/collapsible/collapsible.component.ts +26 -0
  71. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/date-picker/date-picker.component.html +25 -0
  72. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/date-picker/date-picker.component.scss +36 -0
  73. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/date-picker/date-picker.component.ts +41 -0
  74. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/date-range-picker/date-range-picker.component.html +34 -0
  75. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/date-range-picker/date-range-picker.component.scss +33 -0
  76. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/date-range-picker/date-range-picker.component.ts +66 -0
  77. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/dialog/dialog.component.html +37 -0
  78. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/dialog/dialog.component.ts +55 -0
  79. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/field/field.component.html +21 -0
  80. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/field/field.component.ts +36 -0
  81. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/field-size.ts +8 -0
  82. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/input/input.component.html +19 -0
  83. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/input/input.component.scss +35 -0
  84. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/input/input.component.ts +36 -0
  85. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/label/label.component.html +3 -0
  86. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/label/label.component.ts +17 -0
  87. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/paginator/paginator.component.html +10 -0
  88. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/paginator/paginator.component.ts +37 -0
  89. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/popover/popover.component.html +41 -0
  90. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/popover/popover.component.ts +40 -0
  91. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/select/select.component.html +24 -0
  92. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/select/select.component.scss +35 -0
  93. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/select/select.component.ts +72 -0
  94. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/separator/separator.component.html +1 -0
  95. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/separator/separator.component.scss +23 -0
  96. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/separator/separator.component.ts +56 -0
  97. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/skeleton/skeleton.component.html +1 -0
  98. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/skeleton/skeleton.component.scss +28 -0
  99. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/skeleton/skeleton.component.ts +24 -0
  100. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/components/ui/spinner/spinner.component.ts +35 -0
  101. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/auth/auth.guard.ts +50 -0
  102. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/auth/auth.service.ts +126 -0
  103. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/components/status-alert/status-alert.component.html +7 -0
  104. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/components/status-alert/status-alert.component.ts +52 -0
  105. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/config/authentication.config.ts +75 -0
  106. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/forms/auth-form/auth-form.component.html +38 -0
  107. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/forms/auth-form/auth-form.component.ts +94 -0
  108. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/forms/footer-link/footer-link.component.html +11 -0
  109. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/forms/footer-link/footer-link.component.ts +26 -0
  110. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/forms/reactive-form-page.base.ts +50 -0
  111. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/forms/submit-button/submit-button.component.html +8 -0
  112. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/forms/submit-button/submit-button.component.scss +17 -0
  113. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/forms/submit-button/submit-button.component.ts +35 -0
  114. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/layouts/auth-app-layout/auth-app-layout.component.html +2 -0
  115. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/layouts/auth-app-layout/auth-app-layout.component.ts +30 -0
  116. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/layouts/card-layout/card-layout.component.html +17 -0
  117. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/layouts/card-layout/card-layout.component.ts +40 -0
  118. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/menu/auth-menu/auth-menu.component.html +26 -0
  119. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/menu/auth-menu/auth-menu.component.ts +46 -0
  120. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/session-timeout/session-time-servlet.ts +130 -0
  121. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/session-timeout/session-timeout-validator/session-timeout-validator.component.html +57 -0
  122. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/session-timeout/session-timeout-validator/session-timeout-validator.component.ts +205 -0
  123. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/session-timeout/session-timeout.config.ts +83 -0
  124. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/session-timeout/session-timeout.service.ts +201 -0
  125. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/utils/auth-helpers.ts +68 -0
  126. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/utils/auth-validators.ts +72 -0
  127. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/authentication/utils/helpers.ts +85 -0
  128. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/active-filters/active-filters.component.html +23 -0
  129. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/active-filters/active-filters.component.ts +78 -0
  130. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/date-filter/date-filter.component.html +18 -0
  131. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/date-filter/date-filter.component.ts +137 -0
  132. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/date-range-filter/date-range-filter.component.html +11 -0
  133. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/date-range-filter/date-range-filter.component.ts +69 -0
  134. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/filter-field-wrapper/filter-field-wrapper.component.html +11 -0
  135. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/filter-field-wrapper/filter-field-wrapper.component.ts +36 -0
  136. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/multi-select-filter/multi-select-filter.component.html +10 -0
  137. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/multi-select-filter/multi-select-filter.component.ts +58 -0
  138. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/numeric-range-filter/numeric-range-filter.component.html +22 -0
  139. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/numeric-range-filter/numeric-range-filter.component.ts +146 -0
  140. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/search-filter/search-filter.component.html +8 -0
  141. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/search-filter/search-filter.component.ts +82 -0
  142. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/select-filter/select-filter.component.html +12 -0
  143. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/select-filter/select-filter.component.ts +65 -0
  144. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/text-filter/text-filter.component.html +12 -0
  145. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/filters/text-filter/text-filter.component.ts +90 -0
  146. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/object-breadcrumb/object-breadcrumb.component.html +55 -0
  147. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/object-breadcrumb/object-breadcrumb.component.ts +40 -0
  148. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/pagination-controls/pagination-controls.component.html +8 -0
  149. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/pagination-controls/pagination-controls.component.ts +61 -0
  150. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/search-bar/search-bar.component.html +59 -0
  151. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/search-bar/search-bar.component.ts +108 -0
  152. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/sort-control/sort-control.component.html +50 -0
  153. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/components/sort-control/sort-control.component.ts +72 -0
  154. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/object-search-state.service.ts +232 -0
  155. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/utils/debounce.ts +31 -0
  156. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/utils/field-utils.ts +54 -0
  157. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/utils/filter-utils.ts +354 -0
  158. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/utils/index.ts +12 -0
  159. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/features/object-search/utils/sort-utils.ts +46 -0
  160. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/account-detail/account-detail-page.component.html +174 -0
  161. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/account-detail/account-detail-page.component.scss +7 -0
  162. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/account-detail/account-detail-page.component.ts +199 -0
  163. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/account-search/account-search-page.component.html +111 -0
  164. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/account-search/account-search-page.component.ts +217 -0
  165. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/change-password/change-password-page.component.html +68 -0
  166. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/change-password/change-password-page.component.ts +82 -0
  167. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/forgot-password/forgot-password-page.component.html +35 -0
  168. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/forgot-password/forgot-password-page.component.ts +87 -0
  169. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/home/home-page.component.html +18 -0
  170. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/home/home-page.component.ts +47 -0
  171. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/home/home.component.html +6 -0
  172. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/home/home.component.spec.ts +23 -0
  173. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/home/home.component.ts +13 -0
  174. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/login/login-page.component.html +47 -0
  175. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/login/login-page.component.ts +89 -0
  176. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/not-found/not-found.component.html +12 -0
  177. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/not-found/not-found.component.spec.ts +33 -0
  178. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/not-found/not-found.component.ts +15 -0
  179. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/profile/profile-page.component.html +126 -0
  180. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/profile/profile-page.component.ts +194 -0
  181. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/register/register-page.component.html +80 -0
  182. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/register/register-page.component.ts +93 -0
  183. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/reset-password/reset-password-page.component.html +60 -0
  184. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/pages/reset-password/reset-password-page.component.ts +96 -0
  185. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/app/utils/async-data.ts +99 -0
  186. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/index.html +14 -0
  187. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/main.ts +5 -0
  188. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/styles.scss +170 -0
  189. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/theme.scss +39 -0
  190. package/dist/force-app/main/default/uiBundles/angularexternalapp/src/types/sf-globals.d.ts +9 -0
  191. package/dist/force-app/main/default/uiBundles/angularexternalapp/tsconfig.app.json +11 -0
  192. package/dist/force-app/main/default/uiBundles/angularexternalapp/tsconfig.json +33 -0
  193. package/dist/force-app/main/default/uiBundles/angularexternalapp/tsconfig.spec.json +10 -0
  194. package/dist/force-app/main/default/uiBundles/angularexternalapp/ui-bundle.json +7 -0
  195. package/dist/jest.config.js +6 -0
  196. package/dist/package-lock.json +10066 -0
  197. package/dist/package.json +46 -0
  198. package/dist/scripts/apex/hello.apex +10 -0
  199. package/dist/scripts/gitignore-templates.json +4 -0
  200. package/dist/scripts/graphql-search.sh +191 -0
  201. package/dist/scripts/org-setup-config-schema.mjs +103 -0
  202. package/dist/scripts/org-setup-dev.mjs +87 -0
  203. package/dist/scripts/org-setup-utils.mjs +369 -0
  204. package/dist/scripts/org-setup-xml.mjs +182 -0
  205. package/dist/scripts/org-setup.config.json +9 -0
  206. package/dist/scripts/org-setup.mjs +1702 -0
  207. package/dist/scripts/sf-project-setup.mjs +103 -0
  208. package/dist/scripts/soql/account.soql +6 -0
  209. package/dist/scripts/validate-org-setup-config.mjs +38 -0
  210. package/dist/sfdx-project.json +12 -0
  211. package/package.json +40 -0
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { Injectable, inject } from "@angular/core";
7
+ // DataClient is provided by the base-angular-app. Consumed via the
8
+ // `__inherit__` stub in this same folder (app/api/); post-compose patches-cli
9
+ // strips the prefix so it resolves to the seeded base file at
10
+ // app/api/data-client.service.ts.
11
+ import { DataClient } from "./data-client.service";
12
+ import { flattenGraphQLRecord } from "../features/authentication/utils/helpers";
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // Hand-written GraphQL query/mutation strings + wire types. Codegen is PARKED
16
+ // for the Angular port (same decision as object-search). The field selection,
17
+ // query/mutation shape, and variable structure mirror the React
18
+ // `userProfileApi.ts` byte-for-byte so behavior is identical.
19
+ // ---------------------------------------------------------------------------
20
+
21
+ const USER_PROFILE_FIELDS_FULL = `
22
+ Id
23
+ FirstName @optional { value }
24
+ LastName @optional { value }
25
+ Email @optional { value }
26
+ Phone @optional { value }
27
+ Street @optional { value }
28
+ City @optional { value }
29
+ State @optional { value }
30
+ PostalCode @optional { value }
31
+ Country @optional { value }`;
32
+
33
+ const USER_CONTACT_FIELDS = `
34
+ Id
35
+ ContactId @optional { value }`;
36
+
37
+ function getUserProfileQuery(fields: string): string {
38
+ return `
39
+ query GetUserProfile($userId: ID) {
40
+ uiapi {
41
+ query {
42
+ User(where: { Id: { eq: $userId } }) {
43
+ edges {
44
+ node {${fields}}
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }`;
50
+ }
51
+
52
+ function getUserProfileMutation(fields: string): string {
53
+ return `
54
+ mutation UpdateUserProfile($input: UserUpdateInput!) {
55
+ uiapi {
56
+ UserUpdate(input: $input) {
57
+ Record {${fields}}
58
+ }
59
+ }
60
+ }`;
61
+ }
62
+
63
+ /** Wire shape for the GetUserProfile query. */
64
+ interface GetUserProfileData {
65
+ uiapi: {
66
+ query: {
67
+ User: { edges: Array<{ node: Record<string, unknown> } | null> | null } | null;
68
+ };
69
+ };
70
+ }
71
+
72
+ /** Wire shape for the UpdateUserProfile mutation. */
73
+ interface UpdateUserProfileData {
74
+ uiapi: {
75
+ UserUpdate: { Record: Record<string, unknown> | null } | null;
76
+ };
77
+ }
78
+
79
+ /**
80
+ * Extensible user-profile fetching and updating via UI API GraphQL — the
81
+ * Angular port of the React `userProfileApi.ts` module.
82
+ *
83
+ * Uses the base app's `DataClient` (which centralizes GraphQL error handling
84
+ * and routes mutations vs queries), matching the object-search feature's
85
+ * data-access idiom. Responses are flattened via `flattenGraphQLRecord` for
86
+ * straightforward form binding.
87
+ */
88
+ @Injectable({ providedIn: "root" })
89
+ export class UserProfileService {
90
+ private readonly client = inject(DataClient);
91
+
92
+ /**
93
+ * Fetches the user profile via GraphQL and returns a flattened record.
94
+ * @param userId - The Salesforce User Id.
95
+ * @param fields - GraphQL field selection (defaults to the full profile).
96
+ */
97
+ async fetchUserProfile<T>(userId: string, fields: string = USER_PROFILE_FIELDS_FULL): Promise<T> {
98
+ const data = await this.client.execute<GetUserProfileData, { userId: string }>(
99
+ getUserProfileQuery(fields),
100
+ { userId },
101
+ );
102
+ return flattenGraphQLRecord<T>(data.uiapi?.query?.User?.edges?.[0]?.node);
103
+ }
104
+
105
+ /**
106
+ * Fetches the user's associated contact record ID via GraphQL and returns a
107
+ * flattened record.
108
+ * @param userId - The Salesforce User Id.
109
+ */
110
+ async fetchUserContact<T>(userId: string): Promise<T> {
111
+ return this.fetchUserProfile<T>(userId, USER_CONTACT_FIELDS);
112
+ }
113
+
114
+ /**
115
+ * Updates the user profile via GraphQL and returns the flattened updated record.
116
+ * @param userId - The Salesforce User Id.
117
+ * @param values - The field values to update.
118
+ */
119
+ async updateUserProfile<T>(userId: string, values: Record<string, unknown>): Promise<T> {
120
+ const data = await this.client.execute<UpdateUserProfileData, { input: unknown }>(
121
+ getUserProfileMutation(USER_PROFILE_FIELDS_FULL),
122
+ { input: { Id: userId, User: { ...values } } },
123
+ );
124
+ return flattenGraphQLRecord<T>(data.uiapi?.UserUpdate?.Record);
125
+ }
126
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
7
+ import { provideRouter } from '@angular/router';
8
+ import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
9
+ import { provideNativeDateAdapter } from '@angular/material/core';
10
+
11
+ import { routes } from './app.routes';
12
+
13
+ export const appConfig: ApplicationConfig = {
14
+ providers: [
15
+ provideBrowserGlobalErrorListeners(),
16
+ provideRouter(routes),
17
+ provideAnimationsAsync(),
18
+ // Enables mat-datepicker (used by the object-search Date / DateRange
19
+ // filters) with the browser's native Date, avoiding a moment/luxon dep.
20
+ provideNativeDateAdapter(),
21
+ ],
22
+ };
@@ -0,0 +1,77 @@
1
+ import { Routes } from '@angular/router';
2
+ import { NotFoundComponent } from './pages/not-found/not-found.component';
3
+ import { authGuard } from "./features/authentication/auth/auth.guard";
4
+ import { LoginPageComponent } from "./pages/login/login-page.component";
5
+ import { RegisterPageComponent } from "./pages/register/register-page.component";
6
+ import { ForgotPasswordPageComponent } from "./pages/forgot-password/forgot-password-page.component";
7
+ import { ResetPasswordPageComponent } from "./pages/reset-password/reset-password-page.component";
8
+ import { ProfilePageComponent } from "./pages/profile/profile-page.component";
9
+ import { ChangePasswordPageComponent } from "./pages/change-password/change-password-page.component";
10
+ import { AppLayoutComponent } from "./components/layout/app-layout/app-layout.component";
11
+ import { HomePageComponent } from "./pages/home/home-page.component";
12
+ import { AccountSearchPageComponent } from "./pages/account-search/account-search-page.component";
13
+ import { AccountDetailPageComponent } from "./pages/account-detail/account-detail-page.component";
14
+
15
+ export const routes: Routes = [
16
+ {
17
+ path: "",
18
+ component: AppLayoutComponent,
19
+ children: [
20
+ {
21
+ path: "",
22
+ component: HomePageComponent,
23
+ data: { showInNavigation: true, label: "Home" }
24
+ },
25
+ {
26
+ path: "login",
27
+ component: LoginPageComponent,
28
+ title: "Login | MyApp",
29
+ data: { showInNavigation: false, label: "Login" }
30
+ },
31
+ {
32
+ path: "register",
33
+ component: RegisterPageComponent,
34
+ title: "Create Account | MyApp",
35
+ data: { showInNavigation: false }
36
+ },
37
+ {
38
+ path: "forgot-password",
39
+ component: ForgotPasswordPageComponent,
40
+ title: "Recover Password | MyApp",
41
+ data: { showInNavigation: false }
42
+ },
43
+ {
44
+ path: "reset-password",
45
+ component: ResetPasswordPageComponent,
46
+ title: "Reset Password | MyApp",
47
+ data: { showInNavigation: false }
48
+ },
49
+ {
50
+ path: "profile",
51
+ component: ProfilePageComponent,
52
+ canActivate: [authGuard],
53
+ title: "My Profile | MyApp",
54
+ data: { showInNavigation: false, label: "Profile" }
55
+ },
56
+ {
57
+ path: "change-password",
58
+ component: ChangePasswordPageComponent,
59
+ canActivate: [authGuard],
60
+ title: "Change Password | MyApp",
61
+ data: { showInNavigation: false }
62
+ },
63
+ {
64
+ path: "accounts/:recordId",
65
+ component: AccountDetailPageComponent
66
+ },
67
+ {
68
+ path: "accounts",
69
+ component: AccountSearchPageComponent
70
+ },
71
+ {
72
+ path: '**',
73
+ component: NotFoundComponent
74
+ }
75
+ ]
76
+ }
77
+ ];
@@ -0,0 +1,18 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+ import { provideRouter } from '@angular/router';
3
+ import { App } from './app';
4
+
5
+ describe('App', () => {
6
+ beforeEach(async () => {
7
+ await TestBed.configureTestingModule({
8
+ imports: [App],
9
+ providers: [provideRouter([])],
10
+ }).compileComponents();
11
+ });
12
+
13
+ it('should create the app', () => {
14
+ const fixture = TestBed.createComponent(App);
15
+ const app = fixture.componentInstance;
16
+ expect(app).toBeTruthy();
17
+ });
18
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { ChangeDetectionStrategy, Component } from '@angular/core';
7
+ import { RouterOutlet } from '@angular/router';
8
+
9
+ @Component({
10
+ selector: 'app-root',
11
+ changeDetection: ChangeDetectionStrategy.OnPush,
12
+ imports: [RouterOutlet],
13
+ templateUrl: './app.html',
14
+ })
15
+ export class App {}
@@ -0,0 +1,53 @@
1
+ <nav class="bg-white border-b border-gray-200">
2
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
3
+ <div class="flex justify-between items-center h-16">
4
+ <a routerLink="/" class="text-xl font-semibold text-gray-900"> Angular App </a>
5
+ <div class="flex items-center gap-2">
6
+ <app-auth-menu />
7
+ <button
8
+ (click)="toggleMenu()"
9
+ class="p-2 rounded-md text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
10
+ aria-label="Toggle menu"
11
+ [attr.aria-expanded]="isOpen()"
12
+ >
13
+ <div class="w-6 h-6 flex flex-col justify-center space-y-1.5">
14
+ <span
15
+ class="block h-0.5 w-6 bg-current transition-all"
16
+ [class.rotate-45]="isOpen()"
17
+ [class.translate-y-2]="isOpen()"
18
+ ></span>
19
+ <span
20
+ class="block h-0.5 w-6 bg-current transition-all"
21
+ [class.opacity-0]="isOpen()"
22
+ ></span>
23
+ <span
24
+ class="block h-0.5 w-6 bg-current transition-all"
25
+ [class.-rotate-45]="isOpen()"
26
+ [class.-translate-y-2]="isOpen()"
27
+ ></span>
28
+ </div>
29
+ </button>
30
+ </div>
31
+ </div>
32
+ @if (isOpen()) {
33
+ <div class="pb-4">
34
+ <ul class="flex flex-col space-y-2 list-none">
35
+ @for (item of navigationItems(); track item.path) {
36
+ <li>
37
+ <a
38
+ [routerLink]="item.path"
39
+ routerLinkActive="bg-blue-100 text-blue-700"
40
+ [routerLinkActiveOptions]="{ exact: true }"
41
+ (click)="closeMenu()"
42
+ class="block px-3 py-2 rounded-md text-sm font-medium transition-colors text-gray-700 hover:bg-gray-100"
43
+ >
44
+ {{ item.label }}
45
+ </a>
46
+ </li>
47
+ }
48
+ </ul>
49
+ </div>
50
+ }
51
+ </div>
52
+ </nav>
53
+ <router-outlet />
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { Component } from "@angular/core";
7
+ import { TestBed } from "@angular/core/testing";
8
+ import { provideRouter } from "@angular/router";
9
+ import { AppLayoutComponent } from "./app-layout.component";
10
+ import { AuthMenuComponent } from "../../../features/authentication/menu/auth-menu/auth-menu.component";
11
+
12
+ // Stub the auth-menu so this layout test stays hermetic: the real
13
+ // `app-auth-menu` boots AuthService.checkAuth() (network + Cache API) on render,
14
+ // which is out of scope here and unavailable in the unit-test environment.
15
+ @Component({ selector: "app-auth-menu", template: "" })
16
+ class StubAuthMenuComponent {}
17
+
18
+ describe("AppLayoutComponent", () => {
19
+ beforeEach(async () => {
20
+ TestBed.configureTestingModule({
21
+ imports: [AppLayoutComponent],
22
+ providers: [
23
+ provideRouter([
24
+ {
25
+ path: "",
26
+ children: [
27
+ {
28
+ path: "accounts",
29
+ component: AppLayoutComponent,
30
+ data: { showInNavigation: true, label: "Accounts" },
31
+ },
32
+ ],
33
+ },
34
+ ]),
35
+ ],
36
+ });
37
+ TestBed.overrideComponent(AppLayoutComponent, {
38
+ remove: { imports: [AuthMenuComponent] },
39
+ add: { imports: [StubAuthMenuComponent] },
40
+ });
41
+ await TestBed.compileComponents();
42
+ });
43
+
44
+ it("should create the component", () => {
45
+ const fixture = TestBed.createComponent(AppLayoutComponent);
46
+ expect(fixture.componentInstance).toBeTruthy();
47
+ });
48
+
49
+ it("should toggle menu", () => {
50
+ const component = TestBed.createComponent(AppLayoutComponent).componentInstance;
51
+ expect(component.isOpen()).toBe(false);
52
+ component.toggleMenu();
53
+ expect(component.isOpen()).toBe(true);
54
+ component.toggleMenu();
55
+ expect(component.isOpen()).toBe(false);
56
+ });
57
+
58
+ it("should close menu", () => {
59
+ const component = TestBed.createComponent(AppLayoutComponent).componentInstance;
60
+ component.toggleMenu();
61
+ expect(component.isOpen()).toBe(true);
62
+ component.closeMenu();
63
+ expect(component.isOpen()).toBe(false);
64
+ });
65
+
66
+ it("should derive navigation items from the router config", () => {
67
+ const component = TestBed.createComponent(AppLayoutComponent).componentInstance;
68
+ const items = component.navigationItems();
69
+ expect(items.some((i) => i.path === "/accounts" && i.label === "Accounts")).toBe(true);
70
+ });
71
+
72
+ it("should render nav element", async () => {
73
+ const fixture = TestBed.createComponent(AppLayoutComponent);
74
+ await fixture.whenStable();
75
+ const compiled = fixture.nativeElement as HTMLElement;
76
+ expect(compiled.querySelector("nav")).toBeTruthy();
77
+ });
78
+
79
+ it("should set aria-expanded on toggle button", async () => {
80
+ const fixture = TestBed.createComponent(AppLayoutComponent);
81
+ await fixture.whenStable();
82
+ const button = (fixture.nativeElement as HTMLElement).querySelector("button");
83
+ expect(button?.getAttribute("aria-expanded")).toBe("false");
84
+
85
+ fixture.componentInstance.toggleMenu();
86
+ fixture.detectChanges();
87
+ expect(button?.getAttribute("aria-expanded")).toBe("true");
88
+ });
89
+ });
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { ChangeDetectionStrategy, Component, computed, inject, signal } from "@angular/core";
7
+ import { Router, RouterLink, RouterLinkActive, RouterOutlet, type Route } from "@angular/router";
8
+ import { AuthMenuComponent } from "../../../features/authentication/menu/auth-menu/auth-menu.component";
9
+
10
+ interface NavItem {
11
+ path: string;
12
+ label: string;
13
+ }
14
+
15
+ /**
16
+ * App-owned layout — overrides the base `app-layout` at compose (the app package
17
+ * ships its own copy, so patches-cli's "app wins" rule selects this one over the
18
+ * base-angular-app version). This is the Angular analogue of the React external
19
+ * app's own `appLayout.tsx`: the layout belongs to the PROJECT, not the base app
20
+ * or a feature. The auth feature's `AuthAppLayout` wrapper renders `<app-layout />`
21
+ * (via its `__inherit__app-layout` stub), which resolves to this component.
22
+ *
23
+ * Adds two things over the base layout:
24
+ * - `<app-auth-menu />` in the header (the auth feature's account dropdown),
25
+ * the parallel of the React app rendering `<AuthMenu />`.
26
+ * - Dynamic navigation derived from the router config at runtime — the Angular
27
+ * analogue of React's `getAllRoutes()` reading route `handle` metadata. Post
28
+ * compose the router config IS the merged base + feature routes, so nav items
29
+ * surface automatically for any route whose `data.showInNavigation` is true.
30
+ */
31
+ @Component({
32
+ selector: "app-layout",
33
+ changeDetection: ChangeDetectionStrategy.OnPush,
34
+ imports: [RouterOutlet, RouterLink, RouterLinkActive, AuthMenuComponent],
35
+ templateUrl: "./app-layout.component.html",
36
+ })
37
+ export class AppLayoutComponent {
38
+ private readonly router = inject(Router);
39
+
40
+ readonly isOpen = signal(false);
41
+
42
+ /**
43
+ * Flatten the router config and keep routes explicitly marked for navigation
44
+ * (`data.showInNavigation === true` with a `data.label`). Mirrors the React
45
+ * `getAllRoutes().filter(r => r.handle?.showInNavigation)` selection.
46
+ */
47
+ readonly navigationItems = computed<NavItem[]>(() =>
48
+ this.collectNavItems(this.router.config, ""),
49
+ );
50
+
51
+ private collectNavItems(routes: Route[], parentPath: string): NavItem[] {
52
+ const items: NavItem[] = [];
53
+ for (const route of routes) {
54
+ const segment = route.path ?? "";
55
+ const fullPath =
56
+ segment === ""
57
+ ? parentPath || "/"
58
+ : parentPath === "/" || parentPath === ""
59
+ ? `/${segment}`
60
+ : `${parentPath}/${segment}`;
61
+
62
+ const data = route.data as { showInNavigation?: boolean; label?: string } | undefined;
63
+ if (data?.showInNavigation === true && data.label) {
64
+ items.push({ path: fullPath, label: data.label });
65
+ }
66
+
67
+ if (route.children?.length) {
68
+ items.push(...this.collectNavItems(route.children, fullPath));
69
+ }
70
+ }
71
+ return items;
72
+ }
73
+
74
+ toggleMenu(): void {
75
+ this.isOpen.update((v) => !v);
76
+ }
77
+
78
+ closeMenu(): void {
79
+ this.isOpen.set(false);
80
+ }
81
+ }
@@ -0,0 +1,42 @@
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
+ * Shared height scale for the form-field wrappers (app-input, app-select,
9
+ * app-date-picker): sm = 24px, default = 32px, lg = 40px.
10
+ *
11
+ * Material's density scale only reaches 36px at its -5 floor, so these compact
12
+ * heights can't come from `mat.form-field-density`. Instead we set the two M3
13
+ * tokens that drive the height directly:
14
+ * --mat-form-field-container-height -> `.mat-mdc-form-field-flex` min-height
15
+ * --mat-form-field-container-vertical-padding -> infix padding-top / -bottom
16
+ *
17
+ * These are CSS custom properties, so setting them on the wrapper's own
18
+ * `mat-form-field` (an in-view element that matches under emulated
19
+ * encapsulation) is enough — they INHERIT down to Material's internal flex /
20
+ * infix elements. No `::ng-deep` and no global classes needed. This mirrors how
21
+ * `app-button` sizes work (it sets `--mat-button-*-container-height` tokens).
22
+ */
23
+ @mixin apply($height, $vertical-padding) {
24
+ --mat-form-field-container-height: #{$height};
25
+ --mat-form-field-container-vertical-padding: #{$vertical-padding};
26
+ }
27
+
28
+ /*
29
+ * Emit the three size classes. Consumers opt in via `size` on the wrapper,
30
+ * which renders `size-sm | size-default | size-lg` on the mat-form-field.
31
+ */
32
+ @mixin sizes {
33
+ .size-sm {
34
+ @include apply(1.5rem, 0.25rem); // 24px, 4px
35
+ }
36
+ .size-default {
37
+ @include apply(2rem, 0.5rem); // 32px, 8px
38
+ }
39
+ .size-lg {
40
+ @include apply(2.5rem, 0.75rem); // 40px, 12px
41
+ }
42
+ }
@@ -0,0 +1,31 @@
1
+ @if (icon()) {
2
+ <mat-icon class="row-span-2 translate-y-0.5 !size-4 !text-base leading-4" aria-hidden="true">{{
3
+ icon()
4
+ }}</mat-icon>
5
+ }
6
+
7
+ @if (title()) {
8
+ <div data-slot="alert-title" class="col-start-2 font-medium">{{ title() }}</div>
9
+ }
10
+ @if (description()) {
11
+ <div
12
+ data-slot="alert-description"
13
+ class="col-start-2 text-sm"
14
+ [class.text-muted-foreground]="variant() === 'default'"
15
+ [class.text-destructive]="variant() === 'destructive'"
16
+ >
17
+ {{ description() }}
18
+ </div>
19
+ }
20
+
21
+ <!--
22
+ Default slot for callers that project body content (e.g. app-status-alert
23
+ composing a message with a link) instead of the `description` input. Sits in
24
+ the second grid column to align with the icon. Inert when only inputs are used.
25
+ -->
26
+ <div class="col-start-2 text-sm">
27
+ <ng-content />
28
+ </div>
29
+
30
+ <!-- Optional caller-owned trailing control, pinned top-right. -->
31
+ <ng-content select="app-alert-action" />
@@ -0,0 +1,53 @@
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, input } from '@angular/core';
7
+ import { MatIconModule } from '@angular/material/icon';
8
+
9
+ /** Visual variant. */
10
+ export type AppAlertVariant = 'default' | 'destructive';
11
+
12
+ const BASE_CLASSES =
13
+ 'relative w-full grid grid-cols-[auto_1fr] items-start gap-x-2 gap-y-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-[app-alert-action]:pr-18';
14
+ const VARIANT_CLASSES: Record<AppAlertVariant, string> = {
15
+ default: 'bg-card text-card-foreground',
16
+ destructive: 'bg-card text-destructive',
17
+ };
18
+
19
+ /** Alert banner. Optional trailing control via the `app-alert-action` slot. */
20
+ @Component({
21
+ selector: 'app-alert',
22
+ changeDetection: ChangeDetectionStrategy.OnPush,
23
+ imports: [MatIconModule],
24
+ templateUrl: './alert.component.html',
25
+ host: {
26
+ 'data-slot': 'alert',
27
+ role: 'alert',
28
+ '[class]': 'hostClass()',
29
+ },
30
+ })
31
+ export class AlertComponent {
32
+ readonly variant = input<AppAlertVariant>('default');
33
+ readonly title = input<string>('');
34
+ readonly description = input<string>('');
35
+ /** Material icon ligature name, e.g. `info`, `error`, `warning`. */
36
+ readonly icon = input<string>('');
37
+
38
+ protected readonly hostClass = computed(
39
+ () => `${BASE_CLASSES} ${VARIANT_CLASSES[this.variant()]}`,
40
+ );
41
+ }
42
+
43
+ /** Trailing action slot for `app-alert`, pinned to the top-right. */
44
+ @Component({
45
+ selector: 'app-alert-action',
46
+ changeDetection: ChangeDetectionStrategy.OnPush,
47
+ template: '<ng-content />',
48
+ host: {
49
+ 'data-slot': 'alert-action',
50
+ class: 'absolute top-2 right-2',
51
+ },
52
+ })
53
+ export class AlertActionComponent {}
@@ -0,0 +1,18 @@
1
+ <button
2
+ [matButton]="matAppearance()"
3
+ [class]="buttonClass()"
4
+ [class.destructive]="isDestructive()"
5
+ [type]="type()"
6
+ [disabled]="disabled()"
7
+ [attr.aria-label]="ariaLabel()"
8
+ [attr.aria-expanded]="ariaExpanded()"
9
+ (click)="clicked.emit($event)"
10
+ >
11
+ @if (icon()) {
12
+ <mat-icon aria-hidden="true">{{ icon() }}</mat-icon>
13
+ }
14
+ <ng-content />
15
+ @if (iconEnd()) {
16
+ <mat-icon aria-hidden="true" iconPositionEnd>{{ iconEnd() }}</mat-icon>
17
+ }
18
+ </button>