@salesforce/ui-bundle-template-base-angular-app 11.60.0 → 11.62.1
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.
- package/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/src/force-app/main/default/uiBundles/base-angular-app/angular.json +2 -7
- package/src/force-app/main/default/uiBundles/base-angular-app/components.json +6 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/eslint.config.js +9 -1
- package/src/force-app/main/default/uiBundles/base-angular-app/package.json +16 -11
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/app.config.ts +4 -6
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/alert/alert.html +9 -13
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/alert/alert.ts +16 -28
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/button/button.html +19 -10
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/button/button.ts +34 -25
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/card/card.ts +40 -50
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/collapsible/collapsible.html +38 -10
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/collapsible/collapsible.ts +6 -11
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-picker/date-picker.html +17 -22
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-picker/date-picker.ts +29 -21
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-range-picker/date-range-picker.html +16 -30
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-range-picker/date-range-picker.ts +39 -36
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/dialog/dialog.html +13 -30
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/dialog/dialog.ts +6 -21
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/dropdown-menu/dropdown-menu.html +20 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/dropdown-menu/dropdown-menu.ts +100 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/field/field.html +5 -11
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/field/field.ts +10 -18
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/field-appearance.ts +8 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/icon/icon.ts +62 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/input/input.html +32 -17
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/input/input.ts +57 -14
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/label/label.ts +8 -4
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/paginator/paginator.html +74 -10
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/paginator/paginator.ts +74 -18
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/paginator/types.ts +13 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/popover/popover.html +10 -38
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/popover/popover.ts +12 -15
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/select/select.html +34 -22
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/select/select.ts +25 -34
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/separator/separator.ts +11 -36
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/skeleton/skeleton.ts +5 -9
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/spinner/spinner.ts +14 -21
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/alert/hlm-alert-action.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/alert/hlm-alert-description.ts +17 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/alert/hlm-alert-title.ts +17 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/alert/hlm-alert.ts +35 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/alert/index.ts +16 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/button/hlm-button.token.ts +22 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/button/hlm-button.ts +72 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/button/index.ts +6 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/calendar/hlm-calendar-multi.ts +195 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/calendar/hlm-calendar-range.ts +194 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/calendar/hlm-calendar.ts +189 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/calendar/hlm-month-year-calendar.ts +119 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/calendar/index.ts +16 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/card/hlm-card-action.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/card/hlm-card-avatar.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/card/hlm-card-content.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/card/hlm-card-description.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/card/hlm-card-footer.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/card/hlm-card-header.ts +15 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/card/hlm-card-title.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/card/hlm-card.token.ts +19 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/card/hlm-card.ts +22 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/card/index.ts +28 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/collapsible/hlm-collapsible-content.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/collapsible/hlm-collapsible-trigger.ts +9 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/collapsible/hlm-collapsible.ts +15 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/collapsible/index.ts +13 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-multi-input.ts +104 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-picker-anchor.ts +23 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-picker-input.ts +118 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-picker-multi.token.ts +109 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-picker-multi.ts +220 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-picker-trigger.ts +104 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-picker.token.ts +69 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-picker.ts +203 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-range-input.ts +120 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-range-picker.token.ts +86 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-date-range-picker.ts +252 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-month-year-input.ts +105 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-month-year-picker.token.ts +89 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/hlm-month-year-picker.ts +196 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/date-picker/index.ts +38 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog-close.ts +9 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog-content.ts +74 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog-description.ts +17 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog-footer.ts +15 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog-header.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog-overlay.ts +27 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog-portal.ts +8 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog-title.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog-trigger.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog.service.ts +46 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/hlm-dialog.ts +24 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dialog/index.ts +35 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-checkbox-indicator.ts +21 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-checkbox.ts +54 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-focus-on-hover.ts +35 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-group.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-item-sub-indicator.ts +19 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-item.ts +42 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-label.ts +20 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-radio-indicator.ts +21 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-radio.ts +49 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-separator.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-shortcut.ts +15 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-sub-trigger.ts +52 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-sub.ts +53 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-token.ts +26 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu-trigger.ts +46 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/hlm-dropdown-menu.ts +57 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/dropdown-menu/index.ts +49 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/hlm-field-content.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/hlm-field-description.ts +53 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/hlm-field-error.ts +100 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/hlm-field-group.ts +15 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/hlm-field-label.ts +17 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/hlm-field-legend.ts +19 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/hlm-field-separator.ts +24 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/hlm-field-set.ts +15 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/hlm-field-title.ts +15 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/hlm-field.ts +47 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/field/index.ts +34 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/input/hlm-input.ts +21 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/input/index.ts +5 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/input-group/hlm-input-group-addon.ts +40 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/input-group/hlm-input-group-button.ts +47 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/input-group/hlm-input-group-input.ts +17 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/input-group/hlm-input-group-text.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/input-group/hlm-input-group.ts +18 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/input-group/index.ts +19 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/label/hlm-label.ts +17 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/label/index.ts +5 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/label/label.html +11 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/pagination/hlm-numbered-pagination-query-params.ts +191 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/pagination/hlm-numbered-pagination.ts +290 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/pagination/hlm-pagination-content.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/pagination/hlm-pagination-ellipsis.ts +27 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/pagination/hlm-pagination-item.ts +7 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/pagination/hlm-pagination-link.ts +51 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/pagination/hlm-pagination-next.ts +65 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/pagination/hlm-pagination-previous.ts +65 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/pagination/hlm-pagination.ts +19 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/pagination/index.ts +31 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/popover/hlm-popover-content.ts +25 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/popover/hlm-popover-description.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/popover/hlm-popover-header.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/popover/hlm-popover-portal.ts +8 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/popover/hlm-popover-title.ts +12 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/popover/hlm-popover-trigger.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/popover/hlm-popover.ts +23 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/popover/index.ts +25 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-content.ts +44 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-group.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-item.ts +36 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-label.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-multiple.ts +37 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-placeholder.ts +17 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-portal.ts +8 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-scroll-down.ts +22 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-scroll-up.ts +22 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-separator.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-trigger.ts +59 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-value-template.ts +5 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-value.ts +18 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-values-content.ts +9 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select-values.ts +5 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/hlm-select.ts +37 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/select/index.ts +52 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/separator/hlm-separator.ts +19 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/separator/index.ts +5 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/skeleton/hlm-skeleton.ts +14 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/skeleton/index.ts +5 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spinner/hlm-spinner.ts +26 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/spinner/index.ts +5 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/utils/hlm.ts +313 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/utils/index.ts +2 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/utils/provide-spartan-hlm.ts +34 -0
- package/src/force-app/main/default/uiBundles/base-angular-app/src/index.html +0 -1
- package/src/force-app/main/default/uiBundles/base-angular-app/src/{styles.scss → styles.css} +7 -38
- package/src/force-app/main/default/uiBundles/base-angular-app/tsconfig.json +4 -1
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/_field-size.scss +0 -42
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/button/button.scss +0 -112
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/card/card.scss +0 -34
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-picker/date-picker.scss +0 -36
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/date-range-picker/date-range-picker.scss +0 -33
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/input/input.scss +0 -35
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/label/label.html +0 -3
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/select/select.scss +0 -35
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/separator/separator.html +0 -1
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/separator/separator.scss +0 -23
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/skeleton/skeleton.html +0 -1
- package/src/force-app/main/default/uiBundles/base-angular-app/src/app/components/ui/skeleton/skeleton.scss +0 -28
- 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
|
+
}
|
package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/input-group/index.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { HlmInputGroup } from './hlm-input-group';
|
|
2
|
+
import { HlmInputGroupAddon } from './hlm-input-group-addon';
|
|
3
|
+
import { HlmInputGroupButton } from './hlm-input-group-button';
|
|
4
|
+
import { HlmInputGroupInput } from './hlm-input-group-input';
|
|
5
|
+
import { HlmInputGroupText } from './hlm-input-group-text';
|
|
6
|
+
|
|
7
|
+
export * from './hlm-input-group';
|
|
8
|
+
export * from './hlm-input-group-addon';
|
|
9
|
+
export * from './hlm-input-group-button';
|
|
10
|
+
export * from './hlm-input-group-input';
|
|
11
|
+
export * from './hlm-input-group-text';
|
|
12
|
+
|
|
13
|
+
export const HlmInputGroupImports = [
|
|
14
|
+
HlmInputGroup,
|
|
15
|
+
HlmInputGroupAddon,
|
|
16
|
+
HlmInputGroupButton,
|
|
17
|
+
HlmInputGroupInput,
|
|
18
|
+
HlmInputGroupText,
|
|
19
|
+
] as const;
|
package/src/force-app/main/default/uiBundles/base-angular-app/src/app/shared/label/hlm-label.ts
ADDED
|
@@ -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,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,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
|
+
}
|