@hmcts/opal-frontend-common 0.0.101 → 0.0.103

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 (126) hide show
  1. package/fesm2022/{hmcts-opal-frontend-common-access-denied.component-BDPx9bHD.mjs → hmcts-opal-frontend-common-access-denied.component-BxhkCLOI.mjs} +4 -4
  2. package/fesm2022/{hmcts-opal-frontend-common-account-created.component-Bnx53kTU.mjs → hmcts-opal-frontend-common-account-created.component-CJiRndGj.mjs} +4 -4
  3. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-account-summary-base.mjs +3 -3
  4. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-creditor-details-base.mjs +3 -3
  5. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-form-alias-base.mjs +3 -3
  6. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-form-array-base.mjs +3 -3
  7. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-form-array-removal-base.mjs +3 -3
  8. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-form-base.mjs +3 -3
  9. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-nested-form-base.mjs +3 -3
  10. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-report-instances-table-base.mjs +3 -3
  11. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-report-summary-list-base.mjs +3 -3
  12. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-sortable-table-pagination.mjs +49 -7
  13. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-sortable-table.mjs +4 -4
  14. package/fesm2022/hmcts-opal-frontend-common-components-abstract-abstract-table-filter.mjs +3 -3
  15. package/fesm2022/hmcts-opal-frontend-common-components-alphagov-alphagov-accessible-autocomplete.mjs +3 -3
  16. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-accessible-monetary.mjs +3 -3
  17. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-account-information-custom-account-information-item-custom-account-information-item-label.mjs +3 -3
  18. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-account-information-custom-account-information-item-custom-account-information-item-value.mjs +3 -3
  19. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-account-information-custom-account-information-item.mjs +3 -3
  20. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-account-information.mjs +3 -3
  21. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-action-links.mjs +3 -3
  22. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-horizontal-scroll-pane.mjs +3 -3
  23. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-page-header.mjs +3 -3
  24. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-scrollable-panes-custom-scrollable-panes-inner-pane.mjs +3 -3
  25. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-scrollable-panes.mjs +3 -3
  26. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-summary-metric-bar-custom-summary-metric-bar-item-custom-summary-metric-bar-item-label.mjs +3 -3
  27. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-summary-metric-bar-custom-summary-metric-bar-item-custom-summary-metric-bar-item-value.mjs +3 -3
  28. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-summary-metric-bar-custom-summary-metric-bar-item.mjs +3 -3
  29. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-summary-metric-bar.mjs +3 -3
  30. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-vertical-scroll-pane-custom-vertical-scroll-pane-inner-pane.mjs +3 -3
  31. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-vertical-scroll-pane-custom-vertical-scroll-pane-outer-pane.mjs +3 -3
  32. package/fesm2022/hmcts-opal-frontend-common-components-custom-custom-vertical-scroll-pane.mjs +3 -3
  33. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-accordion.mjs +3 -3
  34. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-back-link.mjs +3 -3
  35. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-button.mjs +3 -3
  36. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-cancel-link.mjs +3 -3
  37. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-checkboxes.mjs +12 -12
  38. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-date-input.mjs +3 -3
  39. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-details.mjs +3 -3
  40. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-error-summary.mjs +3 -3
  41. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-footer.mjs +3 -3
  42. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-header.mjs +6 -6
  43. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-heading-with-caption.mjs +3 -3
  44. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-inset-text.mjs +3 -3
  45. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-list-govuk-list-link.mjs +3 -3
  46. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-list.mjs +3 -3
  47. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-notification-banner.mjs +3 -3
  48. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-pagination.mjs +3 -3
  49. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-panel.mjs +3 -3
  50. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-radio.mjs +12 -12
  51. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-select.mjs +3 -3
  52. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-summary-card-list.mjs +6 -6
  53. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-summary-list.mjs +12 -12
  54. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-table.mjs +12 -12
  55. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-tabs-govuk-tabs-list-item.mjs +3 -3
  56. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-tabs-govuk-tabs-panel.mjs +3 -3
  57. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-tabs.mjs +3 -3
  58. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-tag.mjs +3 -3
  59. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-task-list.mjs +6 -6
  60. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-text-area.mjs +3 -3
  61. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-text-input-prefix-suffix.mjs +3 -3
  62. package/fesm2022/hmcts-opal-frontend-common-components-govuk-govuk-text-input.mjs +3 -3
  63. package/fesm2022/hmcts-opal-frontend-common-components-hod-hod-loading-spinner.mjs +3 -3
  64. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-alert.mjs +21 -21
  65. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-badge.mjs +3 -3
  66. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-button-menu-moj-button-menu-item.mjs +3 -3
  67. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-button-menu.mjs +3 -3
  68. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-date-picker.mjs +3 -3
  69. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-filter-moj-filter-panel-moj-filter-panel-header.mjs +3 -3
  70. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-filter-moj-filter-panel-moj-filter-panel-option-moj-filter-panel-option-form-group-item.mjs +3 -3
  71. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-filter-moj-filter-panel-moj-filter-panel-option-moj-filter-panel-option-form-group-keyword.mjs +3 -3
  72. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-filter-moj-filter-panel-moj-filter-panel-option.mjs +3 -3
  73. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-filter-moj-filter-panel-moj-filter-panel-selected-moj-filter-panel-selected-tag.mjs +3 -3
  74. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-filter-moj-filter-panel-moj-filter-panel-selected.mjs +3 -3
  75. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-filter-moj-filter-panel.mjs +3 -3
  76. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-filter.mjs +3 -3
  77. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-header.mjs +6 -6
  78. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-inset-text.mjs +3 -3
  79. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-notification-badge.mjs +3 -3
  80. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-page-header.mjs +3 -3
  81. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-pagination.mjs +3 -3
  82. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-primary-navigation.mjs +6 -6
  83. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-sortable-table.mjs +18 -18
  84. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-sub-navigation.mjs +6 -6
  85. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-ticket-panel.mjs +3 -3
  86. package/fesm2022/hmcts-opal-frontend-common-components-moj-moj-timeline.mjs +6 -6
  87. package/fesm2022/{hmcts-opal-frontend-common-concurrency-failure.component-DhLPSRrO.mjs → hmcts-opal-frontend-common-concurrency-failure.component-Cfu8b65-.mjs} +4 -4
  88. package/fesm2022/hmcts-opal-frontend-common-directives-capitalisation.mjs +3 -3
  89. package/fesm2022/hmcts-opal-frontend-common-directives-govuk-button.mjs +3 -3
  90. package/fesm2022/hmcts-opal-frontend-common-directives-moj-multi-select.mjs +6 -6
  91. package/fesm2022/hmcts-opal-frontend-common-directives-trim-leading-trailing-whitespace.mjs +3 -3
  92. package/fesm2022/{hmcts-opal-frontend-common-internal-server-error.component-CdTVIpN_.mjs → hmcts-opal-frontend-common-internal-server-error.component-CT3bxevh.mjs} +4 -4
  93. package/fesm2022/{hmcts-opal-frontend-common-pages-access-denied.component-BDPx9bHD.mjs → hmcts-opal-frontend-common-pages-access-denied.component-BxhkCLOI.mjs} +4 -4
  94. package/fesm2022/{hmcts-opal-frontend-common-pages-account-created.component-Bnx53kTU.mjs → hmcts-opal-frontend-common-pages-account-created.component-CJiRndGj.mjs} +4 -4
  95. package/fesm2022/{hmcts-opal-frontend-common-pages-concurrency-failure.component-DhLPSRrO.mjs → hmcts-opal-frontend-common-pages-concurrency-failure.component-Cfu8b65-.mjs} +4 -4
  96. package/fesm2022/hmcts-opal-frontend-common-pages-dashboard-page.mjs +3 -3
  97. package/fesm2022/{hmcts-opal-frontend-common-pages-internal-server-error.component-CdTVIpN_.mjs → hmcts-opal-frontend-common-pages-internal-server-error.component-CT3bxevh.mjs} +4 -4
  98. package/fesm2022/{hmcts-opal-frontend-common-pages-permission-denied.component-CJQrh--T.mjs → hmcts-opal-frontend-common-pages-permission-denied.component-BYeottTr.mjs} +4 -4
  99. package/fesm2022/{hmcts-opal-frontend-common-pages-sign-in-stub.component-DGR30VJn.mjs → hmcts-opal-frontend-common-pages-sign-in-stub.component-Cz0W_KDW.mjs} +4 -4
  100. package/fesm2022/{hmcts-opal-frontend-common-pages-sign-in.component-tx1zJtdS.mjs → hmcts-opal-frontend-common-pages-sign-in.component-N_WlJ6nC.mjs} +4 -4
  101. package/fesm2022/hmcts-opal-frontend-common-pages.mjs +6 -6
  102. package/fesm2022/{hmcts-opal-frontend-common-permission-denied.component-CJQrh--T.mjs → hmcts-opal-frontend-common-permission-denied.component-BYeottTr.mjs} +4 -4
  103. package/fesm2022/hmcts-opal-frontend-common-pipes-date-format.mjs +3 -3
  104. package/fesm2022/hmcts-opal-frontend-common-pipes-days-ago.mjs +3 -3
  105. package/fesm2022/hmcts-opal-frontend-common-pipes-monetary.mjs +3 -3
  106. package/fesm2022/hmcts-opal-frontend-common-pipes-national-insurance.mjs +3 -3
  107. package/fesm2022/hmcts-opal-frontend-common-resolvers-title.mjs +3 -3
  108. package/fesm2022/hmcts-opal-frontend-common-services-app-initializer-service.mjs +3 -3
  109. package/fesm2022/hmcts-opal-frontend-common-services-app-insights-service.mjs +3 -3
  110. package/fesm2022/hmcts-opal-frontend-common-services-auth-service.mjs +3 -3
  111. package/fesm2022/hmcts-opal-frontend-common-services-date-service.mjs +3 -3
  112. package/fesm2022/hmcts-opal-frontend-common-services-history-transformation-service.mjs +3 -3
  113. package/fesm2022/hmcts-opal-frontend-common-services-launch-darkly-service.mjs +3 -3
  114. package/fesm2022/hmcts-opal-frontend-common-services-opal-user-service.mjs +3 -3
  115. package/fesm2022/hmcts-opal-frontend-common-services-permissions-service.mjs +3 -3
  116. package/fesm2022/hmcts-opal-frontend-common-services-session-service.mjs +3 -3
  117. package/fesm2022/hmcts-opal-frontend-common-services-sort-service.mjs +3 -3
  118. package/fesm2022/hmcts-opal-frontend-common-services-transfer-state-service.mjs +3 -3
  119. package/fesm2022/hmcts-opal-frontend-common-services-transformation-service.mjs +3 -3
  120. package/fesm2022/hmcts-opal-frontend-common-services-utils-service.mjs +37 -13
  121. package/fesm2022/{hmcts-opal-frontend-common-sign-in-stub.component-DGR30VJn.mjs → hmcts-opal-frontend-common-sign-in-stub.component-Cz0W_KDW.mjs} +4 -4
  122. package/fesm2022/{hmcts-opal-frontend-common-sign-in.component-ZonGWT6k.mjs → hmcts-opal-frontend-common-sign-in.component-Cv5vLQ8y.mjs} +4 -4
  123. package/fesm2022/hmcts-opal-frontend-common.mjs +6 -6
  124. package/package.json +1 -1
  125. package/types/hmcts-opal-frontend-common-components-abstract-abstract-sortable-table-pagination.d.ts +12 -1
  126. package/types/hmcts-opal-frontend-common-services-utils-service.d.ts +10 -3
@@ -25,10 +25,10 @@ class SessionService {
25
25
  }), shareReplay(1));
26
26
  return this.tokenExpiryCache$;
27
27
  }
28
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SessionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
29
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SessionService, providedIn: 'root' });
28
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: SessionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
29
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: SessionService, providedIn: 'root' });
30
30
  }
31
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SessionService, decorators: [{
31
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: SessionService, decorators: [{
32
32
  type: Injectable,
33
33
  args: [{ providedIn: 'root' }]
34
34
  }] });
@@ -79,10 +79,10 @@ class SortService {
79
79
  arraySortDesc(array) {
80
80
  return sort(array).desc();
81
81
  }
82
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SortService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
83
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SortService, providedIn: 'root' });
82
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: SortService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
83
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: SortService, providedIn: 'root' });
84
84
  }
85
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SortService, decorators: [{
85
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: SortService, decorators: [{
86
86
  type: Injectable,
87
87
  args: [{
88
88
  providedIn: 'root',
@@ -82,10 +82,10 @@ class TransferStateService {
82
82
  this.globalStore.setFeatureFlags(featureFlagConfig.releases);
83
83
  }
84
84
  }
85
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TransferStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
86
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TransferStateService, providedIn: 'root' });
85
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: TransferStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
86
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: TransferStateService, providedIn: 'root' });
87
87
  }
88
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TransferStateService, decorators: [{
88
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: TransferStateService, decorators: [{
89
89
  type: Injectable,
90
90
  args: [{
91
91
  providedIn: 'root',
@@ -89,10 +89,10 @@ class TransformationService {
89
89
  }
90
90
  return result;
91
91
  }
92
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TransformationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
93
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TransformationService, providedIn: 'root' });
92
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: TransformationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
93
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: TransformationService, providedIn: 'root' });
94
94
  }
95
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TransformationService, decorators: [{
95
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: TransformationService, decorators: [{
96
96
  type: Injectable,
97
97
  args: [{
98
98
  providedIn: 'root',
@@ -1,8 +1,12 @@
1
- import { ViewportScroller } from '@angular/common';
1
+ import { DOCUMENT, ViewportScroller, formatCurrency } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
3
  import { inject, Injectable } from '@angular/core';
4
4
 
5
+ // Matches decimal strings with an optional leading minus and either no commas or correctly grouped thousands.
6
+ // The optional decimal point may have no fractional digits to preserve accepted values such as "1.".
7
+ const DECIMAL_OR_GROUPED_NUMBER_PATTERN = /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d*)?$/;
5
8
  class UtilsService {
9
+ document = inject(DOCUMENT);
6
10
  viewportScroller = inject(ViewportScroller);
7
11
  /**
8
12
  * Converts the first letter of a string to uppercase.
@@ -21,20 +25,24 @@ class UtilsService {
21
25
  return str.toUpperCase();
22
26
  }
23
27
  /**
24
- * Converts a number to a monetary string representation.
25
- * @param amount - The number to convert.
26
- * @returns The monetary string representation of the number.
28
+ * Converts a finite number or decimal string to a GBP monetary string.
29
+ * String values may use a leading minus, correctly positioned thousands separators, and surrounding whitespace.
30
+ * @param amount - The numeric value to convert.
31
+ * @returns The formatted monetary value, or an empty string when the input is invalid.
27
32
  */
28
33
  convertToMonetaryString(amount) {
29
- let negativeValue = false;
30
34
  if (typeof amount === 'string') {
31
- amount = Number.parseFloat(amount);
35
+ const trimmedAmount = amount.trim();
36
+ if (!DECIMAL_OR_GROUPED_NUMBER_PATTERN.test(trimmedAmount)) {
37
+ return '';
38
+ }
39
+ amount = Number(trimmedAmount.replaceAll(',', ''));
32
40
  }
33
- if (amount < 0) {
34
- negativeValue = true;
35
- amount = Math.abs(amount);
41
+ if (!Number.isFinite(amount)) {
42
+ return '';
36
43
  }
37
- return `${negativeValue ? '-' : ''}£${amount.toFixed(2)}`;
44
+ const normalizedAmount = amount === 0 ? 0 : amount;
45
+ return formatCurrency(normalizedAmount, 'en-GB', '£', 'GBP', '1.2-2');
38
46
  }
39
47
  /**
40
48
  * Formats a 6-digit number or string as a sort code.
@@ -61,6 +69,22 @@ class UtilsService {
61
69
  scrollToTop() {
62
70
  this.viewportScroller.scrollToPosition([0, 0]);
63
71
  }
72
+ /**
73
+ * Moves focus to the main content landmark and scrolls the viewport to the top of the page.
74
+ * A temporary tabindex allows the normally non-focusable landmark to receive programmatic focus.
75
+ */
76
+ focusAndScrollToTop() {
77
+ const mainContent = this.document.getElementById('main-content');
78
+ if (mainContent) {
79
+ const hasTabindex = mainContent.hasAttribute('tabindex');
80
+ if (!hasTabindex) {
81
+ mainContent.setAttribute('tabindex', '-1');
82
+ mainContent.addEventListener('blur', () => mainContent.removeAttribute('tabindex'), { once: true });
83
+ }
84
+ mainContent.focus({ preventScroll: true });
85
+ }
86
+ this.scrollToTop();
87
+ }
64
88
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
89
  checkFormValues(form) {
66
90
  return Object.values(form).some((value) => {
@@ -153,10 +177,10 @@ class UtilsService {
153
177
  hasSetProperty(value) {
154
178
  return Object.values(value ?? {}).some((v) => (typeof v === 'boolean' ? v === true : v !== null && v !== ''));
155
179
  }
156
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
157
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: UtilsService, providedIn: 'root' });
180
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
181
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UtilsService, providedIn: 'root' });
158
182
  }
159
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: UtilsService, decorators: [{
183
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UtilsService, decorators: [{
160
184
  type: Injectable,
161
185
  args: [{
162
186
  providedIn: 'root',
@@ -28,10 +28,10 @@ class SignInStubComponent {
28
28
  ngOnInit() {
29
29
  this.setupSignInForm();
30
30
  }
31
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SignInStubComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
32
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: SignInStubComponent, isStandalone: true, selector: "opal-lib-sign-in-stub", outputs: { signInFormSubmit: "signInFormSubmit" }, ngImport: i0, template: "<form (submit)=\"handleFormSubmit()\">\n <div class=\"govuk-grid-column-two-thirds\">\n <fieldset class=\"govuk-fieldset\">\n <legend class=\"govuk-fieldset__legend govuk-fieldset__legend--m\">\n <h1 class=\"govuk-fieldset__heading\">Sign in</h1>\n </legend>\n\n <div [formGroup]=\"signInForm\">\n <opal-lib-govuk-text-input\n labelText=\"Email\"\n inputId=\"email\"\n inputName=\"email\"\n inputClasses=\"govuk-!-width-one-half\"\n [control]=\"signInForm.controls['email']\"\n ></opal-lib-govuk-text-input>\n </div>\n </fieldset>\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-one-third\">\n <opal-lib-govuk-button buttonId=\"submitForm\" type=\"submit\"> Sign in</opal-lib-govuk-button>\n </div>\n </div>\n </div>\n</form>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: GovukTextInputComponent, selector: "opal-lib-govuk-text-input", inputs: ["labelText", "labelClasses", "inputId", "inputName", "inputClasses", "hintText", "hintHtml", "errors", "autoComplete", "autoCompleteValue", "control"] }, { kind: "component", type: GovukButtonComponent, selector: "opal-lib-govuk-button", inputs: ["buttonId", "type", "buttonClasses"], outputs: ["buttonClickEvent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
31
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: SignInStubComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
32
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.20", type: SignInStubComponent, isStandalone: true, selector: "opal-lib-sign-in-stub", outputs: { signInFormSubmit: "signInFormSubmit" }, ngImport: i0, template: "<form (submit)=\"handleFormSubmit()\">\n <div class=\"govuk-grid-column-two-thirds\">\n <fieldset class=\"govuk-fieldset\">\n <legend class=\"govuk-fieldset__legend govuk-fieldset__legend--m\">\n <h1 class=\"govuk-fieldset__heading\">Sign in</h1>\n </legend>\n\n <div [formGroup]=\"signInForm\">\n <opal-lib-govuk-text-input\n labelText=\"Email\"\n inputId=\"email\"\n inputName=\"email\"\n inputClasses=\"govuk-!-width-one-half\"\n [control]=\"signInForm.controls['email']\"\n ></opal-lib-govuk-text-input>\n </div>\n </fieldset>\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-one-third\">\n <opal-lib-govuk-button buttonId=\"submitForm\" type=\"submit\"> Sign in</opal-lib-govuk-button>\n </div>\n </div>\n </div>\n</form>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: GovukTextInputComponent, selector: "opal-lib-govuk-text-input", inputs: ["labelText", "labelClasses", "inputId", "inputName", "inputClasses", "hintText", "hintHtml", "errors", "autoComplete", "autoCompleteValue", "control"] }, { kind: "component", type: GovukButtonComponent, selector: "opal-lib-govuk-button", inputs: ["buttonId", "type", "buttonClasses"], outputs: ["buttonClickEvent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
33
33
  }
34
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SignInStubComponent, decorators: [{
34
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: SignInStubComponent, decorators: [{
35
35
  type: Component,
36
36
  args: [{ selector: 'opal-lib-sign-in-stub', imports: [FormsModule, ReactiveFormsModule, GovukTextInputComponent, GovukButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<form (submit)=\"handleFormSubmit()\">\n <div class=\"govuk-grid-column-two-thirds\">\n <fieldset class=\"govuk-fieldset\">\n <legend class=\"govuk-fieldset__legend govuk-fieldset__legend--m\">\n <h1 class=\"govuk-fieldset__heading\">Sign in</h1>\n </legend>\n\n <div [formGroup]=\"signInForm\">\n <opal-lib-govuk-text-input\n labelText=\"Email\"\n inputId=\"email\"\n inputName=\"email\"\n inputClasses=\"govuk-!-width-one-half\"\n [control]=\"signInForm.controls['email']\"\n ></opal-lib-govuk-text-input>\n </div>\n </fieldset>\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-one-third\">\n <opal-lib-govuk-button buttonId=\"submitForm\" type=\"submit\"> Sign in</opal-lib-govuk-button>\n </div>\n </div>\n </div>\n</form>\n" }]
37
37
  }], propDecorators: { signInFormSubmit: [{
@@ -39,4 +39,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
39
39
  }] } });
40
40
 
41
41
  export { SignInStubComponent };
42
- //# sourceMappingURL=hmcts-opal-frontend-common-sign-in-stub.component-DGR30VJn.mjs.map
42
+ //# sourceMappingURL=hmcts-opal-frontend-common-sign-in-stub.component-Cz0W_KDW.mjs.map
@@ -16,13 +16,13 @@ class SignInComponent {
16
16
  handleStubSignInFormSubmit(formData) {
17
17
  this.document.location.href = `${SSO_ENDPOINTS.login}?email=${formData.email}`;
18
18
  }
19
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SignInComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
20
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: SignInComponent, isStandalone: true, selector: "opal-lib-sign-in", ngImport: i0, template: "@defer (when !globalStore.ssoEnabled()) {\n <opal-lib-sign-in-stub (signInFormSubmit)=\"handleStubSignInFormSubmit($event)\"></opal-lib-sign-in-stub>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [import('./hmcts-opal-frontend-common-sign-in-stub.component-DGR30VJn.mjs').then(m => m.SignInStubComponent)]] });
19
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: SignInComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
20
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: SignInComponent, isStandalone: true, selector: "opal-lib-sign-in", ngImport: i0, template: "@defer (when !globalStore.ssoEnabled()) {\n <opal-lib-sign-in-stub (signInFormSubmit)=\"handleStubSignInFormSubmit($event)\"></opal-lib-sign-in-stub>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [import('./hmcts-opal-frontend-common-sign-in-stub.component-Cz0W_KDW.mjs').then(m => m.SignInStubComponent)]] });
21
21
  }
22
- i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.19", ngImport: i0, type: SignInComponent, resolveDeferredDeps: () => [import('./hmcts-opal-frontend-common-sign-in-stub.component-DGR30VJn.mjs').then(m => m.SignInStubComponent)], resolveMetadata: SignInStubComponent => ({ decorators: [{
22
+ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.20", ngImport: i0, type: SignInComponent, resolveDeferredDeps: () => [import('./hmcts-opal-frontend-common-sign-in-stub.component-Cz0W_KDW.mjs').then(m => m.SignInStubComponent)], resolveMetadata: SignInStubComponent => ({ decorators: [{
23
23
  type: Component,
24
24
  args: [{ selector: 'opal-lib-sign-in', imports: [SignInStubComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@defer (when !globalStore.ssoEnabled()) {\n <opal-lib-sign-in-stub (signInFormSubmit)=\"handleStubSignInFormSubmit($event)\"></opal-lib-sign-in-stub>\n}\n" }]
25
25
  }], ctorParameters: null, propDecorators: null }) });
26
26
 
27
27
  export { SignInComponent };
28
- //# sourceMappingURL=hmcts-opal-frontend-common-sign-in.component-ZonGWT6k.mjs.map
28
+ //# sourceMappingURL=hmcts-opal-frontend-common-sign-in.component-Cv5vLQ8y.mjs.map
@@ -36,39 +36,39 @@ const routing = [
36
36
  { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
37
37
  {
38
38
  path: PAGES_ROUTING_PATHS.children.accessDenied,
39
- loadComponent: () => import('./hmcts-opal-frontend-common-access-denied.component-BDPx9bHD.mjs').then((c) => c.AccessDeniedComponent),
39
+ loadComponent: () => import('./hmcts-opal-frontend-common-access-denied.component-BxhkCLOI.mjs').then((c) => c.AccessDeniedComponent),
40
40
  canActivate: [authGuard, accountGuard],
41
41
  data: { title: PAGES_ROUTING_TITLES.children.accessDenied },
42
42
  resolve: { title: TitleResolver },
43
43
  },
44
44
  {
45
45
  path: PAGES_ROUTING_PATHS.children.concurrencyFailure,
46
- loadComponent: () => import('./hmcts-opal-frontend-common-concurrency-failure.component-DhLPSRrO.mjs').then((c) => c.ConcurrencyFailureComponent),
46
+ loadComponent: () => import('./hmcts-opal-frontend-common-concurrency-failure.component-Cfu8b65-.mjs').then((c) => c.ConcurrencyFailureComponent),
47
47
  data: { title: PAGES_ROUTING_TITLES.children.concurrencyFailure },
48
48
  resolve: { title: TitleResolver },
49
49
  },
50
50
  {
51
51
  path: PAGES_ROUTING_PATHS.children.permissionDenied,
52
- loadComponent: () => import('./hmcts-opal-frontend-common-permission-denied.component-CJQrh--T.mjs').then((c) => c.PermissionDeniedComponent),
52
+ loadComponent: () => import('./hmcts-opal-frontend-common-permission-denied.component-BYeottTr.mjs').then((c) => c.PermissionDeniedComponent),
53
53
  data: { title: PAGES_ROUTING_TITLES.children.permissionDenied },
54
54
  resolve: { title: TitleResolver },
55
55
  },
56
56
  {
57
57
  path: PAGES_ROUTING_PATHS.children.internalServerError,
58
- loadComponent: () => import('./hmcts-opal-frontend-common-internal-server-error.component-CdTVIpN_.mjs').then((c) => c.InternalServerErrorComponent),
58
+ loadComponent: () => import('./hmcts-opal-frontend-common-internal-server-error.component-CT3bxevh.mjs').then((c) => c.InternalServerErrorComponent),
59
59
  data: { title: PAGES_ROUTING_TITLES.children.internalServerError },
60
60
  resolve: { title: TitleResolver },
61
61
  },
62
62
  {
63
63
  path: PAGES_ROUTING_PATHS.children.signIn,
64
- loadComponent: () => import('./hmcts-opal-frontend-common-sign-in.component-ZonGWT6k.mjs').then((c) => c.SignInComponent),
64
+ loadComponent: () => import('./hmcts-opal-frontend-common-sign-in.component-Cv5vLQ8y.mjs').then((c) => c.SignInComponent),
65
65
  canActivate: [signedInGuard],
66
66
  data: { title: PAGES_ROUTING_TITLES.children.signIn },
67
67
  resolve: { title: TitleResolver },
68
68
  },
69
69
  {
70
70
  path: PAGES_ROUTING_PATHS.children.accountCreated,
71
- loadComponent: () => import('./hmcts-opal-frontend-common-account-created.component-Bnx53kTU.mjs').then((c) => c.AccountCreated),
71
+ loadComponent: () => import('./hmcts-opal-frontend-common-account-created.component-CJiRndGj.mjs').then((c) => c.AccountCreated),
72
72
  canActivate: [authGuard],
73
73
  data: { title: PAGES_ROUTING_TITLES.children.accountCreated },
74
74
  resolve: { title: TitleResolver },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hmcts/opal-frontend-common",
3
- "version": "0.0.101",
3
+ "version": "0.0.103",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -4,12 +4,17 @@ import * as _angular_core from '@angular/core';
4
4
  import { AbstractSortableTableComponent } from '@hmcts/opal-frontend-common/components/abstract/abstract-sortable-table';
5
5
 
6
6
  declare abstract class AbstractSortableTablePaginationComponent extends AbstractSortableTableComponent {
7
+ private readonly injector;
8
+ private readonly paginationFocusUtilsService;
9
+ private readonly paginationFocusTargets;
7
10
  /**
8
11
  * Keeps the current page within the available range when the data set or page size changes.
9
12
  */
10
13
  private readonly clampCurrentPageEffect;
11
14
  currentPageSignal: _angular_core.WritableSignal<number>;
12
15
  itemsPerPageSignal: _angular_core.WritableSignal<number>;
16
+ paginationPageTitle: string;
17
+ readonly pageChangeAnnouncement: _angular_core.WritableSignal<string>;
13
18
  startIndexComputed: _angular_core.Signal<number>;
14
19
  /**
15
20
  * Computes the end index for the current page of the sorted table data.
@@ -19,6 +24,11 @@ declare abstract class AbstractSortableTablePaginationComponent extends Abstract
19
24
  */
20
25
  endIndexComputed: _angular_core.Signal<number>;
21
26
  paginatedTableDataComputed: _angular_core.Signal<_hmcts_opal_frontend_common_components_abstract_abstract_sortable_table_interfaces.IAbstractTableData<_hmcts_opal_frontend_common_components_abstract_abstract_sortable_table_types.SortableValuesType>[]>;
27
+ /**
28
+ * Focuses the first target rendered for the new page and lets the browser scroll it into view.
29
+ * Falls back to the main content landmark when the table has no marked focus target.
30
+ */
31
+ private focusNewPageContent;
22
32
  /**
23
33
  * Handles sorting changes and resets the page to the first page.
24
34
  *
@@ -43,13 +53,14 @@ declare abstract class AbstractSortableTablePaginationComponent extends Abstract
43
53
  onApplyFilters(): void;
44
54
  /**
45
55
  * Handles the event when the page is changed.
56
+ * Moves focus to the first marked target, or the main content fallback, after committing a different page.
46
57
  *
47
58
  * @param newPage - The new page number to set. If the provided page number is out of range,
48
59
  * it will be clamped between 1 and the total number of pages.
49
60
  */
50
61
  onPageChange(newPage: number): void;
51
62
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AbstractSortableTablePaginationComponent, never>;
52
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<AbstractSortableTablePaginationComponent, "ng-component", never, {}, {}, never, never, true, never>;
63
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AbstractSortableTablePaginationComponent, "ng-component", never, { "paginationPageTitle": { "alias": "paginationPageTitle"; "required": false; }; }, {}, never, never, true, never>;
53
64
  }
54
65
 
55
66
  export { AbstractSortableTablePaginationComponent };
@@ -1,6 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
 
3
3
  declare class UtilsService {
4
+ private readonly document;
4
5
  private readonly viewportScroller;
5
6
  /**
6
7
  * Converts the first letter of a string to uppercase.
@@ -15,9 +16,10 @@ declare class UtilsService {
15
16
  */
16
17
  upperCaseAllLetters(str: string): string;
17
18
  /**
18
- * Converts a number to a monetary string representation.
19
- * @param amount - The number to convert.
20
- * @returns The monetary string representation of the number.
19
+ * Converts a finite number or decimal string to a GBP monetary string.
20
+ * String values may use a leading minus, correctly positioned thousands separators, and surrounding whitespace.
21
+ * @param amount - The numeric value to convert.
22
+ * @returns The formatted monetary value, or an empty string when the input is invalid.
21
23
  */
22
24
  convertToMonetaryString(amount: number | string): string;
23
25
  /**
@@ -38,6 +40,11 @@ declare class UtilsService {
38
40
  * Utilizes the `viewportScroller` service to scroll to the position [0, 0].
39
41
  */
40
42
  scrollToTop(): void;
43
+ /**
44
+ * Moves focus to the main content landmark and scrolls the viewport to the top of the page.
45
+ * A temporary tabindex allows the normally non-focusable landmark to receive programmatic focus.
46
+ */
47
+ focusAndScrollToTop(): void;
41
48
  checkFormValues(form: {
42
49
  [key: string]: any;
43
50
  }): boolean;