@salesforce/ui-bundle-template-base-angular-app 11.60.0 → 11.62.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 (192) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/package.json +1 -1
  3. package/src/force-app/main/default/uiBundles/base-angular-app/angular.json +2 -7
  4. package/src/force-app/main/default/uiBundles/base-angular-app/components.json +6 -0
  5. package/src/force-app/main/default/uiBundles/base-angular-app/eslint.config.js +9 -1
  6. package/src/force-app/main/default/uiBundles/base-angular-app/package.json +16 -11
  7. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/app.config.ts +4 -6
  8. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/alert/alert.html +9 -13
  9. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/alert/alert.ts +16 -28
  10. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/button/button.html +19 -10
  11. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/button/button.ts +34 -25
  12. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/card/card.ts +40 -50
  13. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/collapsible/collapsible.html +38 -10
  14. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/collapsible/collapsible.ts +6 -11
  15. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-picker/date-picker.html +17 -22
  16. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-picker/date-picker.ts +29 -21
  17. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-range-picker/date-range-picker.html +16 -30
  18. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-range-picker/date-range-picker.ts +39 -36
  19. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/dialog/dialog.html +13 -30
  20. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/dialog/dialog.ts +6 -21
  21. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/dropdown-menu/dropdown-menu.html +20 -0
  22. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/dropdown-menu/dropdown-menu.ts +100 -0
  23. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/field/field.html +5 -11
  24. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/field/field.ts +10 -18
  25. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/field-appearance.ts +8 -0
  26. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/icon/icon.ts +62 -0
  27. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/input/input.html +32 -17
  28. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/input/input.ts +57 -14
  29. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/label/label.ts +8 -4
  30. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/paginator/paginator.html +74 -10
  31. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/paginator/paginator.ts +74 -18
  32. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/paginator/types.ts +13 -0
  33. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/popover/popover.html +10 -38
  34. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/popover/popover.ts +12 -15
  35. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/select/select.html +34 -22
  36. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/select/select.ts +25 -34
  37. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/separator/separator.ts +11 -36
  38. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/skeleton/skeleton.ts +5 -9
  39. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/spinner/spinner.ts +14 -21
  40. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/alert/src/index.ts +16 -0
  41. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/alert/src/lib/hlm-alert-action.ts +14 -0
  42. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/alert/src/lib/hlm-alert-description.ts +17 -0
  43. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/alert/src/lib/hlm-alert-title.ts +17 -0
  44. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/alert/src/lib/hlm-alert.ts +35 -0
  45. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/button/src/index.ts +6 -0
  46. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/button/src/lib/hlm-button.token.ts +22 -0
  47. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/button/src/lib/hlm-button.ts +72 -0
  48. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/calendar/src/index.ts +16 -0
  49. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/calendar/src/lib/hlm-calendar-multi.ts +195 -0
  50. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/calendar/src/lib/hlm-calendar-range.ts +194 -0
  51. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/calendar/src/lib/hlm-calendar.ts +189 -0
  52. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/calendar/src/lib/hlm-month-year-calendar.ts +119 -0
  53. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/card/src/index.ts +28 -0
  54. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/card/src/lib/hlm-card-action.ts +12 -0
  55. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/card/src/lib/hlm-card-avatar.ts +14 -0
  56. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/card/src/lib/hlm-card-content.ts +12 -0
  57. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/card/src/lib/hlm-card-description.ts +12 -0
  58. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/card/src/lib/hlm-card-footer.ts +12 -0
  59. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/card/src/lib/hlm-card-header.ts +15 -0
  60. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/card/src/lib/hlm-card-title.ts +12 -0
  61. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/card/src/lib/hlm-card.token.ts +19 -0
  62. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/card/src/lib/hlm-card.ts +22 -0
  63. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/collapsible/src/index.ts +13 -0
  64. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/collapsible/src/lib/hlm-collapsible-content.ts +14 -0
  65. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/collapsible/src/lib/hlm-collapsible-trigger.ts +9 -0
  66. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/collapsible/src/lib/hlm-collapsible.ts +15 -0
  67. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/index.ts +38 -0
  68. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-multi-input.ts +104 -0
  69. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-picker-anchor.ts +23 -0
  70. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-picker-input.ts +118 -0
  71. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-picker-multi.token.ts +109 -0
  72. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-picker-multi.ts +220 -0
  73. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-picker-trigger.ts +104 -0
  74. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-picker.token.ts +69 -0
  75. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-picker.ts +203 -0
  76. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-range-input.ts +120 -0
  77. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-range-picker.token.ts +86 -0
  78. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-date-range-picker.ts +252 -0
  79. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-month-year-input.ts +105 -0
  80. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-month-year-picker.token.ts +89 -0
  81. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/date-picker/src/lib/hlm-month-year-picker.ts +196 -0
  82. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/index.ts +35 -0
  83. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog-close.ts +9 -0
  84. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog-content.ts +74 -0
  85. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog-description.ts +17 -0
  86. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog-footer.ts +15 -0
  87. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog-header.ts +12 -0
  88. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog-overlay.ts +27 -0
  89. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog-portal.ts +8 -0
  90. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog-title.ts +14 -0
  91. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog-trigger.ts +14 -0
  92. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog.service.ts +46 -0
  93. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dialog/src/lib/hlm-dialog.ts +24 -0
  94. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/index.ts +49 -0
  95. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-checkbox-indicator.ts +21 -0
  96. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-checkbox.ts +54 -0
  97. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-focus-on-hover.ts +35 -0
  98. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-group.ts +14 -0
  99. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-item-sub-indicator.ts +19 -0
  100. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-item.ts +42 -0
  101. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-label.ts +20 -0
  102. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-radio-indicator.ts +21 -0
  103. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-radio.ts +49 -0
  104. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-separator.ts +12 -0
  105. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-shortcut.ts +15 -0
  106. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-sub-trigger.ts +52 -0
  107. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-sub.ts +53 -0
  108. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-token.ts +26 -0
  109. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu-trigger.ts +46 -0
  110. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/dropdown-menu/src/lib/hlm-dropdown-menu.ts +57 -0
  111. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/index.ts +34 -0
  112. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/lib/hlm-field-content.ts +12 -0
  113. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/lib/hlm-field-description.ts +53 -0
  114. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/lib/hlm-field-error.ts +100 -0
  115. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/lib/hlm-field-group.ts +15 -0
  116. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/lib/hlm-field-label.ts +17 -0
  117. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/lib/hlm-field-legend.ts +19 -0
  118. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/lib/hlm-field-separator.ts +24 -0
  119. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/lib/hlm-field-set.ts +15 -0
  120. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/lib/hlm-field-title.ts +15 -0
  121. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/field/src/lib/hlm-field.ts +47 -0
  122. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/input/src/index.ts +5 -0
  123. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/input/src/lib/hlm-input.ts +21 -0
  124. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/input-group/src/index.ts +19 -0
  125. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/input-group/src/lib/hlm-input-group-addon.ts +40 -0
  126. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/input-group/src/lib/hlm-input-group-button.ts +47 -0
  127. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/input-group/src/lib/hlm-input-group-input.ts +17 -0
  128. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/input-group/src/lib/hlm-input-group-text.ts +14 -0
  129. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/input-group/src/lib/hlm-input-group.ts +18 -0
  130. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/label/label.html +11 -0
  131. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/label/src/index.ts +5 -0
  132. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/label/src/lib/hlm-label.ts +17 -0
  133. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/pagination/src/index.ts +31 -0
  134. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/pagination/src/lib/hlm-numbered-pagination-query-params.ts +191 -0
  135. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/pagination/src/lib/hlm-numbered-pagination.ts +290 -0
  136. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/pagination/src/lib/hlm-pagination-content.ts +12 -0
  137. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/pagination/src/lib/hlm-pagination-ellipsis.ts +27 -0
  138. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/pagination/src/lib/hlm-pagination-item.ts +7 -0
  139. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/pagination/src/lib/hlm-pagination-link.ts +51 -0
  140. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/pagination/src/lib/hlm-pagination-next.ts +65 -0
  141. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/pagination/src/lib/hlm-pagination-previous.ts +65 -0
  142. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/pagination/src/lib/hlm-pagination.ts +19 -0
  143. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/popover/src/index.ts +25 -0
  144. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/popover/src/lib/hlm-popover-content.ts +25 -0
  145. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/popover/src/lib/hlm-popover-description.ts +12 -0
  146. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/popover/src/lib/hlm-popover-header.ts +12 -0
  147. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/popover/src/lib/hlm-popover-portal.ts +8 -0
  148. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/popover/src/lib/hlm-popover-title.ts +12 -0
  149. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/popover/src/lib/hlm-popover-trigger.ts +14 -0
  150. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/popover/src/lib/hlm-popover.ts +23 -0
  151. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/index.ts +52 -0
  152. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-content.ts +44 -0
  153. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-group.ts +14 -0
  154. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-item.ts +36 -0
  155. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-label.ts +14 -0
  156. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-multiple.ts +37 -0
  157. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-placeholder.ts +17 -0
  158. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-portal.ts +8 -0
  159. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-scroll-down.ts +22 -0
  160. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-scroll-up.ts +22 -0
  161. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-separator.ts +14 -0
  162. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-trigger.ts +59 -0
  163. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-value-template.ts +5 -0
  164. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-value.ts +18 -0
  165. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-values-content.ts +9 -0
  166. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select-values.ts +5 -0
  167. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/select/src/lib/hlm-select.ts +37 -0
  168. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/separator/src/index.ts +5 -0
  169. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/separator/src/lib/hlm-separator.ts +19 -0
  170. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/skeleton/src/index.ts +5 -0
  171. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/skeleton/src/lib/hlm-skeleton.ts +14 -0
  172. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/spinner/src/index.ts +5 -0
  173. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/spinner/src/lib/hlm-spinner.ts +26 -0
  174. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/utils/src/index.ts +2 -0
  175. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/utils/src/lib/hlm.ts +313 -0
  176. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spartan/utils/src/lib/provide-spartan-hlm.ts +34 -0
  177. package/src/force-app/main/default/uiBundles/base-angular-app/src/index.html +0 -1
  178. package/src/force-app/main/default/uiBundles/base-angular-app/src/{styles.scss → styles.css} +7 -38
  179. package/src/force-app/main/default/uiBundles/base-angular-app/tsconfig.json +4 -1
  180. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/_field-size.scss +0 -42
  181. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/button/button.scss +0 -112
  182. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/card/card.scss +0 -34
  183. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-picker/date-picker.scss +0 -36
  184. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-range-picker/date-range-picker.scss +0 -33
  185. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/input/input.scss +0 -35
  186. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/label/label.html +0 -3
  187. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/select/select.scss +0 -35
  188. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/separator/separator.html +0 -1
  189. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/separator/separator.scss +0 -23
  190. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/skeleton/skeleton.html +0 -1
  191. package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/skeleton/skeleton.scss +0 -28
  192. package/src/force-app/main/default/uiBundles/base-angular-app/src/theme.scss +0 -39
@@ -0,0 +1,40 @@
1
+ import { Directive, input } from '@angular/core';
2
+ import { classes } from '@spartan-ng/styles/utils';
3
+ import { cva, type VariantProps } from 'class-variance-authority';
4
+
5
+ const inputGroupAddonVariants = cva(
6
+ "text-muted-foreground h-auto gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>ng-icon:not([class*='text-'])]:text-[length:--spacing(4)] flex cursor-text items-center justify-center select-none",
7
+ {
8
+ variants: {
9
+ align: {
10
+ 'inline-start': 'ps-2 has-[>button]:ms-[-0.3rem] has-[>kbd]:ms-[-0.15rem] order-first',
11
+ 'inline-end': 'pe-2 has-[>button]:me-[-0.3rem] has-[>kbd]:me-[-0.15rem] order-last',
12
+ 'block-start':
13
+ 'px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2 order-first w-full justify-start',
14
+ 'block-end':
15
+ 'px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2 order-last w-full justify-start',
16
+ },
17
+ },
18
+ defaultVariants: {
19
+ align: 'inline-start',
20
+ },
21
+ },
22
+ );
23
+
24
+ type InputGroupAddonVariants = VariantProps<typeof inputGroupAddonVariants>;
25
+
26
+ @Directive({
27
+ selector: '[hlmInputGroupAddon],hlm-input-group-addon',
28
+ host: {
29
+ role: 'group',
30
+ 'data-slot': 'input-group-addon',
31
+ '[attr.data-align]': 'align()',
32
+ },
33
+ })
34
+ export class HlmInputGroupAddon {
35
+ public readonly align = input<InputGroupAddonVariants['align']>('inline-start');
36
+
37
+ constructor() {
38
+ classes(() => inputGroupAddonVariants({ align: this.align() }));
39
+ }
40
+ }
@@ -0,0 +1,47 @@
1
+ import { Directive, input } from '@angular/core';
2
+ import { HlmButton, provideBrnButtonConfig } from '@spartan-ng/styles/button';
3
+ import { classes } from '@spartan-ng/styles/utils';
4
+ import { cva, type VariantProps } from 'class-variance-authority';
5
+
6
+ const inputGroupButtonVariants = cva('gap-2 text-sm flex items-center shadow-none', {
7
+ variants: {
8
+ size: {
9
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>ng-icon:not([class*='text-'])]:text-[length:--spacing(3.5)]",
10
+ sm: '',
11
+ 'icon-xs': 'size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>ng-icon]:p-0',
12
+ 'icon-sm': 'size-8 p-0 has-[>ng-icon]:p-0',
13
+ },
14
+ },
15
+ defaultVariants: {
16
+ size: 'xs',
17
+ },
18
+ });
19
+
20
+ type InputGroupButtonVariants = VariantProps<typeof inputGroupButtonVariants>;
21
+
22
+ @Directive({
23
+ selector: 'button[hlmInputGroupButton]',
24
+ providers: [
25
+ provideBrnButtonConfig({
26
+ variant: 'ghost',
27
+ }),
28
+ ],
29
+ hostDirectives: [
30
+ {
31
+ directive: HlmButton,
32
+ inputs: ['variant'],
33
+ },
34
+ ],
35
+ host: {
36
+ '[attr.data-size]': 'size()',
37
+ '[type]': 'type()',
38
+ },
39
+ })
40
+ export class HlmInputGroupButton {
41
+ public readonly size = input<InputGroupButtonVariants['size']>('xs');
42
+ public readonly type = input<'button' | 'submit' | 'reset'>('button');
43
+
44
+ constructor() {
45
+ classes(() => inputGroupButtonVariants({ size: this.size() }));
46
+ }
47
+ }
@@ -0,0 +1,17 @@
1
+ import { Directive } from '@angular/core';
2
+ import { HlmInput } from '@spartan-ng/styles/input';
3
+ import { classes } from '@spartan-ng/styles/utils';
4
+
5
+ @Directive({
6
+ selector: 'input[hlmInputGroupInput]',
7
+ hostDirectives: [HlmInput],
8
+ host: { 'data-slot': 'input-group-control' },
9
+ })
10
+ export class HlmInputGroupInput {
11
+ constructor() {
12
+ classes(
13
+ () =>
14
+ 'rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent data-[matches-spartan-invalid=true]:ring-0 dark:bg-transparent dark:disabled:bg-transparent flex-1',
15
+ );
16
+ }
17
+ }
@@ -0,0 +1,14 @@
1
+ import { Directive } from '@angular/core';
2
+ import { classes } from '@spartan-ng/styles/utils';
3
+
4
+ @Directive({
5
+ selector: '[hlmInputGroupText],hlm-input-group-text',
6
+ })
7
+ export class HlmInputGroupText {
8
+ constructor() {
9
+ classes(
10
+ () =>
11
+ "text-muted-foreground gap-2 text-sm [&_ng-icon:not([class*='text-'])]:text-[length:--spacing(4)] flex items-center [&_ng-icon]:pointer-events-none",
12
+ );
13
+ }
14
+ }
@@ -0,0 +1,18 @@
1
+ import { Directive } from '@angular/core';
2
+ import { classes } from '@spartan-ng/styles/utils';
3
+
4
+ @Directive({
5
+ selector: '[hlmInputGroup],hlm-input-group',
6
+ host: {
7
+ 'data-slot': 'input-group',
8
+ role: 'group',
9
+ },
10
+ })
11
+ export class HlmInputGroup {
12
+ constructor() {
13
+ classes(
14
+ () =>
15
+ 'border-input dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][data-matches-spartan-invalid=true]]:ring-destructive/20 has-[[data-slot][data-matches-spartan-invalid=true]]:border-destructive dark:has-[[data-slot][data-matches-spartan-invalid=true]]:ring-destructive/40 has-[[data-slot=input-group-control]:disabled]:bg-input/50 dark:has-[[data-slot=input-group-control]:disabled]:bg-input/80 h-8 rounded-lg border transition-colors in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-[[data-slot=input-group-control]:disabled]:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][data-matches-spartan-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pe-1.5 has-[>[data-align=inline-start]]:[&>input]:ps-1.5 group/input-group relative flex w-full min-w-0 items-center outline-none has-[>textarea]:h-auto',
16
+ );
17
+ }
18
+ }
@@ -0,0 +1,11 @@
1
+ <!-- Label: Spartan Helm demo — mirrors ui/label/label.html usage -->
2
+ <div class="space-y-6 p-4">
3
+ <div class="space-y-2">
4
+ <label hlmLabel for="hlm-demo-input-1">Default Label</label>
5
+ <input id="hlm-demo-input-1" type="text" class="border rounded px-2 py-1 text-sm" />
6
+ </div>
7
+
8
+ <div class="space-y-2">
9
+ <label hlmLabel>Label without for</label>
10
+ </div>
11
+ </div>
@@ -0,0 +1,5 @@
1
+ import { HlmLabel } from './lib/hlm-label';
2
+
3
+ export * from './lib/hlm-label';
4
+
5
+ export const HlmLabelImports = [HlmLabel] as const;
@@ -0,0 +1,17 @@
1
+ import { Directive } from '@angular/core';
2
+ import { BrnLabel } from '@spartan-ng/brain/label';
3
+ import { classes } from '@spartan-ng/styles/utils';
4
+
5
+ @Directive({
6
+ selector: '[hlmLabel]',
7
+ hostDirectives: [{ directive: BrnLabel, inputs: ['id', 'for'] }],
8
+ host: { 'data-slot': 'label' },
9
+ })
10
+ export class HlmLabel {
11
+ constructor() {
12
+ classes(
13
+ () =>
14
+ 'gap-2 text-sm leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed',
15
+ );
16
+ }
17
+ }
@@ -0,0 +1,31 @@
1
+ import { HlmNumberedPagination } from './lib/hlm-numbered-pagination';
2
+ import { HlmNumberedPaginationQueryParams } from './lib/hlm-numbered-pagination-query-params';
3
+ import { HlmPagination } from './lib/hlm-pagination';
4
+ import { HlmPaginationContent } from './lib/hlm-pagination-content';
5
+ import { HlmPaginationEllipsis } from './lib/hlm-pagination-ellipsis';
6
+ import { HlmPaginationItem } from './lib/hlm-pagination-item';
7
+ import { HlmPaginationLink } from './lib/hlm-pagination-link';
8
+ import { HlmPaginationNext } from './lib/hlm-pagination-next';
9
+ import { HlmPaginationPrevious } from './lib/hlm-pagination-previous';
10
+
11
+ export * from './lib/hlm-numbered-pagination';
12
+ export * from './lib/hlm-numbered-pagination-query-params';
13
+ export * from './lib/hlm-pagination';
14
+ export * from './lib/hlm-pagination-content';
15
+ export * from './lib/hlm-pagination-ellipsis';
16
+ export * from './lib/hlm-pagination-item';
17
+ export * from './lib/hlm-pagination-link';
18
+ export * from './lib/hlm-pagination-next';
19
+ export * from './lib/hlm-pagination-previous';
20
+
21
+ export const HlmPaginationImports = [
22
+ HlmPagination,
23
+ HlmPaginationContent,
24
+ HlmPaginationItem,
25
+ HlmPaginationLink,
26
+ HlmPaginationPrevious,
27
+ HlmPaginationNext,
28
+ HlmPaginationEllipsis,
29
+ HlmNumberedPagination,
30
+ HlmNumberedPaginationQueryParams,
31
+ ] as const;
@@ -0,0 +1,191 @@
1
+ import type { BooleanInput, NumberInput } from '@angular/cdk/coercion';
2
+ import {
3
+ booleanAttribute,
4
+ ChangeDetectionStrategy,
5
+ Component,
6
+ computed,
7
+ input,
8
+ model,
9
+ numberAttribute,
10
+ untracked,
11
+ } from '@angular/core';
12
+ import { HlmSelectImports } from '@spartan-ng/styles/select';
13
+ import { classes } from '@spartan-ng/styles/utils';
14
+ import { createPageArray, outOfBoundCorrection } from './hlm-numbered-pagination';
15
+ import { HlmPagination } from './hlm-pagination';
16
+ import { HlmPaginationContent } from './hlm-pagination-content';
17
+ import { HlmPaginationEllipsis } from './hlm-pagination-ellipsis';
18
+ import { HlmPaginationItem } from './hlm-pagination-item';
19
+ import { HlmPaginationLink } from './hlm-pagination-link';
20
+ import { HlmPaginationNext } from './hlm-pagination-next';
21
+ import { HlmPaginationPrevious } from './hlm-pagination-previous';
22
+
23
+ @Component({
24
+ selector: 'hlm-numbered-pagination-query-params',
25
+ imports: [
26
+ HlmPagination,
27
+ HlmPaginationContent,
28
+ HlmPaginationItem,
29
+ HlmPaginationPrevious,
30
+ HlmPaginationNext,
31
+ HlmPaginationLink,
32
+ HlmPaginationEllipsis,
33
+ HlmSelectImports,
34
+ ],
35
+ changeDetection: ChangeDetectionStrategy.OnPush,
36
+ template: `
37
+ <div class="flex items-center gap-1 text-sm text-nowrap text-gray-600">
38
+ <b>{{ totalItems() }}</b>
39
+ total items |
40
+ <b>{{ _lastPageNumber() }}</b>
41
+ pages
42
+ </div>
43
+
44
+ <nav hlmPagination>
45
+ <ul hlmPaginationContent>
46
+ @if (showEdges() && !_isFirstPageActive()) {
47
+ <li hlmPaginationItem>
48
+ <hlm-pagination-previous
49
+ [link]="link()"
50
+ [queryParams]="{ page: currentPage() - 1 }"
51
+ queryParamsHandling="merge"
52
+ />
53
+ </li>
54
+ }
55
+
56
+ @for (page of _pages(); track page) {
57
+ <li hlmPaginationItem>
58
+ @if (page === '...') {
59
+ <hlm-pagination-ellipsis />
60
+ } @else {
61
+ <a
62
+ hlmPaginationLink
63
+ [link]="currentPage() !== page ? link() : undefined"
64
+ [queryParams]="{ page }"
65
+ queryParamsHandling="merge"
66
+ [isActive]="currentPage() === page"
67
+ >
68
+ {{ page }}
69
+ </a>
70
+ }
71
+ </li>
72
+ }
73
+
74
+ @if (showEdges() && !_isLastPageActive()) {
75
+ <li hlmPaginationItem>
76
+ <hlm-pagination-next
77
+ [link]="link()"
78
+ [queryParams]="{ page: currentPage() + 1 }"
79
+ queryParamsHandling="merge"
80
+ />
81
+ </li>
82
+ }
83
+ </ul>
84
+ </nav>
85
+
86
+ <!-- Show Page Size selector -->
87
+ <hlm-select [(value)]="itemsPerPage" class="ml-auto">
88
+ <hlm-select-trigger class="w-fit">
89
+ <hlm-select-value />
90
+ </hlm-select-trigger>
91
+ <hlm-select-content *hlmSelectPortal>
92
+ <hlm-select-group>
93
+ @for (pageSize of _pageSizesWithCurrent(); track pageSize) {
94
+ <hlm-select-item [value]="pageSize">{{ pageSize }}</hlm-select-item>
95
+ }
96
+ </hlm-select-group>
97
+ </hlm-select-content>
98
+ </hlm-select>
99
+ `,
100
+ })
101
+ export class HlmNumberedPaginationQueryParams {
102
+ /**
103
+ * The current (active) page.
104
+ */
105
+ public readonly currentPage = model.required<number>();
106
+
107
+ /**
108
+ * The number of items per paginated page.
109
+ */
110
+ public readonly itemsPerPage = model.required<number>();
111
+
112
+ /**
113
+ * The total number of items in the collection. Only useful when
114
+ * doing server-side paging, where the collection size is limited
115
+ * to a single page returned by the server API.
116
+ */
117
+ public readonly totalItems = input.required<number, NumberInput>({
118
+ transform: numberAttribute,
119
+ });
120
+
121
+ /**
122
+ * The URL path to use for the pagination links.
123
+ * Defaults to '.' (current path).
124
+ */
125
+ public readonly link = input<string>('.');
126
+
127
+ /**
128
+ * The number of page links to show.
129
+ */
130
+ public readonly maxSize = input<number, NumberInput>(7, {
131
+ transform: numberAttribute,
132
+ });
133
+
134
+ /**
135
+ * Show the first and last page buttons.
136
+ */
137
+ public readonly showEdges = input<boolean, BooleanInput>(true, {
138
+ transform: booleanAttribute,
139
+ });
140
+
141
+ /**
142
+ * The page sizes to show.
143
+ * Defaults to [10, 20, 50, 100]
144
+ */
145
+ public readonly pageSizes = input<number[]>([10, 20, 50, 100]);
146
+
147
+ protected readonly _pageSizesWithCurrent = computed(() => {
148
+ const pageSizes = this.pageSizes();
149
+ return pageSizes.includes(this.itemsPerPage())
150
+ ? pageSizes // if current page size is included, return the same array
151
+ : [...pageSizes, this.itemsPerPage()].sort((a, b) => a - b); // otherwise, add current page size and sort the array
152
+ });
153
+
154
+ protected readonly _isFirstPageActive = computed(() => this.currentPage() === 1);
155
+ protected readonly _isLastPageActive = computed(
156
+ () => this.currentPage() === this._lastPageNumber(),
157
+ );
158
+
159
+ protected readonly _lastPageNumber = computed(() => {
160
+ if (this.totalItems() < 1) {
161
+ // when there are 0 or fewer (an error case) items, there are no "pages" as such,
162
+ // but it makes sense to consider a single, empty page as the last page.
163
+ return 1;
164
+ }
165
+ return Math.ceil(this.totalItems() / this.itemsPerPage());
166
+ });
167
+
168
+ protected readonly _pages = computed(() => {
169
+ const correctedCurrentPage = outOfBoundCorrection(
170
+ this.totalItems(),
171
+ this.itemsPerPage(),
172
+ this.currentPage(),
173
+ );
174
+
175
+ if (correctedCurrentPage !== this.currentPage()) {
176
+ // update the current page
177
+ untracked(() => this.currentPage.set(correctedCurrentPage));
178
+ }
179
+
180
+ return createPageArray(
181
+ correctedCurrentPage,
182
+ this.itemsPerPage(),
183
+ this.totalItems(),
184
+ this.maxSize(),
185
+ );
186
+ });
187
+
188
+ constructor() {
189
+ classes(() => 'flex items-center justify-between gap-2 px-4 py-2');
190
+ }
191
+ }
@@ -0,0 +1,290 @@
1
+ import type { BooleanInput, NumberInput } from '@angular/cdk/coercion';
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ booleanAttribute,
6
+ computed,
7
+ input,
8
+ model,
9
+ numberAttribute,
10
+ untracked,
11
+ } from '@angular/core';
12
+ import { HlmSelectImports } from '@spartan-ng/styles/select';
13
+ import { HlmPagination } from './hlm-pagination';
14
+ import { HlmPaginationContent } from './hlm-pagination-content';
15
+ import { HlmPaginationEllipsis } from './hlm-pagination-ellipsis';
16
+ import { HlmPaginationItem } from './hlm-pagination-item';
17
+ import { HlmPaginationLink } from './hlm-pagination-link';
18
+ import { HlmPaginationNext } from './hlm-pagination-next';
19
+ import { HlmPaginationPrevious } from './hlm-pagination-previous';
20
+
21
+ @Component({
22
+ selector: 'hlm-numbered-pagination',
23
+ imports: [
24
+ HlmPagination,
25
+ HlmPaginationContent,
26
+ HlmPaginationItem,
27
+ HlmPaginationPrevious,
28
+ HlmPaginationNext,
29
+ HlmPaginationLink,
30
+ HlmPaginationEllipsis,
31
+ HlmSelectImports,
32
+ ],
33
+ changeDetection: ChangeDetectionStrategy.OnPush,
34
+ template: `
35
+ <div class="flex items-center justify-between gap-2 px-4 py-2">
36
+ <div class="flex items-center gap-1 text-sm text-nowrap text-gray-600">
37
+ <b>{{ totalItems() }}</b>
38
+ total items |
39
+ <b>{{ _lastPageNumber() }}</b>
40
+ pages
41
+ </div>
42
+
43
+ <nav hlmPagination>
44
+ <ul hlmPaginationContent>
45
+ @if (showEdges() && !_isFirstPageActive()) {
46
+ <li hlmPaginationItem (click)="goToPrevious()">
47
+ <hlm-pagination-previous />
48
+ </li>
49
+ }
50
+
51
+ @for (page of _pages(); track page) {
52
+ <li hlmPaginationItem>
53
+ @if (page === '...') {
54
+ <hlm-pagination-ellipsis />
55
+ } @else {
56
+ <a
57
+ hlmPaginationLink
58
+ [isActive]="currentPage() === page"
59
+ (click)="currentPage.set(page)"
60
+ >
61
+ {{ page }}
62
+ </a>
63
+ }
64
+ </li>
65
+ }
66
+
67
+ @if (showEdges() && !_isLastPageActive()) {
68
+ <li hlmPaginationItem (click)="goToNext()">
69
+ <hlm-pagination-next />
70
+ </li>
71
+ }
72
+ </ul>
73
+ </nav>
74
+
75
+ <!-- Show Page Size selector -->
76
+ <hlm-select [(value)]="itemsPerPage" class="ml-auto">
77
+ <hlm-select-trigger class="w-fit">
78
+ <hlm-select-value />
79
+ </hlm-select-trigger>
80
+ <hlm-select-content *hlmSelectPortal>
81
+ <hlm-select-group>
82
+ @for (pageSize of _pageSizesWithCurrent(); track pageSize) {
83
+ <hlm-select-item [value]="pageSize">{{ pageSize }}</hlm-select-item>
84
+ }
85
+ </hlm-select-group>
86
+ </hlm-select-content>
87
+ </hlm-select>
88
+ </div>
89
+ `,
90
+ })
91
+ export class HlmNumberedPagination {
92
+ /**
93
+ * The current (active) page.
94
+ */
95
+ public readonly currentPage = model.required<number>();
96
+
97
+ /**
98
+ * The number of items per paginated page.
99
+ */
100
+ public readonly itemsPerPage = model.required<number>();
101
+
102
+ /**
103
+ * The total number of items in the collection. Only useful when
104
+ * doing server-side paging, where the collection size is limited
105
+ * to a single page returned by the server API.
106
+ */
107
+ public readonly totalItems = input.required<number, NumberInput>({
108
+ transform: numberAttribute,
109
+ });
110
+
111
+ /**
112
+ * The number of page links to show.
113
+ */
114
+ public readonly maxSize = input<number, NumberInput>(7, {
115
+ transform: numberAttribute,
116
+ });
117
+
118
+ /**
119
+ * Show the first and last page buttons.
120
+ */
121
+ public readonly showEdges = input<boolean, BooleanInput>(true, {
122
+ transform: booleanAttribute,
123
+ });
124
+
125
+ /**
126
+ * The page sizes to show.
127
+ * Defaults to [10, 20, 50, 100]
128
+ */
129
+ public readonly pageSizes = input<number[]>([10, 20, 50, 100]);
130
+
131
+ protected readonly _pageSizesWithCurrent = computed(() => {
132
+ const pageSizes = this.pageSizes();
133
+ return pageSizes.includes(this.itemsPerPage())
134
+ ? pageSizes // if current page size is included, return the same array
135
+ : [...pageSizes, this.itemsPerPage()].sort((a, b) => a - b); // otherwise, add current page size and sort the array
136
+ });
137
+
138
+ protected readonly _isFirstPageActive = computed(() => this.currentPage() === 1);
139
+ protected readonly _isLastPageActive = computed(
140
+ () => this.currentPage() === this._lastPageNumber(),
141
+ );
142
+
143
+ protected readonly _lastPageNumber = computed(() => {
144
+ if (this.totalItems() < 1) {
145
+ // when there are 0 or fewer (an error case) items, there are no "pages" as such,
146
+ // but it makes sense to consider a single, empty page as the last page.
147
+ return 1;
148
+ }
149
+ return Math.ceil(this.totalItems() / this.itemsPerPage());
150
+ });
151
+
152
+ protected readonly _pages = computed(() => {
153
+ const correctedCurrentPage = outOfBoundCorrection(
154
+ this.totalItems(),
155
+ this.itemsPerPage(),
156
+ this.currentPage(),
157
+ );
158
+
159
+ if (correctedCurrentPage !== this.currentPage()) {
160
+ // update the current page
161
+ untracked(() => this.currentPage.set(correctedCurrentPage));
162
+ }
163
+
164
+ return createPageArray(
165
+ correctedCurrentPage,
166
+ this.itemsPerPage(),
167
+ this.totalItems(),
168
+ this.maxSize(),
169
+ );
170
+ });
171
+
172
+ protected goToPrevious(): void {
173
+ this.currentPage.set(this.currentPage() - 1);
174
+ }
175
+
176
+ protected goToNext(): void {
177
+ this.currentPage.set(this.currentPage() + 1);
178
+ }
179
+
180
+ protected goToFirst(): void {
181
+ this.currentPage.set(1);
182
+ }
183
+
184
+ protected goToLast(): void {
185
+ this.currentPage.set(this._lastPageNumber());
186
+ }
187
+ }
188
+
189
+ type Page = number | '...';
190
+
191
+ /**
192
+ * Checks that the instance.currentPage property is within bounds for the current page range.
193
+ * If not, return a correct value for currentPage, or the current value if OK.
194
+ *
195
+ * Copied from 'ngx-pagination' package
196
+ */
197
+ export function outOfBoundCorrection(
198
+ totalItems: number,
199
+ itemsPerPage: number,
200
+ currentPage: number,
201
+ ): number {
202
+ const totalPages = Math.ceil(totalItems / itemsPerPage);
203
+ if (totalPages < currentPage && 0 < totalPages) {
204
+ return totalPages;
205
+ }
206
+
207
+ if (currentPage < 1) {
208
+ return 1;
209
+ }
210
+
211
+ return currentPage;
212
+ }
213
+
214
+ /**
215
+ * Returns an array of Page objects to use in the pagination controls.
216
+ *
217
+ * Copied from 'ngx-pagination' package
218
+ */
219
+ export function createPageArray(
220
+ currentPage: number,
221
+ itemsPerPage: number,
222
+ totalItems: number,
223
+ paginationRange: number,
224
+ ): Page[] {
225
+ // paginationRange could be a string if passed from attribute, so cast to number.
226
+ paginationRange = +paginationRange;
227
+ const pages: Page[] = [];
228
+
229
+ // Return 1 as default page number
230
+ // Make sense to show 1 instead of empty when there are no items
231
+ const totalPages = Math.max(Math.ceil(totalItems / itemsPerPage), 1);
232
+ const halfWay = Math.ceil(paginationRange / 2);
233
+
234
+ const isStart = currentPage <= halfWay;
235
+ const isEnd = totalPages - halfWay < currentPage;
236
+ const isMiddle = !isStart && !isEnd;
237
+
238
+ const ellipsesNeeded = paginationRange < totalPages;
239
+ let i = 1;
240
+
241
+ while (i <= totalPages && i <= paginationRange) {
242
+ let label: number | '...';
243
+ const pageNumber = calculatePageNumber(i, currentPage, paginationRange, totalPages);
244
+ const openingEllipsesNeeded = i === 2 && (isMiddle || isEnd);
245
+ const closingEllipsesNeeded = i === paginationRange - 1 && (isMiddle || isStart);
246
+ if (ellipsesNeeded && (openingEllipsesNeeded || closingEllipsesNeeded)) {
247
+ label = '...';
248
+ } else {
249
+ label = pageNumber;
250
+ }
251
+ pages.push(label);
252
+ i++;
253
+ }
254
+
255
+ return pages;
256
+ }
257
+
258
+ /**
259
+ * Given the position in the sequence of pagination links [i],
260
+ * figure out what page number corresponds to that position.
261
+ *
262
+ * Copied from 'ngx-pagination' package
263
+ */
264
+ function calculatePageNumber(
265
+ i: number,
266
+ currentPage: number,
267
+ paginationRange: number,
268
+ totalPages: number,
269
+ ) {
270
+ const halfWay = Math.ceil(paginationRange / 2);
271
+ if (i === paginationRange) {
272
+ return totalPages;
273
+ }
274
+
275
+ if (i === 1) {
276
+ return i;
277
+ }
278
+
279
+ if (paginationRange < totalPages) {
280
+ if (totalPages - halfWay < currentPage) {
281
+ return totalPages - paginationRange + i;
282
+ }
283
+ if (halfWay < currentPage) {
284
+ return currentPage - halfWay + i;
285
+ }
286
+ return i;
287
+ }
288
+
289
+ return i;
290
+ }