@salesforce/ui-bundle-template-feature-angular-language-switcher 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 (253) hide show
  1. package/LICENSE.txt +82 -0
  2. package/README.md +193 -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-language-switcher/.forceignore +15 -0
  12. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/.graphqlrc.yml +2 -0
  13. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/.postcssrc.json +5 -0
  14. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/.prettierignore +8 -0
  15. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/.prettierrc +12 -0
  16. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/CHANGELOG.md +4 -0
  17. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/README.md +85 -0
  18. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/angular.json +98 -0
  19. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/codegen.yml +95 -0
  20. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/components.json +6 -0
  21. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/e2e/app.spec.ts +15 -0
  22. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/esbuild/api-version.mjs +17 -0
  23. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/esbuild/graphql-codegen.mjs +13 -0
  24. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/eslint-plugin-angular-graphql.js +148 -0
  25. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/eslint.config.js +76 -0
  26. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/feature-angular-language-switcher.uibundle-meta.xml +7 -0
  27. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/middleware/html.mjs +3 -0
  28. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/middleware/proxy.mjs +12 -0
  29. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/package.json +69 -0
  30. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/playwright.config.ts +25 -0
  31. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/public/favicon.ico +0 -0
  32. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/scripts/get-graphql-schema.mjs +69 -0
  33. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/scripts/rewrite-e2e-assets.mjs +30 -0
  34. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/api/data-client.service.spec.ts +184 -0
  35. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/api/data-client.service.ts +74 -0
  36. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/app.config.ts +20 -0
  37. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/app.html +1 -0
  38. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/app.routes.ts +26 -0
  39. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/app.spec.ts +18 -0
  40. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/app.ts +15 -0
  41. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/layout/app-layout/app-layout.html +51 -0
  42. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/layout/app-layout/app-layout.spec.ts +63 -0
  43. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/layout/app-layout/app-layout.ts +27 -0
  44. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/alert/alert.html +27 -0
  45. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/alert/alert.ts +41 -0
  46. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/button/button.html +27 -0
  47. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/button/button.ts +66 -0
  48. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/card/card.ts +100 -0
  49. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/collapsible/collapsible.html +38 -0
  50. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/collapsible/collapsible.ts +21 -0
  51. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/date-picker/date-picker.html +20 -0
  52. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/date-picker/date-picker.ts +49 -0
  53. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/date-range-picker/date-range-picker.html +20 -0
  54. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/date-range-picker/date-range-picker.ts +69 -0
  55. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/dialog/dialog.html +20 -0
  56. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/dialog/dialog.ts +40 -0
  57. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/dropdown-menu/dropdown-menu.html +20 -0
  58. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/dropdown-menu/dropdown-menu.ts +100 -0
  59. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/field/field.html +15 -0
  60. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/field/field.ts +28 -0
  61. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/field-appearance.ts +8 -0
  62. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/field-size.ts +8 -0
  63. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/icon/icon.ts +68 -0
  64. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/input/input.html +34 -0
  65. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/input/input.ts +79 -0
  66. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/label/label.ts +21 -0
  67. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/paginator/paginator.html +74 -0
  68. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/paginator/paginator.ts +93 -0
  69. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/paginator/types.ts +13 -0
  70. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/popover/popover.html +13 -0
  71. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/popover/popover.ts +37 -0
  72. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/select/select.html +36 -0
  73. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/select/select.ts +63 -0
  74. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/separator/separator.ts +31 -0
  75. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/skeleton/skeleton.ts +20 -0
  76. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/components/ui/spinner/spinner.ts +28 -0
  77. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/features/language-switcher/__examples__/html-middleware-site-example.ts +41 -0
  78. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/features/language-switcher/__examples__/language-switcher-example.ts +41 -0
  79. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/features/language-switcher/build-language-url.ts +158 -0
  80. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/features/language-switcher/index.ts +28 -0
  81. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/features/language-switcher/language-switcher.html +22 -0
  82. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/features/language-switcher/language-switcher.ts +110 -0
  83. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/features/language-switcher/languages.ts +46 -0
  84. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/pages/home/home.html +6 -0
  85. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/pages/home/home.spec.ts +23 -0
  86. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/pages/home/home.ts +13 -0
  87. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/pages/not-found/not-found.html +12 -0
  88. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/pages/not-found/not-found.spec.ts +33 -0
  89. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/pages/not-found/not-found.ts +15 -0
  90. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/alert/hlm-alert-action.ts +14 -0
  91. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/alert/hlm-alert-description.ts +17 -0
  92. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/alert/hlm-alert-title.ts +17 -0
  93. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/alert/hlm-alert.ts +35 -0
  94. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/alert/index.ts +16 -0
  95. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/button/hlm-button.token.ts +22 -0
  96. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/button/hlm-button.ts +72 -0
  97. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/button/index.ts +6 -0
  98. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/calendar/hlm-calendar-multi.ts +195 -0
  99. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/calendar/hlm-calendar-range.ts +194 -0
  100. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/calendar/hlm-calendar.ts +189 -0
  101. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/calendar/hlm-month-year-calendar.ts +119 -0
  102. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/calendar/index.ts +16 -0
  103. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/card/hlm-card-action.ts +12 -0
  104. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/card/hlm-card-avatar.ts +14 -0
  105. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/card/hlm-card-content.ts +12 -0
  106. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/card/hlm-card-description.ts +12 -0
  107. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/card/hlm-card-footer.ts +12 -0
  108. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/card/hlm-card-header.ts +15 -0
  109. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/card/hlm-card-title.ts +12 -0
  110. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/card/hlm-card.token.ts +19 -0
  111. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/card/hlm-card.ts +22 -0
  112. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/card/index.ts +28 -0
  113. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/collapsible/hlm-collapsible-content.ts +14 -0
  114. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/collapsible/hlm-collapsible-trigger.ts +9 -0
  115. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/collapsible/hlm-collapsible.ts +15 -0
  116. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/collapsible/index.ts +13 -0
  117. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-multi-input.ts +104 -0
  118. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-picker-anchor.ts +23 -0
  119. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-picker-input.ts +118 -0
  120. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-picker-multi.token.ts +109 -0
  121. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-picker-multi.ts +220 -0
  122. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-picker-trigger.ts +104 -0
  123. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-picker.token.ts +69 -0
  124. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-picker.ts +203 -0
  125. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-range-input.ts +120 -0
  126. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-range-picker.token.ts +86 -0
  127. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-date-range-picker.ts +252 -0
  128. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-month-year-input.ts +105 -0
  129. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-month-year-picker.token.ts +89 -0
  130. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/hlm-month-year-picker.ts +196 -0
  131. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/date-picker/index.ts +38 -0
  132. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog-close.ts +9 -0
  133. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog-content.ts +74 -0
  134. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog-description.ts +17 -0
  135. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog-footer.ts +15 -0
  136. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog-header.ts +12 -0
  137. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog-overlay.ts +27 -0
  138. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog-portal.ts +8 -0
  139. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog-title.ts +14 -0
  140. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog-trigger.ts +14 -0
  141. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog.service.ts +46 -0
  142. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/hlm-dialog.ts +24 -0
  143. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dialog/index.ts +35 -0
  144. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-checkbox-indicator.ts +21 -0
  145. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-checkbox.ts +54 -0
  146. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-focus-on-hover.ts +35 -0
  147. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-group.ts +14 -0
  148. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-item-sub-indicator.ts +19 -0
  149. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-item.ts +42 -0
  150. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-label.ts +20 -0
  151. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-radio-indicator.ts +21 -0
  152. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-radio.ts +49 -0
  153. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-separator.ts +12 -0
  154. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-shortcut.ts +15 -0
  155. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-sub-trigger.ts +52 -0
  156. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-sub.ts +53 -0
  157. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-token.ts +26 -0
  158. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu-trigger.ts +46 -0
  159. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/hlm-dropdown-menu.ts +57 -0
  160. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/dropdown-menu/index.ts +49 -0
  161. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/hlm-field-content.ts +12 -0
  162. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/hlm-field-description.ts +53 -0
  163. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/hlm-field-error.ts +100 -0
  164. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/hlm-field-group.ts +15 -0
  165. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/hlm-field-label.ts +17 -0
  166. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/hlm-field-legend.ts +19 -0
  167. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/hlm-field-separator.ts +24 -0
  168. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/hlm-field-set.ts +15 -0
  169. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/hlm-field-title.ts +15 -0
  170. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/hlm-field.ts +47 -0
  171. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/field/index.ts +34 -0
  172. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/input/hlm-input.ts +21 -0
  173. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/input/index.ts +5 -0
  174. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/input-group/hlm-input-group-addon.ts +40 -0
  175. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/input-group/hlm-input-group-button.ts +47 -0
  176. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/input-group/hlm-input-group-input.ts +17 -0
  177. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/input-group/hlm-input-group-text.ts +14 -0
  178. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/input-group/hlm-input-group.ts +18 -0
  179. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/input-group/index.ts +19 -0
  180. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/label/hlm-label.ts +17 -0
  181. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/label/index.ts +5 -0
  182. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/label/label.html +11 -0
  183. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/pagination/hlm-numbered-pagination-query-params.ts +191 -0
  184. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/pagination/hlm-numbered-pagination.ts +290 -0
  185. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/pagination/hlm-pagination-content.ts +12 -0
  186. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/pagination/hlm-pagination-ellipsis.ts +27 -0
  187. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/pagination/hlm-pagination-item.ts +7 -0
  188. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/pagination/hlm-pagination-link.ts +51 -0
  189. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/pagination/hlm-pagination-next.ts +65 -0
  190. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/pagination/hlm-pagination-previous.ts +65 -0
  191. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/pagination/hlm-pagination.ts +19 -0
  192. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/pagination/index.ts +31 -0
  193. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/popover/hlm-popover-content.ts +25 -0
  194. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/popover/hlm-popover-description.ts +12 -0
  195. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/popover/hlm-popover-header.ts +12 -0
  196. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/popover/hlm-popover-portal.ts +8 -0
  197. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/popover/hlm-popover-title.ts +12 -0
  198. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/popover/hlm-popover-trigger.ts +14 -0
  199. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/popover/hlm-popover.ts +23 -0
  200. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/popover/index.ts +25 -0
  201. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-content.ts +44 -0
  202. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-group.ts +14 -0
  203. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-item.ts +36 -0
  204. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-label.ts +14 -0
  205. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-multiple.ts +37 -0
  206. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-placeholder.ts +17 -0
  207. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-portal.ts +8 -0
  208. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-scroll-down.ts +22 -0
  209. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-scroll-up.ts +22 -0
  210. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-separator.ts +14 -0
  211. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-trigger.ts +59 -0
  212. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-value-template.ts +5 -0
  213. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-value.ts +18 -0
  214. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-values-content.ts +9 -0
  215. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select-values.ts +5 -0
  216. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/hlm-select.ts +37 -0
  217. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/select/index.ts +52 -0
  218. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/separator/hlm-separator.ts +19 -0
  219. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/separator/index.ts +5 -0
  220. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/skeleton/hlm-skeleton.ts +14 -0
  221. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/skeleton/index.ts +5 -0
  222. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/spinner/hlm-spinner.ts +26 -0
  223. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/spinner/index.ts +5 -0
  224. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/utils/hlm.ts +313 -0
  225. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/utils/index.ts +2 -0
  226. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/shared/utils/provide-spartan-hlm.ts +34 -0
  227. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/app/utils/async-data.ts +99 -0
  228. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/index.html +13 -0
  229. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/main.ts +5 -0
  230. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/styles.css +139 -0
  231. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/src/types/sf-globals.d.ts +23 -0
  232. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/tsconfig.app.json +11 -0
  233. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/tsconfig.json +36 -0
  234. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/tsconfig.spec.json +10 -0
  235. package/dist/force-app/main/default/uiBundles/feature-angular-language-switcher/ui-bundle.json +7 -0
  236. package/dist/jest.config.js +6 -0
  237. package/dist/package-lock.json +12554 -0
  238. package/dist/package.json +46 -0
  239. package/dist/scripts/apex/hello.apex +10 -0
  240. package/dist/scripts/gitignore-templates.json +4 -0
  241. package/dist/scripts/graphql-search.sh +191 -0
  242. package/dist/scripts/org-setup-config-schema.mjs +132 -0
  243. package/dist/scripts/org-setup-dev.mjs +114 -0
  244. package/dist/scripts/org-setup-url.mjs +108 -0
  245. package/dist/scripts/org-setup-utils.mjs +569 -0
  246. package/dist/scripts/org-setup-xml.mjs +278 -0
  247. package/dist/scripts/org-setup.config.json +5 -0
  248. package/dist/scripts/org-setup.mjs +2537 -0
  249. package/dist/scripts/sf-project-setup.mjs +103 -0
  250. package/dist/scripts/soql/account.soql +6 -0
  251. package/dist/scripts/validate-org-setup-config.mjs +38 -0
  252. package/dist/sfdx-project.json +12 -0
  253. package/package.json +46 -0
@@ -0,0 +1,28 @@
1
+ import { HlmCard } from './hlm-card';
2
+ import { HlmCardAction } from './hlm-card-action';
3
+ import { HlmCardAvatar } from './hlm-card-avatar';
4
+ import { HlmCardContent } from './hlm-card-content';
5
+ import { HlmCardDescription } from './hlm-card-description';
6
+ import { HlmCardFooter } from './hlm-card-footer';
7
+ import { HlmCardHeader } from './hlm-card-header';
8
+ import { HlmCardTitle } from './hlm-card-title';
9
+
10
+ export * from './hlm-card';
11
+ export * from './hlm-card-action';
12
+ export * from './hlm-card-avatar';
13
+ export * from './hlm-card-content';
14
+ export * from './hlm-card-description';
15
+ export * from './hlm-card-footer';
16
+ export * from './hlm-card-header';
17
+ export * from './hlm-card-title';
18
+
19
+ export const HlmCardImports = [
20
+ HlmCard,
21
+ HlmCardAction,
22
+ HlmCardAvatar,
23
+ HlmCardContent,
24
+ HlmCardDescription,
25
+ HlmCardFooter,
26
+ HlmCardHeader,
27
+ HlmCardTitle,
28
+ ] as const;
@@ -0,0 +1,14 @@
1
+ import { Directive } from '@angular/core';
2
+ import { BrnCollapsibleContent } from '@spartan-ng/brain/collapsible';
3
+ import { classes } from '@spartan-ng/styles/utils';
4
+
5
+ @Directive({
6
+ selector: '[hlmCollapsibleContent],hlm-collapsible-content',
7
+ hostDirectives: [{ directive: BrnCollapsibleContent, inputs: ['id'] }],
8
+ host: { 'data-slot': 'collapsible-content' },
9
+ })
10
+ export class HlmCollapsibleContent {
11
+ constructor() {
12
+ classes(() => 'data-[state=closed]:hidden');
13
+ }
14
+ }
@@ -0,0 +1,9 @@
1
+ import { Directive } from '@angular/core';
2
+ import { BrnCollapsibleTrigger } from '@spartan-ng/brain/collapsible';
3
+
4
+ @Directive({
5
+ selector: 'button[hlmCollapsibleTrigger]',
6
+ hostDirectives: [{ directive: BrnCollapsibleTrigger, inputs: ['type'] }],
7
+ host: { 'data-slot': 'collapsible-trigger' },
8
+ })
9
+ export class HlmCollapsibleTrigger {}
@@ -0,0 +1,15 @@
1
+ import { Directive } from '@angular/core';
2
+ import { BrnCollapsible } from '@spartan-ng/brain/collapsible';
3
+
4
+ @Directive({
5
+ selector: '[hlmCollapsible],hlm-collapsible',
6
+ hostDirectives: [
7
+ {
8
+ directive: BrnCollapsible,
9
+ inputs: ['expanded', 'disabled'],
10
+ outputs: ['expandedChange'],
11
+ },
12
+ ],
13
+ host: { 'data-slot': 'collapsible' },
14
+ })
15
+ export class HlmCollapsible {}
@@ -0,0 +1,13 @@
1
+ import { HlmCollapsible } from './hlm-collapsible';
2
+ import { HlmCollapsibleContent } from './hlm-collapsible-content';
3
+ import { HlmCollapsibleTrigger } from './hlm-collapsible-trigger';
4
+
5
+ export * from './hlm-collapsible';
6
+ export * from './hlm-collapsible-content';
7
+ export * from './hlm-collapsible-trigger';
8
+
9
+ export const HlmCollapsibleImports = [
10
+ HlmCollapsible,
11
+ HlmCollapsibleContent,
12
+ HlmCollapsibleTrigger,
13
+ ] as const;
@@ -0,0 +1,104 @@
1
+ import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';
2
+ import { NgIcon, provideIcons } from '@ng-icons/core';
3
+ import { lucideCalendar, lucideX } from '@ng-icons/lucide';
4
+ import {
5
+ BrnDateInput,
6
+ type BrnDatePickerTriggerBase,
7
+ provideBrnDatePickerTrigger,
8
+ } from '@spartan-ng/brain/date-picker';
9
+ import { BrnFieldControl } from '@spartan-ng/brain/field';
10
+ import { HlmInputGroup, HlmInputGroupImports } from '@spartan-ng/styles/input-group';
11
+ import { injectHlmDatePickerMultiConfig } from './hlm-date-picker-multi.token';
12
+
13
+ @Component({
14
+ selector: 'hlm-date-multi-input',
15
+ imports: [HlmInputGroupImports, NgIcon],
16
+ providers: [
17
+ provideIcons({ lucideCalendar, lucideX }),
18
+ provideBrnDatePickerTrigger(HlmDateMultiInput),
19
+ ],
20
+ changeDetection: ChangeDetectionStrategy.OnPush,
21
+ hostDirectives: [HlmInputGroup],
22
+ template: `
23
+ <input
24
+ #input
25
+ hlmInputGroupInput
26
+ [value]="_inputValue()"
27
+ [id]="inputId()"
28
+ [placeholder]="placeholder()"
29
+ [disabled]="_disabled()"
30
+ [forceInvalid]="forceInvalid()"
31
+ [attr.aria-invalid]="_ariaInvalid()"
32
+ [attr.data-invalid]="_ariaInvalid()"
33
+ [attr.data-touched]="_touched?.() ? 'true' : null"
34
+ [attr.data-dirty]="_dirty?.() ? 'true' : null"
35
+ [attr.data-matches-spartan-invalid]="_spartanInvalid() ? 'true' : null"
36
+ (click)="_handleClick()"
37
+ (keydown.arrowDown)="_open()"
38
+ (keydown.enter)="_handleEnter($event)"
39
+ (input)="_handleInputChange($event)"
40
+ (focus)="_handleFocus()"
41
+ (blur)="_handleBlur()"
42
+ />
43
+ <hlm-input-group-addon align="inline-end">
44
+ @if (_showClearButton()) {
45
+ <button
46
+ hlmInputGroupButton
47
+ size="icon-xs"
48
+ variant="ghost"
49
+ [attr.aria-label]="clearAriaLabel()"
50
+ (click)="_clear()"
51
+ [disabled]="_disabled()"
52
+ >
53
+ <ng-icon name="lucideX" />
54
+ </button>
55
+ }
56
+ <button
57
+ hlmInputGroupButton
58
+ size="icon-xs"
59
+ [attr.aria-label]="calendarAriaLabel()"
60
+ (click)="_popover().open()"
61
+ [disabled]="_disabled()"
62
+ >
63
+ <ng-icon name="lucideCalendar" />
64
+ </button>
65
+ </hlm-input-group-addon>
66
+ `,
67
+ })
68
+ export class HlmDateMultiInput<T> extends BrnDateInput<T[]> implements BrnDatePickerTriggerBase {
69
+ private readonly _config = injectHlmDatePickerMultiConfig<T>();
70
+ private readonly _fieldControl = inject(BrnFieldControl, { optional: true });
71
+
72
+ private readonly _invalid = this._fieldControl?.invalid;
73
+ protected readonly _spartanInvalid = computed(
74
+ () => this.forceInvalid() || this._fieldControl?.spartanInvalid(),
75
+ );
76
+ protected readonly _dirty = this._fieldControl?.dirty;
77
+ protected readonly _touched = this._fieldControl?.touched;
78
+
79
+ protected readonly _ariaInvalid = computed(() => (this._invalid?.() ? 'true' : null));
80
+ /**
81
+ * Parses input text into dates. Return `null` for invalid input - the
82
+ * picker's dates are cleared while the text is preserved so the user can
83
+ * fix it.
84
+ *
85
+ * Defaults to `parseDate` from `HlmDatePickerMultiConfig`.
86
+ */
87
+ public readonly parseDate = input<(value: string) => T[] | null>(this._config.parseDate);
88
+
89
+ /**
90
+ * Formats the current dates into the input/edit format shown while the
91
+ * input is focused. On blur the picker's display format is restored.
92
+ *
93
+ * Defaults to `formatInputDates` from `HlmDatePickerMultiConfig`.
94
+ */
95
+ public readonly formatInputDates = input<(dates: T[]) => string>(this._config.formatInputDates);
96
+
97
+ protected override parseValue(value: string): T[] | null {
98
+ return this.parseDate()(value);
99
+ }
100
+
101
+ protected override formatInputValue(value: T[]): string {
102
+ return this.formatInputDates()(value);
103
+ }
104
+ }
@@ -0,0 +1,23 @@
1
+ import { Directive, effect, ElementRef, inject, input, linkedSignal } from '@angular/core';
2
+ import { BrnOverlay } from '@spartan-ng/brain/overlay';
3
+ import { BrnPopover } from '@spartan-ng/brain/popover';
4
+
5
+ @Directive({ selector: '[hlmDatePickerAnchor]' })
6
+ export class HlmDatePickerAnchor {
7
+ private readonly _host = inject(ElementRef, { host: true });
8
+ private readonly _brnOverlay = inject(BrnOverlay, { optional: true });
9
+
10
+ public readonly hlmDatePickerAnchorForInput = input<BrnPopover | undefined>(undefined, {
11
+ alias: 'hlmDatePickerAnchorFor',
12
+ });
13
+
14
+ public readonly hlmDatePickerAnchorFor = linkedSignal(this.hlmDatePickerAnchorForInput);
15
+
16
+ constructor() {
17
+ effect(() => {
18
+ this.hlmDatePickerAnchorFor()?.setOrigin(this._host.nativeElement);
19
+ });
20
+
21
+ this._brnOverlay?.setOrigin(this._host.nativeElement);
22
+ }
23
+ }
@@ -0,0 +1,118 @@
1
+ import {
2
+ booleanAttribute,
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ computed,
6
+ inject,
7
+ input,
8
+ } from '@angular/core';
9
+ import { NgIcon, provideIcons } from '@ng-icons/core';
10
+ import { lucideCalendar, lucideX } from '@ng-icons/lucide';
11
+ import {
12
+ BrnDateInput,
13
+ type BrnDatePickerTriggerBase,
14
+ provideBrnDatePickerTrigger,
15
+ } from '@spartan-ng/brain/date-picker';
16
+ import { BrnFieldControl } from '@spartan-ng/brain/field';
17
+ import type { BooleanInput } from '@angular/cdk/coercion';
18
+ import { HlmInputGroup, HlmInputGroupImports } from '@spartan-ng/styles/input-group';
19
+ import { injectHlmDatePickerConfig } from './hlm-date-picker.token';
20
+
21
+ @Component({
22
+ selector: 'hlm-date-picker-input',
23
+ imports: [HlmInputGroupImports, NgIcon],
24
+ providers: [
25
+ provideIcons({ lucideCalendar, lucideX }),
26
+ provideBrnDatePickerTrigger(HlmDatePickerInput),
27
+ ],
28
+ changeDetection: ChangeDetectionStrategy.OnPush,
29
+ hostDirectives: [HlmInputGroup],
30
+ template: `
31
+ <input
32
+ #input
33
+ hlmInputGroupInput
34
+ [value]="_inputValue()"
35
+ [id]="inputId()"
36
+ [placeholder]="placeholder()"
37
+ [disabled]="_disabled()"
38
+ [readonly]="readonly()"
39
+ [forceInvalid]="forceInvalid()"
40
+ [attr.aria-invalid]="_ariaInvalid()"
41
+ [attr.data-invalid]="_ariaInvalid()"
42
+ [attr.data-touched]="_touched?.() ? 'true' : null"
43
+ [attr.data-dirty]="_dirty?.() ? 'true' : null"
44
+ [attr.data-matches-spartan-invalid]="_spartanInvalid() ? 'true' : null"
45
+ (click)="_handleClick(); readonly() && _popover().open()"
46
+ (keydown.arrowDown)="_open()"
47
+ (keydown.enter)="_handleEnter($event); readonly() && _popover().open()"
48
+ (keydown.space)="readonly() && _popover().open()"
49
+ (input)="_handleInputChange($event)"
50
+ (focus)="_handleFocus()"
51
+ (blur)="_handleBlur()"
52
+ />
53
+ <hlm-input-group-addon align="inline-end">
54
+ @if (_showClearButton() && !readonly()) {
55
+ <button
56
+ hlmInputGroupButton
57
+ size="icon-xs"
58
+ variant="ghost"
59
+ [attr.aria-label]="clearAriaLabel()"
60
+ (click)="_clear()"
61
+ [disabled]="_disabled()"
62
+ >
63
+ <ng-icon name="lucideX" />
64
+ </button>
65
+ }
66
+ <button
67
+ hlmInputGroupButton
68
+ size="icon-xs"
69
+ [attr.aria-label]="calendarAriaLabel()"
70
+ (click)="_popover().open()"
71
+ [disabled]="_disabled()"
72
+ >
73
+ <ng-icon name="lucideCalendar" />
74
+ </button>
75
+ </hlm-input-group-addon>
76
+ `,
77
+ })
78
+ export class HlmDatePickerInput<T> extends BrnDateInput<T> implements BrnDatePickerTriggerBase {
79
+ private readonly _config = injectHlmDatePickerConfig<T>();
80
+ private readonly _fieldControl = inject(BrnFieldControl, { optional: true });
81
+
82
+ /** When true, typing is blocked but the calendar toggle still works. */
83
+ public readonly readonly = input<boolean, BooleanInput>(false, { transform: booleanAttribute });
84
+
85
+ private readonly _invalid = this._fieldControl?.invalid;
86
+ protected readonly _spartanInvalid = computed(
87
+ () => this.forceInvalid() || this._fieldControl?.spartanInvalid(),
88
+ );
89
+ protected readonly _dirty = this._fieldControl?.dirty;
90
+ protected readonly _touched = this._fieldControl?.touched;
91
+
92
+ protected readonly _ariaInvalid = computed(() => (this._invalid?.() ? 'true' : null));
93
+
94
+ /**
95
+ * Parses input text into a date value. Return `null` for invalid
96
+ * input - the picker's date is cleared while the text is preserved so
97
+ * the user can fix it.
98
+ *
99
+ * Defaults to `parseDate` from `HlmDatePickerConfig`.
100
+ */
101
+ public readonly parseDate = input<(value: string) => T | null>(this._config.parseDate);
102
+
103
+ /**
104
+ * Formats the current date into the input/edit format shown while the
105
+ * input is focused. On blur the picker's display format is restored.
106
+ *
107
+ * Defaults to `formatInputDate` from `HlmDatePickerConfig`.
108
+ */
109
+ public readonly formatInputDate = input<(date: T) => string>(this._config.formatInputDate);
110
+
111
+ protected parseValue(value: string): T | null {
112
+ return this.parseDate()(value);
113
+ }
114
+
115
+ protected formatInputValue(value: T): string {
116
+ return this.formatInputDate()(value);
117
+ }
118
+ }
@@ -0,0 +1,109 @@
1
+ import { inject, InjectionToken, type ValueProvider } from '@angular/core';
2
+
3
+ export interface HlmDatePickerMultiConfig<T> {
4
+ /**
5
+ * If true, the date picker will close when the max selection of dates is reached.
6
+ */
7
+ autoCloseOnMaxSelection: boolean;
8
+
9
+ /**
10
+ * Defines how the date should be displayed in the UI.
11
+ *
12
+ * @param dates
13
+ * @returns formatted date
14
+ */
15
+ formatDates: (dates: T[]) => string;
16
+
17
+ /**
18
+ * Defines how the dates should be displayed while the input is focused,
19
+ * i.e. the format the user is expected to type in.
20
+ *
21
+ * @param dates
22
+ * @returns formatted dates in the input/edit format
23
+ */
24
+ formatInputDates: (dates: T[]) => string;
25
+
26
+ /**
27
+ * Defines how the date should be transformed before saving to model/form.
28
+ *
29
+ * @param dates
30
+ * @returns transformed date
31
+ */
32
+ transformDates: (dates: T[]) => T[];
33
+
34
+ /**
35
+ * Parse a user-entered string into a date.
36
+ *
37
+ * @param value the raw string from the input
38
+ * @returns the parsed date, or `null` when the value can't be parsed
39
+ */
40
+ parseDate: (value: string) => T[] | null;
41
+ }
42
+
43
+ function getDefaultConfig<T>(): HlmDatePickerMultiConfig<T> {
44
+ return {
45
+ formatDates: (dates) =>
46
+ dates.map((date) => (date instanceof Date ? date.toDateString() : `${date}`)).join(', '),
47
+ formatInputDates: (dates) =>
48
+ dates
49
+ .map((date) => {
50
+ if (!(date instanceof Date)) return `${date}`;
51
+
52
+ const day = String(date.getDate()).padStart(2, '0');
53
+ const month = String(date.getMonth() + 1).padStart(2, '0');
54
+ const year = date.getFullYear();
55
+
56
+ return `${day}/${month}/${year}`;
57
+ })
58
+ .join(', '),
59
+ transformDates: (dates) => dates,
60
+ autoCloseOnMaxSelection: false,
61
+ parseDate: (value) => {
62
+ if (typeof value !== 'string') return null;
63
+
64
+ const parts = value.split(',').map((v) => v.trim());
65
+ const result: Date[] = [];
66
+
67
+ for (const part of parts) {
68
+ const match = part.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
69
+ if (!match) return null;
70
+
71
+ const day = Number(match[1]);
72
+ const month = Number(match[2]);
73
+ const year = Number(match[3]);
74
+
75
+ if (month < 1 || month > 12) return null;
76
+ if (day < 1 || day > 31) return null;
77
+
78
+ const date = new Date(year, month - 1, day);
79
+
80
+ if (
81
+ date.getFullYear() !== year ||
82
+ date.getMonth() !== month - 1 ||
83
+ date.getDate() !== day
84
+ ) {
85
+ return null;
86
+ }
87
+
88
+ result.push(date);
89
+ }
90
+
91
+ return result as T[];
92
+ },
93
+ };
94
+ }
95
+
96
+ const HlmDatePickerMultiConfigToken = new InjectionToken<HlmDatePickerMultiConfig<unknown>>(
97
+ 'HlmDatePickerMultiConfig',
98
+ );
99
+
100
+ export function provideHlmDatePickerMultiConfig<T>(
101
+ config: Partial<HlmDatePickerMultiConfig<T>>,
102
+ ): ValueProvider {
103
+ return { provide: HlmDatePickerMultiConfigToken, useValue: { ...getDefaultConfig(), ...config } };
104
+ }
105
+
106
+ export function injectHlmDatePickerMultiConfig<T>(): HlmDatePickerMultiConfig<T> {
107
+ const injectedConfig = inject(HlmDatePickerMultiConfigToken, { optional: true });
108
+ return injectedConfig ? (injectedConfig as HlmDatePickerMultiConfig<T>) : getDefaultConfig();
109
+ }
@@ -0,0 +1,220 @@
1
+ import type { BooleanInput, NumberInput } from '@angular/cdk/coercion';
2
+ import {
3
+ booleanAttribute,
4
+ ChangeDetectionStrategy,
5
+ Component,
6
+ computed,
7
+ contentChild,
8
+ forwardRef,
9
+ input,
10
+ linkedSignal,
11
+ numberAttribute,
12
+ output,
13
+ signal,
14
+ viewChild,
15
+ } from '@angular/core';
16
+ import { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
17
+ import {
18
+ type BrnDatePickerBase,
19
+ BrnDatePickerTriggerToken,
20
+ provideBrnDatePicker,
21
+ } from '@spartan-ng/brain/date-picker';
22
+ import { BrnFieldControl, provideBrnLabelable } from '@spartan-ng/brain/field';
23
+ import type { ChangeFn, TouchFn } from '@spartan-ng/brain/forms';
24
+ import type { BrnOverlayState } from '@spartan-ng/brain/overlay';
25
+ import { BrnPopover, type BrnPopoverAlign } from '@spartan-ng/brain/popover';
26
+ import { HlmCalendarMulti } from '@spartan-ng/styles/calendar';
27
+ import { HlmPopoverImports } from '@spartan-ng/styles/popover';
28
+ import { injectHlmDatePickerMultiConfig } from './hlm-date-picker-multi.token';
29
+
30
+ export const HLM_DATE_PICKER_MUTLI_VALUE_ACCESSOR = {
31
+ provide: NG_VALUE_ACCESSOR,
32
+ useExisting: forwardRef(() => HlmDatePickerMulti),
33
+ multi: true,
34
+ };
35
+
36
+ @Component({
37
+ selector: 'hlm-date-picker-multi',
38
+ imports: [HlmPopoverImports, HlmCalendarMulti],
39
+ providers: [
40
+ HLM_DATE_PICKER_MUTLI_VALUE_ACCESSOR,
41
+ provideBrnDatePicker(HlmDatePickerMulti),
42
+ provideBrnLabelable(HlmDatePickerMulti),
43
+ ],
44
+ changeDetection: ChangeDetectionStrategy.OnPush,
45
+ hostDirectives: [BrnFieldControl],
46
+ host: { class: 'block' },
47
+ template: `
48
+ <hlm-popover
49
+ [align]="align()"
50
+ sideOffset="5"
51
+ [state]="_popoverState()"
52
+ (stateChanged)="_onStateChange($event)"
53
+ >
54
+ <ng-content />
55
+
56
+ <hlm-popover-content class="w-fit p-0" *hlmPopoverPortal="let ctx">
57
+ <ng-content select="[hlmDatePickerHeader]" />
58
+ <hlm-calendar-multi
59
+ class="rounded-none border-0"
60
+ [date]="_mutableDate()"
61
+ [captionLayout]="captionLayout()"
62
+ [min]="minDate()"
63
+ [max]="maxDate()"
64
+ [minSelection]="minSelection()"
65
+ [maxSelection]="maxSelection()"
66
+ [disabled]="_disabled()"
67
+ (dateChange)="_handleChange($event)"
68
+ />
69
+ <ng-content select="[hlmDatePickerFooter]" />
70
+ </hlm-popover-content>
71
+ </hlm-popover>
72
+ `,
73
+ })
74
+ export class HlmDatePickerMulti<T> implements BrnDatePickerBase<T[]>, ControlValueAccessor {
75
+ private readonly _config = injectHlmDatePickerMultiConfig<T>();
76
+
77
+ public readonly popover = viewChild.required(BrnPopover);
78
+
79
+ private readonly _trigger = contentChild(BrnDatePickerTriggerToken);
80
+
81
+ public readonly align = input<BrnPopoverAlign>('center');
82
+
83
+ /** Show dropdowns to navigate between months or years. */
84
+ public readonly captionLayout = input<
85
+ 'dropdown' | 'label' | 'dropdown-months' | 'dropdown-years'
86
+ >('label');
87
+
88
+ /** The minimum date that can be selected.*/
89
+ public readonly minDate = input<T>();
90
+
91
+ /** The maximum date that can be selected. */
92
+ public readonly maxDate = input<T>();
93
+
94
+ /** The minimum selectable dates. */
95
+ public readonly minSelection = input<number, NumberInput>(undefined, {
96
+ transform: numberAttribute,
97
+ });
98
+
99
+ /** The maximum selectable dates. */
100
+ public readonly maxSelection = input<number, NumberInput>(undefined, {
101
+ transform: numberAttribute,
102
+ });
103
+
104
+ /** Determine if the date picker is disabled. */
105
+ public readonly disabled = input<boolean, BooleanInput>(false, {
106
+ transform: booleanAttribute,
107
+ });
108
+
109
+ /** The selected value. */
110
+ public readonly date = input<T[]>();
111
+
112
+ protected readonly _mutableDate = linkedSignal(this.date);
113
+
114
+ /** If true, the date picker will close when the max selection of dates is reached. */
115
+ public readonly autoCloseOnMaxSelection = input<boolean, BooleanInput>(
116
+ this._config.autoCloseOnMaxSelection,
117
+ {
118
+ transform: booleanAttribute,
119
+ },
120
+ );
121
+
122
+ /** Defines how the date should be displayed in the UI. */
123
+ public readonly formatDates = input<(date: T[]) => string>(this._config.formatDates);
124
+
125
+ /** Defines how the date should be transformed before saving to model/form. */
126
+ public readonly transformDates = input<(date: T[]) => T[]>(this._config.transformDates);
127
+
128
+ protected readonly _popoverState = signal<BrnOverlayState | null>(null);
129
+
130
+ protected readonly _disabled = linkedSignal(this.disabled);
131
+
132
+ /** @internal The disabled state as a readonly signal */
133
+ public readonly disabledState = this._disabled.asReadonly();
134
+
135
+ public readonly formattedDate = computed(() => {
136
+ const dates = this._mutableDate();
137
+ return dates ? this.formatDates()(dates) : undefined;
138
+ });
139
+
140
+ public readonly dateChange = output<T[]>();
141
+
142
+ public readonly labelableId = computed(() => this._trigger()?.triggerId());
143
+
144
+ public readonly hasDate = computed(() => !!this._mutableDate()?.length);
145
+
146
+ /** @internal The current raw value, used by inputs to reformat on focus. */
147
+ public readonly value = computed(() => this._mutableDate() ?? null);
148
+
149
+ protected _onChange?: ChangeFn<T[]>;
150
+ protected _onTouched?: TouchFn;
151
+
152
+ protected _onStateChange(state: BrnOverlayState) {
153
+ this._popoverState.set(state);
154
+ if (state === 'closed') this._onTouched?.();
155
+ }
156
+
157
+ protected _handleChange(value: T[] | undefined) {
158
+ if (value === undefined) return;
159
+
160
+ if (this._disabled()) return;
161
+ const transformedDate = value !== undefined ? this.transformDates()(value) : value;
162
+
163
+ this._mutableDate.set(transformedDate);
164
+ this._onChange?.(transformedDate);
165
+ this.dateChange.emit(transformedDate);
166
+
167
+ if (this.autoCloseOnMaxSelection() && this._mutableDate()?.length === this.maxSelection()) {
168
+ this._popoverState.set('closed');
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Commit dates to the picker. Updates the internal model, notifies form
174
+ * controls, and emits `dateChange`. Intended to be called from a text input
175
+ * that parses user-entered values. Pass `null` to clear the selection.
176
+ */
177
+ public updateDate(value: T[] | null) {
178
+ if (this._disabled()) return;
179
+ const transformedDate = value ? this.transformDates()(value) : undefined;
180
+
181
+ this._mutableDate.set(transformedDate);
182
+ this._onChange?.(transformedDate ?? []);
183
+ this.dateChange.emit(transformedDate ?? []);
184
+ }
185
+
186
+ public touched(): void {
187
+ this._onTouched?.();
188
+ }
189
+
190
+ /** CONTROL VALUE ACCESSOR */
191
+ public writeValue(value: T[] | null): void {
192
+ this._mutableDate.set(value ? this.transformDates()(value) : undefined);
193
+ }
194
+
195
+ public registerOnChange(fn: ChangeFn<T[]>): void {
196
+ this._onChange = fn;
197
+ }
198
+
199
+ public registerOnTouched(fn: TouchFn): void {
200
+ this._onTouched = fn;
201
+ }
202
+
203
+ public setDisabledState(isDisabled: boolean): void {
204
+ this._disabled.set(isDisabled);
205
+ }
206
+
207
+ public open() {
208
+ this._popoverState.set('open');
209
+ }
210
+
211
+ public close() {
212
+ this._popoverState.set('closed');
213
+ }
214
+
215
+ public reset() {
216
+ this._mutableDate.set(undefined);
217
+ this._onChange?.([]);
218
+ this.dateChange.emit([]);
219
+ }
220
+ }