ngwr 13.0.0 → 14.0.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 (200) hide show
  1. package/README.md +13 -6
  2. package/color-picker/styles/_index.scss +43 -5
  3. package/fesm2022/ngwr-alert.mjs +5 -5
  4. package/fesm2022/ngwr-alert.mjs.map +1 -1
  5. package/fesm2022/ngwr-back-top.mjs +11 -1
  6. package/fesm2022/ngwr-back-top.mjs.map +1 -1
  7. package/fesm2022/ngwr-blur-text.mjs +13 -2
  8. package/fesm2022/ngwr-blur-text.mjs.map +1 -1
  9. package/fesm2022/ngwr-border-glow.mjs +12 -3
  10. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  11. package/fesm2022/ngwr-breadcrumbs.mjs +14 -3
  12. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  13. package/fesm2022/ngwr-button.mjs +4 -4
  14. package/fesm2022/ngwr-button.mjs.map +1 -1
  15. package/fesm2022/ngwr-calendar-testing.mjs +15 -0
  16. package/fesm2022/ngwr-calendar-testing.mjs.map +1 -1
  17. package/fesm2022/ngwr-calendar.mjs +51 -5
  18. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  19. package/fesm2022/ngwr-circular-text.mjs +20 -1
  20. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  21. package/fesm2022/ngwr-collapse.mjs.map +1 -1
  22. package/fesm2022/ngwr-color-picker-testing.mjs +23 -7
  23. package/fesm2022/ngwr-color-picker-testing.mjs.map +1 -1
  24. package/fesm2022/ngwr-color-picker.mjs +89 -10
  25. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  26. package/fesm2022/ngwr-command-palette.mjs +27 -3
  27. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  28. package/fesm2022/ngwr-context-menu.mjs +13 -3
  29. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  30. package/fesm2022/ngwr-date-adapters-fns.mjs +101 -33
  31. package/fesm2022/ngwr-date-adapters-fns.mjs.map +1 -1
  32. package/fesm2022/ngwr-date-picker-testing.mjs +10 -2
  33. package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -1
  34. package/fesm2022/ngwr-date-picker.mjs +103 -13
  35. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  36. package/fesm2022/ngwr-date.mjs +480 -79
  37. package/fesm2022/ngwr-date.mjs.map +1 -1
  38. package/fesm2022/ngwr-dialog.mjs +22 -16
  39. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  40. package/fesm2022/ngwr-directives.mjs +5 -2
  41. package/fesm2022/ngwr-directives.mjs.map +1 -1
  42. package/fesm2022/ngwr-drag-drop.mjs +30 -2
  43. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  44. package/fesm2022/ngwr-drawer.mjs +24 -18
  45. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  46. package/fesm2022/ngwr-dropdown.mjs +8 -3
  47. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  48. package/fesm2022/ngwr-event-calendar-testing.mjs.map +1 -1
  49. package/fesm2022/ngwr-event-calendar.mjs +1 -1
  50. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  51. package/fesm2022/ngwr-file-upload.mjs +52 -12
  52. package/fesm2022/ngwr-file-upload.mjs.map +1 -1
  53. package/fesm2022/ngwr-fuzzy-text.mjs +21 -4
  54. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  55. package/fesm2022/ngwr-gradient-text.mjs +9 -2
  56. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  57. package/fesm2022/ngwr-i18n-en.mjs +63 -1
  58. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  59. package/fesm2022/ngwr-i18n-ru.mjs +28 -1
  60. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  61. package/fesm2022/ngwr-i18n.mjs +150 -22
  62. package/fesm2022/ngwr-i18n.mjs.map +1 -1
  63. package/fesm2022/ngwr-icon-adapters-feather.mjs +11 -0
  64. package/fesm2022/ngwr-icon-adapters-feather.mjs.map +1 -1
  65. package/fesm2022/ngwr-icon-adapters-lucide.mjs +22 -2
  66. package/fesm2022/ngwr-icon-adapters-lucide.mjs.map +1 -1
  67. package/fesm2022/ngwr-icon.mjs +474 -37
  68. package/fesm2022/ngwr-icon.mjs.map +1 -1
  69. package/fesm2022/ngwr-input-number.mjs +3 -3
  70. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  71. package/fesm2022/ngwr-input-otp.mjs +21 -3
  72. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  73. package/fesm2022/ngwr-input.mjs +14 -7
  74. package/fesm2022/ngwr-input.mjs.map +1 -1
  75. package/fesm2022/ngwr-knob-testing.mjs.map +1 -1
  76. package/fesm2022/ngwr-knob.mjs +20 -2
  77. package/fesm2022/ngwr-knob.mjs.map +1 -1
  78. package/fesm2022/ngwr-loading-bar-router.mjs +73 -0
  79. package/fesm2022/ngwr-loading-bar-router.mjs.map +1 -0
  80. package/fesm2022/ngwr-loading-bar.mjs +21 -32
  81. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  82. package/fesm2022/ngwr-markdown.mjs +63 -11
  83. package/fesm2022/ngwr-markdown.mjs.map +1 -1
  84. package/fesm2022/ngwr-mention.mjs +104 -14
  85. package/fesm2022/ngwr-mention.mjs.map +1 -1
  86. package/fesm2022/ngwr-overlay.mjs +36 -7
  87. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  88. package/fesm2022/ngwr-pagination-testing.mjs +11 -10
  89. package/fesm2022/ngwr-pagination-testing.mjs.map +1 -1
  90. package/fesm2022/ngwr-pagination.mjs +65 -30
  91. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  92. package/fesm2022/ngwr-popconfirm.mjs +3 -2
  93. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  94. package/fesm2022/ngwr-popover.mjs +2 -1
  95. package/fesm2022/ngwr-popover.mjs.map +1 -1
  96. package/fesm2022/ngwr-qr.mjs +38 -1
  97. package/fesm2022/ngwr-qr.mjs.map +1 -1
  98. package/fesm2022/ngwr-select.mjs +93 -34
  99. package/fesm2022/ngwr-select.mjs.map +1 -1
  100. package/fesm2022/ngwr-shiny-text.mjs +10 -3
  101. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  102. package/fesm2022/ngwr-splitter-testing.mjs.map +1 -1
  103. package/fesm2022/ngwr-squircle.mjs +2 -1
  104. package/fesm2022/ngwr-squircle.mjs.map +1 -1
  105. package/fesm2022/ngwr-statistic.mjs +35 -4
  106. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  107. package/fesm2022/ngwr-table.mjs +35 -12
  108. package/fesm2022/ngwr-table.mjs.map +1 -1
  109. package/fesm2022/ngwr-tabs-router.mjs +158 -0
  110. package/fesm2022/ngwr-tabs-router.mjs.map +1 -0
  111. package/fesm2022/ngwr-tabs-testing.mjs +13 -11
  112. package/fesm2022/ngwr-tabs-testing.mjs.map +1 -1
  113. package/fesm2022/ngwr-tabs.mjs +104 -12
  114. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  115. package/fesm2022/ngwr-textarea.mjs +20 -1
  116. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  117. package/fesm2022/ngwr-tour.mjs +1 -1
  118. package/fesm2022/ngwr-tour.mjs.map +1 -1
  119. package/fesm2022/ngwr-transfer.mjs +2 -2
  120. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  121. package/fesm2022/ngwr-tree.mjs +18 -2
  122. package/fesm2022/ngwr-tree.mjs.map +1 -1
  123. package/fesm2022/ngwr-utils.mjs +143 -1
  124. package/fesm2022/ngwr-utils.mjs.map +1 -1
  125. package/fesm2022/ngwr-version.mjs +1 -1
  126. package/fesm2022/ngwr-version.mjs.map +1 -1
  127. package/fesm2022/ngwr-window-testing.mjs +10 -2
  128. package/fesm2022/ngwr-window-testing.mjs.map +1 -1
  129. package/fesm2022/ngwr-window.mjs +4 -4
  130. package/fesm2022/ngwr-window.mjs.map +1 -1
  131. package/i18n/en.json +33 -6
  132. package/i18n/ru.json +33 -6
  133. package/llms-full.txt +20 -11
  134. package/llms.txt +47 -16
  135. package/mcp/catalog.js +3 -3
  136. package/mcp/providers.js +11 -0
  137. package/package.json +11 -3
  138. package/schematics/migrations/v13/index.js +101 -0
  139. package/schematics/migrations/v14/index.js +422 -0
  140. package/schematics/migrations.json +10 -0
  141. package/schematics/page/templates.js +1 -1
  142. package/schematics/use/symbol-map.json +1 -0
  143. package/skills/ngwr/SKILL.md +4 -1
  144. package/skills/ngwr/references/catalog.md +2 -0
  145. package/skills/ngwr/references/setup.md +4 -0
  146. package/stepper/styles/_index.scss +19 -1
  147. package/textarea/styles/_index.scss +14 -6
  148. package/toast/styles/_index.scss +12 -4
  149. package/types/ngwr-alert.d.ts +3 -3
  150. package/types/ngwr-blur-text.d.ts +8 -0
  151. package/types/ngwr-breadcrumbs.d.ts +1 -0
  152. package/types/ngwr-button.d.ts +2 -2
  153. package/types/ngwr-calendar-testing.d.ts +21 -4
  154. package/types/ngwr-calendar.d.ts +37 -0
  155. package/types/ngwr-circular-text.d.ts +9 -0
  156. package/types/ngwr-collapse.d.ts +19 -15
  157. package/types/ngwr-color-picker-testing.d.ts +10 -4
  158. package/types/ngwr-color-picker.d.ts +70 -2
  159. package/types/ngwr-command-palette.d.ts +14 -0
  160. package/types/ngwr-context-menu.d.ts +1 -1
  161. package/types/ngwr-date-adapters-fns.d.ts +71 -29
  162. package/types/ngwr-date-picker-testing.d.ts +206 -185
  163. package/types/ngwr-date-picker.d.ts +7 -0
  164. package/types/ngwr-date.d.ts +143 -13
  165. package/types/ngwr-drag-drop.d.ts +19 -0
  166. package/types/ngwr-dropdown.d.ts +1 -1
  167. package/types/ngwr-event-calendar-testing.d.ts +12 -9
  168. package/types/ngwr-file-upload.d.ts +31 -3
  169. package/types/ngwr-fuzzy-text.d.ts +5 -0
  170. package/types/ngwr-i18n.d.ts +89 -7
  171. package/types/ngwr-icon-adapters-feather.d.ts +11 -0
  172. package/types/ngwr-icon.d.ts +42 -1
  173. package/types/ngwr-input-number.d.ts +1 -1
  174. package/types/ngwr-input-otp.d.ts +3 -0
  175. package/types/ngwr-input.d.ts +11 -4
  176. package/types/ngwr-knob-testing.d.ts +8 -4
  177. package/types/ngwr-knob.d.ts +18 -0
  178. package/types/ngwr-loading-bar-router.d.ts +35 -0
  179. package/types/ngwr-loading-bar.d.ts +19 -9
  180. package/types/ngwr-mention.d.ts +13 -0
  181. package/types/ngwr-pagination-testing.d.ts +11 -10
  182. package/types/ngwr-pagination.d.ts +39 -10
  183. package/types/ngwr-popconfirm.d.ts +1 -1
  184. package/types/ngwr-popover.d.ts +1 -1
  185. package/types/ngwr-select.d.ts +65 -10
  186. package/types/ngwr-shiny-text.d.ts +1 -0
  187. package/types/ngwr-splitter-testing.d.ts +9 -4
  188. package/types/ngwr-squircle.d.ts +1 -1
  189. package/types/ngwr-statistic.d.ts +22 -2
  190. package/types/ngwr-table.d.ts +24 -5
  191. package/types/ngwr-tabs-router.d.ts +67 -0
  192. package/types/ngwr-tabs-testing.d.ts +12 -10
  193. package/types/ngwr-tabs.d.ts +103 -6
  194. package/types/ngwr-textarea.d.ts +9 -0
  195. package/types/ngwr-tree.d.ts +7 -0
  196. package/types/ngwr-utils.d.ts +79 -1
  197. package/types/ngwr-version.d.ts +1 -1
  198. package/types/ngwr-window-testing.d.ts +11 -3
  199. package/types/ngwr-window.d.ts +11 -4
  200. package/window/styles/_index.scss +1 -1
@@ -1,6 +1,6 @@
1
1
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
2
2
  import * as i0 from '@angular/core';
3
- import { model, input, computed, effect, ViewEncapsulation, Component } from '@angular/core';
3
+ import { model, input, computed, inject, LOCALE_ID, effect, ViewEncapsulation, Component } from '@angular/core';
4
4
  import { WrButton } from 'ngwr/button';
5
5
  import { useI18nText, useI18nFormatter } from 'ngwr/i18n';
6
6
  import { WrSelect, WrOption } from 'ngwr/select';
@@ -16,13 +16,13 @@ const ELLIPSIS = '…';
16
16
  /**
17
17
  * Numbered page navigator with optional total / page-size controls.
18
18
  *
19
- * Two-way binds `currentPage` and `pageSize` via signal `model()` inputs.
19
+ * Two-way binds `page` and `pageSize` via signal `model()` inputs.
20
20
  *
21
21
  * @example
22
22
  * ```html
23
23
  * <wr-pagination
24
24
  * [total]="120"
25
- * [(currentPage)]="page"
25
+ * [(page)]="page"
26
26
  * [(pageSize)]="size"
27
27
  * showTotal
28
28
  * showSizeChanger
@@ -32,9 +32,17 @@ const ELLIPSIS = '…';
32
32
  * @see https://ngwr.dev/reference/components/pagination
33
33
  */
34
34
  class WrPagination {
35
- /** Currently displayed page (1-based). Two-way bindable. */
36
- currentPage = model(1, /* @ts-ignore */
37
- ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
35
+ /**
36
+ * Currently displayed page (1-based). Two-way bindable.
37
+ *
38
+ * `page` rather than `currentPage` since v14, so this and `<wr-table>` — which
39
+ * renders one of these in its own footer — spell the two concepts they share
40
+ * one way each. It also names the output: a `model()` called `X` forces
41
+ * `(XChange)`, so the old name produced `(currentPageChange)` against the
42
+ * table's `(pageChange)`.
43
+ */
44
+ page = model(1, /* @ts-ignore */
45
+ ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
38
46
  /** Items per page. Two-way bindable. */
39
47
  pageSize = model(10, /* @ts-ignore */
40
48
  ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
@@ -64,9 +72,6 @@ class WrPagination {
64
72
  * width, not the viewport). @default false
65
73
  */
66
74
  responsive = input(false, { ...(ngDevMode ? { debugName: "responsive" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
67
- /** Localised text between range and total ("X–Y of Z"). Falls back to `pagination.of` then `'of'`. */
68
- ofLabel = input(null, /* @ts-ignore */
69
- ...(ngDevMode ? [{ debugName: "ofLabel" }] : /* istanbul ignore next */ []));
70
75
  /** Previous-page button aria-label. Falls back to `pagination.prev`. */
71
76
  prevLabel = input(null, /* @ts-ignore */
72
77
  ...(ngDevMode ? [{ debugName: "prevLabel" }] : /* istanbul ignore next */ []));
@@ -80,7 +85,6 @@ class WrPagination {
80
85
  label = input(null, /* @ts-ignore */
81
86
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
82
87
  /** Resolved labels. */
83
- resolvedOf = useI18nText(this.ofLabel, 'pagination.of', 'of');
84
88
  resolvedPrev = useI18nText(this.prevLabel, 'pagination.prev', 'Previous page');
85
89
  resolvedNext = useI18nText(this.nextLabel, 'pagination.next', 'Next page');
86
90
  resolvedItemsPerPage = useI18nText(this.itemsPerPageLabel, 'pagination.itemsPerPage', 'Items per page');
@@ -99,7 +103,7 @@ class WrPagination {
99
103
  ...(ngDevMode ? [{ debugName: "totalPages" }] : /* istanbul ignore next */ []));
100
104
  /**
101
105
  * Internal: where the previous arrow goes. Clamped to the end of the valid
102
- * range rather than being a plain `currentPage() - 1`, because the page can
106
+ * range rather than being a plain `page() - 1`, because the page can
103
107
  * legitimately sit past that end while `total` is 0 (see the guard effect).
104
108
  * From page 5 of one page, `goTo(4)` is refused as out of range, so the arrow
105
109
  * was enabled and did nothing — and under `responsive` on a narrow box the
@@ -107,15 +111,46 @@ class WrPagination {
107
111
  * all. `Math.min` only ever moves the target INWARD, so `goTo`'s own
108
112
  * past-the-end refusal keeps working as the backstop it is.
109
113
  */
110
- prevPage = computed(() => Math.min(this.currentPage() - 1, this.totalPages()), /* @ts-ignore */
114
+ prevPage = computed(() => Math.min(this.page() - 1, this.totalPages()), /* @ts-ignore */
111
115
  ...(ngDevMode ? [{ debugName: "prevPage" }] : /* istanbul ignore next */ []));
112
- /** Internal: "X–Y of Z" string. */
116
+ /**
117
+ * Internal: the "1–10 of 235" line, as ONE catalog template.
118
+ *
119
+ * It used to be `` `${start}-${end} ${of} ${total}` ``, which localised the
120
+ * word in the middle and nothing else: the ASCII hyphen between the bounds and
121
+ * the operand order were both frozen in TypeScript, so ja-JP and ar-SA got
122
+ * English word order and no language could change the range separator. The
123
+ * three numbers go through `Intl.NumberFormat` for the same reason the total
124
+ * beside them does — a five-figure total needs the locale's grouping, and
125
+ * ar-SA needs its own digits.
126
+ *
127
+ * The `ofLabel` input is gone with it: an input for the middle word is the
128
+ * concatenation, re-offered as API.
129
+ */
113
130
  rangeLabel = computed(() => {
114
- const start = this.total() === 0 ? 0 : (this.currentPage() - 1) * this.pageSize() + 1;
115
- const end = Math.min(this.currentPage() * this.pageSize(), this.total());
116
- return `${start}-${end} ${this.resolvedOf()} ${this.total()}`;
131
+ const start = this.total() === 0 ? 0 : (this.page() - 1) * this.pageSize() + 1;
132
+ const end = Math.min(this.page() * this.pageSize(), this.total());
133
+ return this.rangeText({
134
+ from: this.number(start),
135
+ to: this.number(end),
136
+ total: this.number(this.total()),
137
+ });
117
138
  }, /* @ts-ignore */
118
139
  ...(ngDevMode ? [{ debugName: "rangeLabel" }] : /* istanbul ignore next */ []));
140
+ /** Internal: the compact pager's `1 / 24`, likewise a catalog template. */
141
+ compactLabel = computed(() => this.compactText({ current: this.number(this.page()), total: this.number(this.totalPages()) }), /* @ts-ignore */
142
+ ...(ngDevMode ? [{ debugName: "compactLabel" }] : /* istanbul ignore next */ []));
143
+ rangeText = useI18nFormatter('pagination.range', '{{from}}–{{to}} of {{total}}');
144
+ compactText = useI18nFormatter('pagination.compact', '{{current}} / {{total}}');
145
+ locale = inject(LOCALE_ID);
146
+ /**
147
+ * Grouped per `LOCALE_ID`. Only the range and the compact pager go through
148
+ * this — a page NUMBER on a button is an identifier, and `1,024` on a button
149
+ * reads as two things.
150
+ */
151
+ number(value) {
152
+ return new Intl.NumberFormat(this.locale).format(value);
153
+ }
119
154
  /**
120
155
  * Internal: page list with ellipses. Window of 7 visible page slots.
121
156
  *
@@ -123,7 +158,7 @@ class WrPagination {
123
158
  */
124
159
  pages = computed(() => {
125
160
  const total = this.totalPages();
126
- const current = this.currentPage();
161
+ const current = this.page();
127
162
  if (total <= 7) {
128
163
  return Array.from({ length: total }, (_, i) => i + 1);
129
164
  }
@@ -169,14 +204,14 @@ class WrPagination {
169
204
  }, /* @ts-ignore */
170
205
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
171
206
  isCurrent(page) {
172
- return this.currentPage() === page;
207
+ return this.page() === page;
173
208
  }
174
209
  goTo(page) {
175
210
  if (typeof page !== 'number')
176
211
  return;
177
- if (this.disabled() || page < 1 || page > this.totalPages() || page === this.currentPage())
212
+ if (this.disabled() || page < 1 || page > this.totalPages() || page === this.page())
178
213
  return;
179
- this.currentPage.set(page);
214
+ this.page.set(page);
180
215
  }
181
216
  /**
182
217
  * `wr-select` carries an `unknown` value by design, so the size arrives
@@ -184,8 +219,8 @@ class WrPagination {
184
219
  * `[ngModel]`, which hid the coercion rather than removing the need for it.
185
220
  */
186
221
  constructor() {
187
- // `currentPage` is a plain `model` — a `model()` takes no transform — so a
188
- // shrinking `total` and a host `[(currentPage)]` write both land in it
222
+ // `page` is a plain `model` — a `model()` takes no transform — so a
223
+ // shrinking `total` and a host `[(page)]` write both land in it
189
224
  // unchecked. The guard used to read and write the page inside `untracked()`
190
225
  // and pull DOWNWARDS only, so it fired when `total` / `pageSize` moved and
191
226
  // never when the host wrote: past the end no cell carries `aria-current`,
@@ -202,7 +237,7 @@ class WrPagination {
202
237
  // value whenever the params change, and a params function returning an
203
238
  // object literal is never reference-equal, so `total` reads 0 between the
204
239
  // click and the response. `totalPages()` is 1 there, so the guard pulled
205
- // every page above the first back to 1 and emitted a `currentPageChange`
240
+ // every page above the first back to 1 and emitted a `pageChange`
206
241
  // the host could not tell from a click: the pager could not leave page 1,
207
242
  // and each click cost two events. A negative `total` is folded into the
208
243
  // same branch because it is as meaningless as a zero one.
@@ -212,7 +247,7 @@ class WrPagination {
212
247
  // and while it was skipped a host write of -3 survived — `rangeLabel()`
213
248
  // guards `start` for an empty total and not `end`, so it read "0--30 of 0",
214
249
  // and the compact pager read "-3 / 1". It is written as one expression
215
- // rather than an early return so the effect depends on `currentPage()` and
250
+ // rather than an early return so the effect depends on `page()` and
216
251
  // `total()` on every run, whichever branch decides the result.
217
252
  //
218
253
  // What IS still given up while `total` is 0 and the held page is past the
@@ -225,11 +260,11 @@ class WrPagination {
225
260
  // the "enabled and inert" behaviour described above, which this component
226
261
  // used to accept at both ends.
227
262
  effect(() => {
228
- const page = this.currentPage();
263
+ const page = this.page();
229
264
  const floored = Math.max(1, page);
230
265
  const clamped = this.total() <= 0 ? floored : Math.min(floored, this.totalPages());
231
266
  if (clamped !== page)
232
- this.currentPage.set(clamped);
267
+ this.page.set(clamped);
233
268
  });
234
269
  }
235
270
  onSizeChange(size) {
@@ -243,7 +278,7 @@ class WrPagination {
243
278
  // that write has not reached the model yet, it arrives on the next binding
244
279
  // pass. So the clamp computed a cap from the PRE-change page and wrote the
245
280
  // result over the host's decision: from page 6 at size 10, choosing 25
246
- // emitted `currentPageChange(5)` on top of the host's reset to 1, which the
281
+ // emitted `pageChange(5)` on top of the host's reset to 1, which the
247
282
  // host cannot tell from a navigation, and a second request went out. The
248
283
  // guard effect in the constructor takes it over and runs once the bindings
249
284
  // have settled, so it clamps the page the host actually wants.
@@ -260,12 +295,12 @@ class WrPagination {
260
295
  this.pageSize.set(next);
261
296
  }
262
297
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: WrPagination, deps: [], target: i0.ɵɵFactoryTarget.Component });
263
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: WrPagination, isStandalone: true, selector: "wr-pagination", inputs: { currentPage: { classPropertyName: "currentPage", publicName: "currentPage", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, showSizeChanger: { classPropertyName: "showSizeChanger", publicName: "showSizeChanger", isSignal: true, isRequired: false, transformFunction: null }, showTotal: { classPropertyName: "showTotal", publicName: "showTotal", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, ofLabel: { classPropertyName: "ofLabel", publicName: "ofLabel", isSignal: true, isRequired: false, transformFunction: null }, prevLabel: { classPropertyName: "prevLabel", publicName: "prevLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, itemsPerPageLabel: { classPropertyName: "itemsPerPageLabel", publicName: "itemsPerPageLabel", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { currentPage: "currentPageChange", pageSize: "pageSizeChange" }, host: { attributes: { "role": "navigation" }, properties: { "class": "classes()", "attr.aria-label": "navLabel()" } }, ngImport: i0, template: "<div class=\"wr-pagination__inner\">\n @if (showTotal()) {\n <span class=\"wr-pagination__total\">{{ rangeLabel() }}</span>\n }\n\n <div class=\"wr-pagination__nav\">\n <!--\n `wr-pagination__nav-btn` exists so the stylesheet can mirror the arrow\n glyph under `dir=\"rtl\"`. A class rather than `:first-child` /\n `:last-child` on the row: those two positions do hold today \u2014 which is why\n the `--square` end caps use them \u2014 but only while the prev button, the\n compact label and the next button all stay unconditional and in this\n order. A mirror keyed to position would follow a reorder, or land on a\n page cell, without a word.\n\n The two `[disabled]` bindings compare against the RANGE (`<= 1`,\n `>= totalPages()`) rather than for equality with its ends. While `total`\n is 0 the guard effect stops enforcing the upper bound, so the page can\n legitimately sit past `totalPages()` \u2014 and `=== totalPages()` reported\n next as enabled there while `goTo` refused the step. Prev is still\n enabled in that state, correctly: `prevPage()` walks it back into range.\n -->\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || currentPage() <= 1\"\n (click)=\"goTo(prevPage())\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n </wr-btn>\n\n @for (page of pages(); track $index) {\n @if (page === ellipsis) {\n <span class=\"wr-pagination__ellipsis\">{{ ellipsis }}</span>\n } @else {\n <wr-btn\n class=\"wr-pagination__page\"\n [size]=\"size()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"goToPage({ page })\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <!-- Compact pager \u2014 shown only in responsive mode on a narrow box (CSS). -->\n <span class=\"wr-pagination__current\" aria-hidden=\"true\">{{ currentPage() }} / {{ totalPages() }}</span>\n\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedNext()\"\n [disabled]=\"disabled() || currentPage() >= totalPages()\"\n (click)=\"goTo(currentPage() + 1)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </wr-btn>\n </div>\n\n @if (showSizeChanger()) {\n <!--\n `ariaLabel`, not `[attr.aria-label]`: `<wr-select>`'s host carries no role,\n so an attribute there names nothing and never reaches the `role=\"combobox\"`\n button inside \u2014 the size changer announced itself as the catalog's generic\n \"Select\".\n -->\n <wr-select\n class=\"wr-pagination__size\"\n [ariaLabel]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [value]=\"pageSize()\"\n (valueChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ perPage({ size: option }) }}</wr-option>\n }\n </wr-select>\n }\n</div>\n", dependencies: [{ kind: "component", type: WrButton, selector: "wr-btn, button[wr-btn], a[wr-btn]", inputs: ["color", "size", "shape", "icon", "iconPosition", "disabled", "outlined", "block", "loading", "isDisabledWhenLoading"] }, { kind: "component", type: WrSelect, selector: "wr-select", inputs: ["placeholder", "clearLabel", "ariaLabel", "disabled", "readonly", "rounded", "size", "responsive", "mode", "searchable", "searchQuery", "options", "displayWith", "loader", "serverSearch", "debounceMs", "minChars", "freeText", "virtualScroll", "rowHeight", "viewportHeight", "overscan", "noResultsText", "loadingText", "loading", "separators", "allowDuplicates", "validate", "clearable", "maxItems", "maxTagCount", "value"], outputs: ["searchQueryChange", "searchChange", "valueChange", "touch"] }, { kind: "component", type: WrOption, selector: "wr-option", inputs: ["value", "disabled"] }], encapsulation: i0.ViewEncapsulation.None });
298
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: WrPagination, isStandalone: true, selector: "wr-pagination", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, showSizeChanger: { classPropertyName: "showSizeChanger", publicName: "showSizeChanger", isSignal: true, isRequired: false, transformFunction: null }, showTotal: { classPropertyName: "showTotal", publicName: "showTotal", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, prevLabel: { classPropertyName: "prevLabel", publicName: "prevLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, itemsPerPageLabel: { classPropertyName: "itemsPerPageLabel", publicName: "itemsPerPageLabel", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { page: "pageChange", pageSize: "pageSizeChange" }, host: { attributes: { "role": "navigation" }, properties: { "class": "classes()", "attr.aria-label": "navLabel()" } }, ngImport: i0, template: "<div class=\"wr-pagination__inner\">\n @if (showTotal()) {\n <span class=\"wr-pagination__total\">{{ rangeLabel() }}</span>\n }\n\n <div class=\"wr-pagination__nav\">\n <!--\n `wr-pagination__nav-btn` exists so the stylesheet can mirror the arrow\n glyph under `dir=\"rtl\"`. A class rather than `:first-child` /\n `:last-child` on the row: those two positions do hold today \u2014 which is why\n the `--square` end caps use them \u2014 but only while the prev button, the\n compact label and the next button all stay unconditional and in this\n order. A mirror keyed to position would follow a reorder, or land on a\n page cell, without a word.\n\n The two `[disabled]` bindings compare against the RANGE (`<= 1`,\n `>= totalPages()`) rather than for equality with its ends. While `total`\n is 0 the guard effect stops enforcing the upper bound, so the page can\n legitimately sit past `totalPages()` \u2014 and `=== totalPages()` reported\n next as enabled there while `goTo` refused the step. Prev is still\n enabled in that state, correctly: `prevPage()` walks it back into range.\n -->\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || page() <= 1\"\n (click)=\"goTo(prevPage())\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n </wr-btn>\n\n @for (page of pages(); track $index) {\n @if (page === ellipsis) {\n <span class=\"wr-pagination__ellipsis\">{{ ellipsis }}</span>\n } @else {\n <wr-btn\n class=\"wr-pagination__page\"\n [size]=\"size()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"goToPage({ page })\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <!-- Compact pager \u2014 shown only in responsive mode on a narrow box (CSS). -->\n <span class=\"wr-pagination__current\" aria-hidden=\"true\">{{ compactLabel() }}</span>\n\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedNext()\"\n [disabled]=\"disabled() || page() >= totalPages()\"\n (click)=\"goTo(page() + 1)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </wr-btn>\n </div>\n\n @if (showSizeChanger()) {\n <!--\n `ariaLabel`, not `[attr.aria-label]`: `<wr-select>`'s host carries no role,\n so an attribute there names nothing and never reaches the `role=\"combobox\"`\n button inside \u2014 the size changer announced itself as the catalog's generic\n \"Select\".\n -->\n <wr-select\n class=\"wr-pagination__size\"\n [ariaLabel]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [value]=\"pageSize()\"\n (valueChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ perPage({ size: option }) }}</wr-option>\n }\n </wr-select>\n }\n</div>\n", dependencies: [{ kind: "component", type: WrButton, selector: "wr-btn, button[wr-btn], a[wr-btn]", inputs: ["color", "size", "shape", "icon", "iconPosition", "disabled", "outlined", "block", "loading", "disabledWhenLoading"] }, { kind: "component", type: WrSelect, selector: "wr-select", inputs: ["placeholder", "clearLabel", "ariaLabel", "disabled", "readonly", "rounded", "size", "responsive", "mode", "searchable", "searchQuery", "options", "displayWith", "loader", "serverSearch", "debounceMs", "minChars", "freeText", "virtualScroll", "rowHeight", "viewportHeight", "overscan", "noResultsText", "loadingText", "loading", "separators", "allowDuplicates", "validate", "clearable", "maxItems", "maxTagCount", "value"], outputs: ["searchQueryChange", "searchChange", "valueChange", "touch"] }, { kind: "component", type: WrOption, selector: "wr-option", inputs: ["value", "disabled"] }], encapsulation: i0.ViewEncapsulation.None });
264
299
  }
265
300
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: WrPagination, decorators: [{
266
301
  type: Component,
267
- args: [{ selector: 'wr-pagination', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()', role: 'navigation', '[attr.aria-label]': 'navLabel()' }, imports: [WrButton, WrSelect, WrOption], template: "<div class=\"wr-pagination__inner\">\n @if (showTotal()) {\n <span class=\"wr-pagination__total\">{{ rangeLabel() }}</span>\n }\n\n <div class=\"wr-pagination__nav\">\n <!--\n `wr-pagination__nav-btn` exists so the stylesheet can mirror the arrow\n glyph under `dir=\"rtl\"`. A class rather than `:first-child` /\n `:last-child` on the row: those two positions do hold today \u2014 which is why\n the `--square` end caps use them \u2014 but only while the prev button, the\n compact label and the next button all stay unconditional and in this\n order. A mirror keyed to position would follow a reorder, or land on a\n page cell, without a word.\n\n The two `[disabled]` bindings compare against the RANGE (`<= 1`,\n `>= totalPages()`) rather than for equality with its ends. While `total`\n is 0 the guard effect stops enforcing the upper bound, so the page can\n legitimately sit past `totalPages()` \u2014 and `=== totalPages()` reported\n next as enabled there while `goTo` refused the step. Prev is still\n enabled in that state, correctly: `prevPage()` walks it back into range.\n -->\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || currentPage() <= 1\"\n (click)=\"goTo(prevPage())\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n </wr-btn>\n\n @for (page of pages(); track $index) {\n @if (page === ellipsis) {\n <span class=\"wr-pagination__ellipsis\">{{ ellipsis }}</span>\n } @else {\n <wr-btn\n class=\"wr-pagination__page\"\n [size]=\"size()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"goToPage({ page })\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <!-- Compact pager \u2014 shown only in responsive mode on a narrow box (CSS). -->\n <span class=\"wr-pagination__current\" aria-hidden=\"true\">{{ currentPage() }} / {{ totalPages() }}</span>\n\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedNext()\"\n [disabled]=\"disabled() || currentPage() >= totalPages()\"\n (click)=\"goTo(currentPage() + 1)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </wr-btn>\n </div>\n\n @if (showSizeChanger()) {\n <!--\n `ariaLabel`, not `[attr.aria-label]`: `<wr-select>`'s host carries no role,\n so an attribute there names nothing and never reaches the `role=\"combobox\"`\n button inside \u2014 the size changer announced itself as the catalog's generic\n \"Select\".\n -->\n <wr-select\n class=\"wr-pagination__size\"\n [ariaLabel]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [value]=\"pageSize()\"\n (valueChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ perPage({ size: option }) }}</wr-option>\n }\n </wr-select>\n }\n</div>\n" }]
268
- }], ctorParameters: () => [], propDecorators: { currentPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPage", required: false }] }, { type: i0.Output, args: ["currentPageChange"] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }, { type: i0.Output, args: ["pageSizeChange"] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], showSizeChanger: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSizeChanger", required: false }] }], showTotal: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTotal", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], ofLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ofLabel", required: false }] }], prevLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "prevLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], itemsPerPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsPerPageLabel", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
302
+ args: [{ selector: 'wr-pagination', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()', role: 'navigation', '[attr.aria-label]': 'navLabel()' }, imports: [WrButton, WrSelect, WrOption], template: "<div class=\"wr-pagination__inner\">\n @if (showTotal()) {\n <span class=\"wr-pagination__total\">{{ rangeLabel() }}</span>\n }\n\n <div class=\"wr-pagination__nav\">\n <!--\n `wr-pagination__nav-btn` exists so the stylesheet can mirror the arrow\n glyph under `dir=\"rtl\"`. A class rather than `:first-child` /\n `:last-child` on the row: those two positions do hold today \u2014 which is why\n the `--square` end caps use them \u2014 but only while the prev button, the\n compact label and the next button all stay unconditional and in this\n order. A mirror keyed to position would follow a reorder, or land on a\n page cell, without a word.\n\n The two `[disabled]` bindings compare against the RANGE (`<= 1`,\n `>= totalPages()`) rather than for equality with its ends. While `total`\n is 0 the guard effect stops enforcing the upper bound, so the page can\n legitimately sit past `totalPages()` \u2014 and `=== totalPages()` reported\n next as enabled there while `goTo` refused the step. Prev is still\n enabled in that state, correctly: `prevPage()` walks it back into range.\n -->\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || page() <= 1\"\n (click)=\"goTo(prevPage())\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n </wr-btn>\n\n @for (page of pages(); track $index) {\n @if (page === ellipsis) {\n <span class=\"wr-pagination__ellipsis\">{{ ellipsis }}</span>\n } @else {\n <wr-btn\n class=\"wr-pagination__page\"\n [size]=\"size()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"goToPage({ page })\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <!-- Compact pager \u2014 shown only in responsive mode on a narrow box (CSS). -->\n <span class=\"wr-pagination__current\" aria-hidden=\"true\">{{ compactLabel() }}</span>\n\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedNext()\"\n [disabled]=\"disabled() || page() >= totalPages()\"\n (click)=\"goTo(page() + 1)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </wr-btn>\n </div>\n\n @if (showSizeChanger()) {\n <!--\n `ariaLabel`, not `[attr.aria-label]`: `<wr-select>`'s host carries no role,\n so an attribute there names nothing and never reaches the `role=\"combobox\"`\n button inside \u2014 the size changer announced itself as the catalog's generic\n \"Select\".\n -->\n <wr-select\n class=\"wr-pagination__size\"\n [ariaLabel]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [value]=\"pageSize()\"\n (valueChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ perPage({ size: option }) }}</wr-option>\n }\n </wr-select>\n }\n</div>\n" }]
303
+ }], ctorParameters: () => [], propDecorators: { page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }, { type: i0.Output, args: ["pageChange"] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }, { type: i0.Output, args: ["pageSizeChange"] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], showSizeChanger: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSizeChanger", required: false }] }], showTotal: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTotal", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], prevLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "prevLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], itemsPerPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsPerPageLabel", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
269
304
 
270
305
  /**
271
306
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-pagination.mjs","sources":["../../../projects/lib/pagination/pagination.ts","../../../projects/lib/pagination/pagination.html","../../../projects/lib/pagination/ngwr-pagination.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, effect, input, model } from '@angular/core';\n\nimport { WrButton } from 'ngwr/button';\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\nimport { WrOption, WrSelect } from 'ngwr/select';\nimport { numAttr } from 'ngwr/utils';\n\nimport type { WrPaginationAlign, WrPaginationShape, WrPaginationSize } from './interfaces';\n\nconst ELLIPSIS = '…' as const;\ntype PageEntry = number | typeof ELLIPSIS;\n\n/**\n * Numbered page navigator with optional total / page-size controls.\n *\n * Two-way binds `currentPage` and `pageSize` via signal `model()` inputs.\n *\n * @example\n * ```html\n * <wr-pagination\n * [total]=\"120\"\n * [(currentPage)]=\"page\"\n * [(pageSize)]=\"size\"\n * showTotal\n * showSizeChanger\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/pagination\n */\n@Component({\n selector: 'wr-pagination',\n templateUrl: './pagination.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()', role: 'navigation', '[attr.aria-label]': 'navLabel()' },\n imports: [WrButton, WrSelect, WrOption],\n})\nexport class WrPagination {\n /** Currently displayed page (1-based). Two-way bindable. */\n readonly currentPage = model<number>(1);\n\n /** Items per page. Two-way bindable. */\n readonly pageSize = model<number>(10);\n\n /** Total item count across all pages. */\n readonly total = input(0, { transform: numAttr(0) });\n\n /** Options shown in the page-size dropdown. */\n readonly pageSizeOptions = input<readonly number[]>([10, 20, 50, 100]);\n\n /** Render the page-size dropdown. @default false */\n readonly showSizeChanger = input(false, { transform: coerceBooleanProperty });\n\n /** Render the \"X–Y of Z\" total label. @default false */\n readonly showTotal = input(false, { transform: coerceBooleanProperty });\n\n /** Horizontal alignment. @default 'start' */\n readonly align = input<WrPaginationAlign>('start');\n\n /** Size variant — cascades to every internal button. @default 'sm' */\n readonly size = input<WrPaginationSize>('sm');\n\n /** Cell corner treatment. @default 'rounded' */\n readonly shape = input<WrPaginationShape>('rounded');\n\n /** Disable interaction. @default false */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Collapse to a compact `‹ page / total ›` pager when the control's own box\n * is too narrow for the full numbered strip (a container query on its own\n * width, not the viewport). @default false\n */\n readonly responsive = input(false, { transform: coerceBooleanProperty });\n\n /** Localised text between range and total (\"X–Y of Z\"). Falls back to `pagination.of` then `'of'`. */\n readonly ofLabel = input<string | null>(null);\n\n /** Previous-page button aria-label. Falls back to `pagination.prev`. */\n readonly prevLabel = input<string | null>(null);\n\n /** Next-page button aria-label. Falls back to `pagination.next`. */\n readonly nextLabel = input<string | null>(null);\n\n /** \"Items per page\" label. Falls back to `pagination.itemsPerPage`. */\n readonly itemsPerPageLabel = input<string | null>(null);\n\n /** Accessible name for the `role=\"navigation\"` host. Falls back to `pagination.label`. */\n readonly label = input<string | null>(null);\n\n /** Resolved labels. */\n protected readonly resolvedOf = useI18nText(this.ofLabel, 'pagination.of', 'of');\n protected readonly resolvedPrev = useI18nText(this.prevLabel, 'pagination.prev', 'Previous page');\n protected readonly resolvedNext = useI18nText(this.nextLabel, 'pagination.next', 'Next page');\n protected readonly resolvedItemsPerPage = useI18nText(\n this.itemsPerPageLabel,\n 'pagination.itemsPerPage',\n 'Items per page'\n );\n\n /**\n * Page-size option text — interpolates `{{size}}`. Was the template literal\n * `{{ option }} / page`, which no catalog could reach, so a Russian UI read\n * \"25 / page\".\n */\n protected readonly perPage = useI18nFormatter('pagination.perPage', '{{size}} / page');\n\n /** Per-page-button aria-label — interpolates `{{page}}`. */\n protected readonly goToPage = useI18nFormatter('pagination.goToPage', 'Go to page {{page}}');\n\n /** The nav landmark's own accessible name — was a hardcoded English literal. */\n protected readonly navLabel = useI18nText(this.label, 'pagination.label', 'Pagination');\n\n /** Internal: total page count. */\n protected readonly totalPages = computed(() => Math.max(1, Math.ceil(this.total() / this.pageSize())));\n\n /**\n * Internal: where the previous arrow goes. Clamped to the end of the valid\n * range rather than being a plain `currentPage() - 1`, because the page can\n * legitimately sit past that end while `total` is 0 (see the guard effect).\n * From page 5 of one page, `goTo(4)` is refused as out of range, so the arrow\n * was enabled and did nothing — and under `responsive` on a narrow box the\n * numbered cells are hidden by a container query, which left no way back at\n * all. `Math.min` only ever moves the target INWARD, so `goTo`'s own\n * past-the-end refusal keeps working as the backstop it is.\n */\n protected readonly prevPage = computed(() => Math.min(this.currentPage() - 1, this.totalPages()));\n\n /** Internal: \"X–Y of Z\" string. */\n protected readonly rangeLabel = computed(() => {\n const start = this.total() === 0 ? 0 : (this.currentPage() - 1) * this.pageSize() + 1;\n const end = Math.min(this.currentPage() * this.pageSize(), this.total());\n return `${start}-${end} ${this.resolvedOf()} ${this.total()}`;\n });\n\n /**\n * Internal: page list with ellipses. Window of 7 visible page slots.\n *\n * 1 … 5 6 [7] 8 9 … 20\n */\n protected readonly pages = computed<readonly PageEntry[]>(() => {\n const total = this.totalPages();\n const current = this.currentPage();\n\n if (total <= 7) {\n return Array.from({ length: total }, (_, i) => i + 1);\n }\n\n const items: PageEntry[] = [1];\n if (current > 4) items.push(ELLIPSIS);\n\n let start: number;\n let end: number;\n if (current <= 4) {\n start = 2;\n end = 5;\n } else if (current >= total - 3) {\n start = total - 4;\n end = total - 1;\n } else {\n start = current - 2;\n end = current + 2;\n }\n\n for (let i = start; i <= end; i++) items.push(i);\n if (current < total - 3) items.push(ELLIPSIS);\n if (end !== total) items.push(total);\n\n return items;\n });\n\n protected readonly ellipsis = ELLIPSIS;\n\n protected readonly classes = computed(() => {\n const parts = [\n 'wr-pagination',\n `wr-pagination--${this.align()}`,\n `wr-pagination--${this.size()}`,\n `wr-pagination--${this.shape()}`,\n ];\n if (this.disabled()) parts.push('wr-pagination--disabled');\n if (this.responsive()) parts.push('wr-pagination--responsive');\n return parts.join(' ');\n });\n\n protected isCurrent(page: number): boolean {\n return this.currentPage() === page;\n }\n\n protected goTo(page: number | typeof ELLIPSIS): void {\n if (typeof page !== 'number') return;\n if (this.disabled() || page < 1 || page > this.totalPages() || page === this.currentPage()) return;\n this.currentPage.set(page);\n }\n\n /**\n * `wr-select` carries an `unknown` value by design, so the size arrives\n * untyped and is narrowed here. It used to arrive as `any` through\n * `[ngModel]`, which hid the coercion rather than removing the need for it.\n */\n constructor() {\n // `currentPage` is a plain `model` — a `model()` takes no transform — so a\n // shrinking `total` and a host `[(currentPage)]` write both land in it\n // unchecked. The guard used to read and write the page inside `untracked()`\n // and pull DOWNWARDS only, so it fired when `total` / `pageSize` moved and\n // never when the host wrote: past the end no cell carries `aria-current`,\n // the arrow at that end stays enabled and inert (`goTo` refuses the step\n // rather than correcting the stored page), and below 1 `rangeLabel()` counts\n // backwards (\"-9-0 of 120\"). Two-sided and tracked, the same shape\n // `wr-stepper` and `wr-carousel` use for their own host-owned `model()`.\n //\n // Only the UPPER bound is conditional. A `total` at or below 0 is the one\n // value where pulling the page down is destructive rather than cosmetic:\n // there is no `loading` input, so 0 is genuinely ambiguous between \"the\n // list is empty\" and \"the page is still in flight\", and the second is the\n // ordinary state of a server-paged host — Angular's `resource` drops its\n // value whenever the params change, and a params function returning an\n // object literal is never reference-equal, so `total` reads 0 between the\n // click and the response. `totalPages()` is 1 there, so the guard pulled\n // every page above the first back to 1 and emitted a `currentPageChange`\n // the host could not tell from a click: the pager could not leave page 1,\n // and each click cost two events. A negative `total` is folded into the\n // same branch because it is as meaningless as a zero one.\n //\n // The LOWER bound is unconditional, and gating it on `total` was a mistake\n // in the first cut of this fix: no value of `total` makes page 0 correct,\n // and while it was skipped a host write of -3 survived — `rangeLabel()`\n // guards `start` for an empty total and not `end`, so it read \"0--30 of 0\",\n // and the compact pager read \"-3 / 1\". It is written as one expression\n // rather than an early return so the effect depends on `currentPage()` and\n // `total()` on every run, whichever branch decides the result.\n //\n // What IS still given up while `total` is 0 and the held page is past the\n // first: no cell carries `aria-current`, because `pages` renders the single\n // page and that is not the page the host holds. `rangeLabel()` is not in\n // that list — it already special-cases an empty total and reads \"0-0 of 0\".\n // Nor are the arrows: they compare against the RANGE rather than its ends\n // (see the template), so past the end next renders disabled and prev stays\n // enabled and steps back INTO range via `prevPage`. That is a change from\n // the \"enabled and inert\" behaviour described above, which this component\n // used to accept at both ends.\n effect(() => {\n const page = this.currentPage();\n const floored = Math.max(1, page);\n const clamped = this.total() <= 0 ? floored : Math.min(floored, this.totalPages());\n if (clamped !== page) this.currentPage.set(clamped);\n });\n }\n\n protected onSizeChange(size: unknown): void {\n const next = Number(size);\n if (this.disabled() || !Number.isFinite(next) || next <= 0 || next === this.pageSize()) return;\n // The size and nothing else. This used to clamp the page against the new\n // size too, and it read a value that was already superseded: `pageSize.set`\n // emits `pageSizeChange` synchronously, so by the following statement the\n // host has run its own policy — most tables reset to the first page — and\n // that write has not reached the model yet, it arrives on the next binding\n // pass. So the clamp computed a cap from the PRE-change page and wrote the\n // result over the host's decision: from page 6 at size 10, choosing 25\n // emitted `currentPageChange(5)` on top of the host's reset to 1, which the\n // host cannot tell from a navigation, and a second request went out. The\n // guard effect in the constructor takes it over and runs once the bindings\n // have settled, so it clamps the page the host actually wants.\n //\n // For a SETTLED `total` that is the whole story. For the server-paged host\n // this fix exists for it is not: the size change invalidates the payload\n // too, so `total` reads 0 and the guard returns early. Measured, from page\n // 6 at size 10 choosing 25 with a host that does not reset — in flight:\n // `navigations []`, page 6, total 0; after settle: `navigations [5]`, page\n // 5. So a non-resetting host issues one doomed request for a page that no\n // longer exists and is corrected only when the answer lands. That is an\n // accepted cost of refusing to write back from transient state, not\n // something the guard covers.\n this.pageSize.set(next);\n }\n}\n","<div class=\"wr-pagination__inner\">\n @if (showTotal()) {\n <span class=\"wr-pagination__total\">{{ rangeLabel() }}</span>\n }\n\n <div class=\"wr-pagination__nav\">\n <!--\n `wr-pagination__nav-btn` exists so the stylesheet can mirror the arrow\n glyph under `dir=\"rtl\"`. A class rather than `:first-child` /\n `:last-child` on the row: those two positions do hold today — which is why\n the `--square` end caps use them — but only while the prev button, the\n compact label and the next button all stay unconditional and in this\n order. A mirror keyed to position would follow a reorder, or land on a\n page cell, without a word.\n\n The two `[disabled]` bindings compare against the RANGE (`<= 1`,\n `>= totalPages()`) rather than for equality with its ends. While `total`\n is 0 the guard effect stops enforcing the upper bound, so the page can\n legitimately sit past `totalPages()` — and `=== totalPages()` reported\n next as enabled there while `goTo` refused the step. Prev is still\n enabled in that state, correctly: `prevPage()` walks it back into range.\n -->\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || currentPage() <= 1\"\n (click)=\"goTo(prevPage())\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n </wr-btn>\n\n @for (page of pages(); track $index) {\n @if (page === ellipsis) {\n <span class=\"wr-pagination__ellipsis\">{{ ellipsis }}</span>\n } @else {\n <wr-btn\n class=\"wr-pagination__page\"\n [size]=\"size()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"goToPage({ page })\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <!-- Compact pager — shown only in responsive mode on a narrow box (CSS). -->\n <span class=\"wr-pagination__current\" aria-hidden=\"true\">{{ currentPage() }} / {{ totalPages() }}</span>\n\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedNext()\"\n [disabled]=\"disabled() || currentPage() >= totalPages()\"\n (click)=\"goTo(currentPage() + 1)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </wr-btn>\n </div>\n\n @if (showSizeChanger()) {\n <!--\n `ariaLabel`, not `[attr.aria-label]`: `<wr-select>`'s host carries no role,\n so an attribute there names nothing and never reaches the `role=\"combobox\"`\n button inside — the size changer announced itself as the catalog's generic\n \"Select\".\n -->\n <wr-select\n class=\"wr-pagination__size\"\n [ariaLabel]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [value]=\"pageSize()\"\n (valueChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ perPage({ size: option }) }}</wr-option>\n }\n </wr-select>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngwr-pagination.mjs","sources":["../../../projects/lib/pagination/pagination.ts","../../../projects/lib/pagination/pagination.html","../../../projects/lib/pagination/ngwr-pagination.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, LOCALE_ID, ViewEncapsulation, computed, effect, inject, input, model } from '@angular/core';\n\nimport { WrButton } from 'ngwr/button';\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\nimport { WrOption, WrSelect } from 'ngwr/select';\nimport { numAttr } from 'ngwr/utils';\n\nimport type { WrPaginationAlign, WrPaginationShape, WrPaginationSize } from './interfaces';\n\nconst ELLIPSIS = '…' as const;\ntype PageEntry = number | typeof ELLIPSIS;\n\n/**\n * Numbered page navigator with optional total / page-size controls.\n *\n * Two-way binds `page` and `pageSize` via signal `model()` inputs.\n *\n * @example\n * ```html\n * <wr-pagination\n * [total]=\"120\"\n * [(page)]=\"page\"\n * [(pageSize)]=\"size\"\n * showTotal\n * showSizeChanger\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/pagination\n */\n@Component({\n selector: 'wr-pagination',\n templateUrl: './pagination.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()', role: 'navigation', '[attr.aria-label]': 'navLabel()' },\n imports: [WrButton, WrSelect, WrOption],\n})\nexport class WrPagination {\n /**\n * Currently displayed page (1-based). Two-way bindable.\n *\n * `page` rather than `currentPage` since v14, so this and `<wr-table>` — which\n * renders one of these in its own footer — spell the two concepts they share\n * one way each. It also names the output: a `model()` called `X` forces\n * `(XChange)`, so the old name produced `(currentPageChange)` against the\n * table's `(pageChange)`.\n */\n readonly page = model<number>(1);\n\n /** Items per page. Two-way bindable. */\n readonly pageSize = model<number>(10);\n\n /** Total item count across all pages. */\n readonly total = input(0, { transform: numAttr(0) });\n\n /** Options shown in the page-size dropdown. */\n readonly pageSizeOptions = input<readonly number[]>([10, 20, 50, 100]);\n\n /** Render the page-size dropdown. @default false */\n readonly showSizeChanger = input(false, { transform: coerceBooleanProperty });\n\n /** Render the \"X–Y of Z\" total label. @default false */\n readonly showTotal = input(false, { transform: coerceBooleanProperty });\n\n /** Horizontal alignment. @default 'start' */\n readonly align = input<WrPaginationAlign>('start');\n\n /** Size variant — cascades to every internal button. @default 'sm' */\n readonly size = input<WrPaginationSize>('sm');\n\n /** Cell corner treatment. @default 'rounded' */\n readonly shape = input<WrPaginationShape>('rounded');\n\n /** Disable interaction. @default false */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Collapse to a compact `‹ page / total ›` pager when the control's own box\n * is too narrow for the full numbered strip (a container query on its own\n * width, not the viewport). @default false\n */\n readonly responsive = input(false, { transform: coerceBooleanProperty });\n\n /** Previous-page button aria-label. Falls back to `pagination.prev`. */\n readonly prevLabel = input<string | null>(null);\n\n /** Next-page button aria-label. Falls back to `pagination.next`. */\n readonly nextLabel = input<string | null>(null);\n\n /** \"Items per page\" label. Falls back to `pagination.itemsPerPage`. */\n readonly itemsPerPageLabel = input<string | null>(null);\n\n /** Accessible name for the `role=\"navigation\"` host. Falls back to `pagination.label`. */\n readonly label = input<string | null>(null);\n\n /** Resolved labels. */\n protected readonly resolvedPrev = useI18nText(this.prevLabel, 'pagination.prev', 'Previous page');\n protected readonly resolvedNext = useI18nText(this.nextLabel, 'pagination.next', 'Next page');\n protected readonly resolvedItemsPerPage = useI18nText(\n this.itemsPerPageLabel,\n 'pagination.itemsPerPage',\n 'Items per page'\n );\n\n /**\n * Page-size option text — interpolates `{{size}}`. Was the template literal\n * `{{ option }} / page`, which no catalog could reach, so a Russian UI read\n * \"25 / page\".\n */\n protected readonly perPage = useI18nFormatter('pagination.perPage', '{{size}} / page');\n\n /** Per-page-button aria-label — interpolates `{{page}}`. */\n protected readonly goToPage = useI18nFormatter('pagination.goToPage', 'Go to page {{page}}');\n\n /** The nav landmark's own accessible name — was a hardcoded English literal. */\n protected readonly navLabel = useI18nText(this.label, 'pagination.label', 'Pagination');\n\n /** Internal: total page count. */\n protected readonly totalPages = computed(() => Math.max(1, Math.ceil(this.total() / this.pageSize())));\n\n /**\n * Internal: where the previous arrow goes. Clamped to the end of the valid\n * range rather than being a plain `page() - 1`, because the page can\n * legitimately sit past that end while `total` is 0 (see the guard effect).\n * From page 5 of one page, `goTo(4)` is refused as out of range, so the arrow\n * was enabled and did nothing — and under `responsive` on a narrow box the\n * numbered cells are hidden by a container query, which left no way back at\n * all. `Math.min` only ever moves the target INWARD, so `goTo`'s own\n * past-the-end refusal keeps working as the backstop it is.\n */\n protected readonly prevPage = computed(() => Math.min(this.page() - 1, this.totalPages()));\n\n /**\n * Internal: the \"1–10 of 235\" line, as ONE catalog template.\n *\n * It used to be `` `${start}-${end} ${of} ${total}` ``, which localised the\n * word in the middle and nothing else: the ASCII hyphen between the bounds and\n * the operand order were both frozen in TypeScript, so ja-JP and ar-SA got\n * English word order and no language could change the range separator. The\n * three numbers go through `Intl.NumberFormat` for the same reason the total\n * beside them does — a five-figure total needs the locale's grouping, and\n * ar-SA needs its own digits.\n *\n * The `ofLabel` input is gone with it: an input for the middle word is the\n * concatenation, re-offered as API.\n */\n protected readonly rangeLabel = computed(() => {\n const start = this.total() === 0 ? 0 : (this.page() - 1) * this.pageSize() + 1;\n const end = Math.min(this.page() * this.pageSize(), this.total());\n return this.rangeText({\n from: this.number(start),\n to: this.number(end),\n total: this.number(this.total()),\n });\n });\n\n /** Internal: the compact pager's `1 / 24`, likewise a catalog template. */\n protected readonly compactLabel = computed(() =>\n this.compactText({ current: this.number(this.page()), total: this.number(this.totalPages()) })\n );\n\n private readonly rangeText = useI18nFormatter('pagination.range', '{{from}}–{{to}} of {{total}}');\n private readonly compactText = useI18nFormatter('pagination.compact', '{{current}} / {{total}}');\n\n private readonly locale = inject(LOCALE_ID);\n\n /**\n * Grouped per `LOCALE_ID`. Only the range and the compact pager go through\n * this — a page NUMBER on a button is an identifier, and `1,024` on a button\n * reads as two things.\n */\n private number(value: number): string {\n return new Intl.NumberFormat(this.locale).format(value);\n }\n\n /**\n * Internal: page list with ellipses. Window of 7 visible page slots.\n *\n * 1 … 5 6 [7] 8 9 … 20\n */\n protected readonly pages = computed<readonly PageEntry[]>(() => {\n const total = this.totalPages();\n const current = this.page();\n\n if (total <= 7) {\n return Array.from({ length: total }, (_, i) => i + 1);\n }\n\n const items: PageEntry[] = [1];\n if (current > 4) items.push(ELLIPSIS);\n\n let start: number;\n let end: number;\n if (current <= 4) {\n start = 2;\n end = 5;\n } else if (current >= total - 3) {\n start = total - 4;\n end = total - 1;\n } else {\n start = current - 2;\n end = current + 2;\n }\n\n for (let i = start; i <= end; i++) items.push(i);\n if (current < total - 3) items.push(ELLIPSIS);\n if (end !== total) items.push(total);\n\n return items;\n });\n\n protected readonly ellipsis = ELLIPSIS;\n\n protected readonly classes = computed(() => {\n const parts = [\n 'wr-pagination',\n `wr-pagination--${this.align()}`,\n `wr-pagination--${this.size()}`,\n `wr-pagination--${this.shape()}`,\n ];\n if (this.disabled()) parts.push('wr-pagination--disabled');\n if (this.responsive()) parts.push('wr-pagination--responsive');\n return parts.join(' ');\n });\n\n protected isCurrent(page: number): boolean {\n return this.page() === page;\n }\n\n protected goTo(page: number | typeof ELLIPSIS): void {\n if (typeof page !== 'number') return;\n if (this.disabled() || page < 1 || page > this.totalPages() || page === this.page()) return;\n this.page.set(page);\n }\n\n /**\n * `wr-select` carries an `unknown` value by design, so the size arrives\n * untyped and is narrowed here. It used to arrive as `any` through\n * `[ngModel]`, which hid the coercion rather than removing the need for it.\n */\n constructor() {\n // `page` is a plain `model` — a `model()` takes no transform — so a\n // shrinking `total` and a host `[(page)]` write both land in it\n // unchecked. The guard used to read and write the page inside `untracked()`\n // and pull DOWNWARDS only, so it fired when `total` / `pageSize` moved and\n // never when the host wrote: past the end no cell carries `aria-current`,\n // the arrow at that end stays enabled and inert (`goTo` refuses the step\n // rather than correcting the stored page), and below 1 `rangeLabel()` counts\n // backwards (\"-9-0 of 120\"). Two-sided and tracked, the same shape\n // `wr-stepper` and `wr-carousel` use for their own host-owned `model()`.\n //\n // Only the UPPER bound is conditional. A `total` at or below 0 is the one\n // value where pulling the page down is destructive rather than cosmetic:\n // there is no `loading` input, so 0 is genuinely ambiguous between \"the\n // list is empty\" and \"the page is still in flight\", and the second is the\n // ordinary state of a server-paged host — Angular's `resource` drops its\n // value whenever the params change, and a params function returning an\n // object literal is never reference-equal, so `total` reads 0 between the\n // click and the response. `totalPages()` is 1 there, so the guard pulled\n // every page above the first back to 1 and emitted a `pageChange`\n // the host could not tell from a click: the pager could not leave page 1,\n // and each click cost two events. A negative `total` is folded into the\n // same branch because it is as meaningless as a zero one.\n //\n // The LOWER bound is unconditional, and gating it on `total` was a mistake\n // in the first cut of this fix: no value of `total` makes page 0 correct,\n // and while it was skipped a host write of -3 survived — `rangeLabel()`\n // guards `start` for an empty total and not `end`, so it read \"0--30 of 0\",\n // and the compact pager read \"-3 / 1\". It is written as one expression\n // rather than an early return so the effect depends on `page()` and\n // `total()` on every run, whichever branch decides the result.\n //\n // What IS still given up while `total` is 0 and the held page is past the\n // first: no cell carries `aria-current`, because `pages` renders the single\n // page and that is not the page the host holds. `rangeLabel()` is not in\n // that list — it already special-cases an empty total and reads \"0-0 of 0\".\n // Nor are the arrows: they compare against the RANGE rather than its ends\n // (see the template), so past the end next renders disabled and prev stays\n // enabled and steps back INTO range via `prevPage`. That is a change from\n // the \"enabled and inert\" behaviour described above, which this component\n // used to accept at both ends.\n effect(() => {\n const page = this.page();\n const floored = Math.max(1, page);\n const clamped = this.total() <= 0 ? floored : Math.min(floored, this.totalPages());\n if (clamped !== page) this.page.set(clamped);\n });\n }\n\n protected onSizeChange(size: unknown): void {\n const next = Number(size);\n if (this.disabled() || !Number.isFinite(next) || next <= 0 || next === this.pageSize()) return;\n // The size and nothing else. This used to clamp the page against the new\n // size too, and it read a value that was already superseded: `pageSize.set`\n // emits `pageSizeChange` synchronously, so by the following statement the\n // host has run its own policy — most tables reset to the first page — and\n // that write has not reached the model yet, it arrives on the next binding\n // pass. So the clamp computed a cap from the PRE-change page and wrote the\n // result over the host's decision: from page 6 at size 10, choosing 25\n // emitted `pageChange(5)` on top of the host's reset to 1, which the\n // host cannot tell from a navigation, and a second request went out. The\n // guard effect in the constructor takes it over and runs once the bindings\n // have settled, so it clamps the page the host actually wants.\n //\n // For a SETTLED `total` that is the whole story. For the server-paged host\n // this fix exists for it is not: the size change invalidates the payload\n // too, so `total` reads 0 and the guard returns early. Measured, from page\n // 6 at size 10 choosing 25 with a host that does not reset — in flight:\n // `navigations []`, page 6, total 0; after settle: `navigations [5]`, page\n // 5. So a non-resetting host issues one doomed request for a page that no\n // longer exists and is corrected only when the answer lands. That is an\n // accepted cost of refusing to write back from transient state, not\n // something the guard covers.\n this.pageSize.set(next);\n }\n}\n","<div class=\"wr-pagination__inner\">\n @if (showTotal()) {\n <span class=\"wr-pagination__total\">{{ rangeLabel() }}</span>\n }\n\n <div class=\"wr-pagination__nav\">\n <!--\n `wr-pagination__nav-btn` exists so the stylesheet can mirror the arrow\n glyph under `dir=\"rtl\"`. A class rather than `:first-child` /\n `:last-child` on the row: those two positions do hold today — which is why\n the `--square` end caps use them — but only while the prev button, the\n compact label and the next button all stay unconditional and in this\n order. A mirror keyed to position would follow a reorder, or land on a\n page cell, without a word.\n\n The two `[disabled]` bindings compare against the RANGE (`<= 1`,\n `>= totalPages()`) rather than for equality with its ends. While `total`\n is 0 the guard effect stops enforcing the upper bound, so the page can\n legitimately sit past `totalPages()` — and `=== totalPages()` reported\n next as enabled there while `goTo` refused the step. Prev is still\n enabled in that state, correctly: `prevPage()` walks it back into range.\n -->\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || page() <= 1\"\n (click)=\"goTo(prevPage())\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n </wr-btn>\n\n @for (page of pages(); track $index) {\n @if (page === ellipsis) {\n <span class=\"wr-pagination__ellipsis\">{{ ellipsis }}</span>\n } @else {\n <wr-btn\n class=\"wr-pagination__page\"\n [size]=\"size()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"goToPage({ page })\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <!-- Compact pager — shown only in responsive mode on a narrow box (CSS). -->\n <span class=\"wr-pagination__current\" aria-hidden=\"true\">{{ compactLabel() }}</span>\n\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedNext()\"\n [disabled]=\"disabled() || page() >= totalPages()\"\n (click)=\"goTo(page() + 1)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </wr-btn>\n </div>\n\n @if (showSizeChanger()) {\n <!--\n `ariaLabel`, not `[attr.aria-label]`: `<wr-select>`'s host carries no role,\n so an attribute there names nothing and never reaches the `role=\"combobox\"`\n button inside — the size changer announced itself as the catalog's generic\n \"Select\".\n -->\n <wr-select\n class=\"wr-pagination__size\"\n [ariaLabel]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [value]=\"pageSize()\"\n (valueChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ perPage({ size: option }) }}</wr-option>\n }\n </wr-select>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -49,7 +49,7 @@ class WrPopconfirmPanel {
49
49
  confirmed = output();
50
50
  cancelled = output();
51
51
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: WrPopconfirmPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
52
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: WrPopconfirmPanel, isStandalone: true, selector: "wr-popconfirm", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, messageId: { classPropertyName: "messageId", publicName: "messageId", isSignal: true, isRequired: false, transformFunction: null }, confirmText: { classPropertyName: "confirmText", publicName: "confirmText", isSignal: true, isRequired: false, transformFunction: null }, cancelText: { classPropertyName: "cancelText", publicName: "cancelText", isSignal: true, isRequired: false, transformFunction: null }, confirmColor: { classPropertyName: "confirmColor", publicName: "confirmColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", cancelled: "cancelled" }, host: { classAttribute: "wr-popconfirm" }, ngImport: i0, template: "<p class=\"wr-popconfirm__message\" [attr.id]=\"messageId()\">{{ message() }}</p>\n\n<div class=\"wr-popconfirm__actions\">\n <wr-btn class=\"wr-popconfirm__action wr-popconfirm__action--cancel\" size=\"sm\" (click)=\"cancelled.emit()\">\n {{ cancelText() }}\n </wr-btn>\n <wr-btn\n class=\"wr-popconfirm__action wr-popconfirm__action--confirm\"\n size=\"sm\"\n [color]=\"confirmColor()\"\n (click)=\"confirmed.emit()\"\n >\n {{ confirmText() }}\n </wr-btn>\n</div>\n", dependencies: [{ kind: "component", type: WrButton, selector: "wr-btn, button[wr-btn], a[wr-btn]", inputs: ["color", "size", "shape", "icon", "iconPosition", "disabled", "outlined", "block", "loading", "isDisabledWhenLoading"] }], encapsulation: i0.ViewEncapsulation.None });
52
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: WrPopconfirmPanel, isStandalone: true, selector: "wr-popconfirm", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, messageId: { classPropertyName: "messageId", publicName: "messageId", isSignal: true, isRequired: false, transformFunction: null }, confirmText: { classPropertyName: "confirmText", publicName: "confirmText", isSignal: true, isRequired: false, transformFunction: null }, cancelText: { classPropertyName: "cancelText", publicName: "cancelText", isSignal: true, isRequired: false, transformFunction: null }, confirmColor: { classPropertyName: "confirmColor", publicName: "confirmColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", cancelled: "cancelled" }, host: { classAttribute: "wr-popconfirm" }, ngImport: i0, template: "<p class=\"wr-popconfirm__message\" [attr.id]=\"messageId()\">{{ message() }}</p>\n\n<div class=\"wr-popconfirm__actions\">\n <wr-btn class=\"wr-popconfirm__action wr-popconfirm__action--cancel\" size=\"sm\" (click)=\"cancelled.emit()\">\n {{ cancelText() }}\n </wr-btn>\n <wr-btn\n class=\"wr-popconfirm__action wr-popconfirm__action--confirm\"\n size=\"sm\"\n [color]=\"confirmColor()\"\n (click)=\"confirmed.emit()\"\n >\n {{ confirmText() }}\n </wr-btn>\n</div>\n", dependencies: [{ kind: "component", type: WrButton, selector: "wr-btn, button[wr-btn], a[wr-btn]", inputs: ["color", "size", "shape", "icon", "iconPosition", "disabled", "outlined", "block", "loading", "disabledWhenLoading"] }], encapsulation: i0.ViewEncapsulation.None });
53
53
  }
54
54
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: WrPopconfirmPanel, decorators: [{
55
55
  type: Component,
@@ -236,12 +236,13 @@ class WrPopconfirm {
236
236
  return this.dir?.value === 'rtl';
237
237
  }
238
238
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: WrPopconfirm, deps: [], target: i0.ɵɵFactoryTarget.Directive });
239
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.4", type: WrPopconfirm, isStandalone: true, selector: "[wrPopconfirm]", inputs: { message: { classPropertyName: "message", publicName: "wrPopconfirm", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, confirmText: { classPropertyName: "confirmText", publicName: "confirmText", isSignal: true, isRequired: false, transformFunction: null }, cancelText: { classPropertyName: "cancelText", publicName: "cancelText", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, confirmColor: { classPropertyName: "confirmColor", publicName: "confirmColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", cancelled: "cancelled" }, host: { listeners: { "click": "toggle($event)" }, properties: { "attr.aria-haspopup": "\"dialog\"", "attr.aria-expanded": "isOpen()", "attr.aria-controls": "isOpen() ? panelId : null" }, classAttribute: "wr-popconfirm-trigger" }, ngImport: i0 });
239
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.4", type: WrPopconfirm, isStandalone: true, selector: "[wrPopconfirm]", inputs: { message: { classPropertyName: "message", publicName: "wrPopconfirm", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, confirmText: { classPropertyName: "confirmText", publicName: "confirmText", isSignal: true, isRequired: false, transformFunction: null }, cancelText: { classPropertyName: "cancelText", publicName: "cancelText", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, confirmColor: { classPropertyName: "confirmColor", publicName: "confirmColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", cancelled: "cancelled" }, host: { listeners: { "click": "toggle($event)" }, properties: { "attr.aria-haspopup": "\"dialog\"", "attr.aria-expanded": "isOpen()", "attr.aria-controls": "isOpen() ? panelId : null" }, classAttribute: "wr-popconfirm-trigger" }, exportAs: ["wrPopconfirm"], ngImport: i0 });
240
240
  }
241
241
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: WrPopconfirm, decorators: [{
242
242
  type: Directive,
243
243
  args: [{
244
244
  selector: '[wrPopconfirm]',
245
+ exportAs: 'wrPopconfirm',
245
246
  host: {
246
247
  // Marks the trigger the way `[wrPopover]` and `[wrDropdown]` mark theirs. The
247
248
  // question is normally BOUND (`[wrPopconfirm]="question"`), which leaves no
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-popconfirm.mjs","sources":["../../../projects/lib/popconfirm/interfaces/popconfirm-position.ts","../../../projects/lib/popconfirm/popconfirm-panel.ts","../../../projects/lib/popconfirm/popconfirm-panel.html","../../../projects/lib/popconfirm/popconfirm.ts","../../../projects/lib/popconfirm/ngwr-popconfirm.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { ConnectedPosition } from '@angular/cdk/overlay';\n\nexport type WrPopconfirmPosition = 'top' | 'bottom' | 'left' | 'right';\n\n/** @internal */\nexport const WR_POPCONFIRM_POSITIONS: Record<WrPopconfirmPosition, ConnectedPosition[]> = {\n top: [{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 }],\n bottom: [{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 }],\n left: [{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 }],\n right: [{ originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 }],\n};\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Component, ViewEncapsulation, input, output } from '@angular/core';\n\nimport { WrButton } from 'ngwr/button';\nimport type { WrColor } from 'ngwr/theme';\n\n/**\n * Confirmation panel rendered inside the popconfirm overlay. Not part\n * of the public template API — use `[wrPopconfirm]` instead.\n *\n * @internal\n */\n@Component({\n selector: 'wr-popconfirm',\n templateUrl: './popconfirm-panel.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-popconfirm' },\n imports: [WrButton],\n})\nexport class WrPopconfirmPanel {\n readonly message = input.required<string>();\n\n /** Id the anchoring directive points `aria-describedby` at. */\n readonly messageId = input<string | null>(null);\n readonly confirmText = input<string>('Confirm');\n readonly cancelText = input<string>('Cancel');\n readonly confirmColor = input<WrColor>('primary');\n\n readonly confirmed = output<void>();\n readonly cancelled = output<void>();\n}\n","<p class=\"wr-popconfirm__message\" [attr.id]=\"messageId()\">{{ message() }}</p>\n\n<div class=\"wr-popconfirm__actions\">\n <wr-btn class=\"wr-popconfirm__action wr-popconfirm__action--cancel\" size=\"sm\" (click)=\"cancelled.emit()\">\n {{ cancelText() }}\n </wr-btn>\n <wr-btn\n class=\"wr-popconfirm__action wr-popconfirm__action--confirm\"\n size=\"sm\"\n [color]=\"confirmColor()\"\n (click)=\"confirmed.emit()\"\n >\n {{ confirmText() }}\n </wr-btn>\n</div>\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { type OverlayRef, ScrollStrategyOptions } from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { DestroyRef, Directive, ElementRef, ViewContainerRef, inject, input, output, signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nimport { useI18nText } from 'ngwr/i18n';\nimport { WR_OVERLAY, WrOutsideClick, wrMirrorOffsets } from 'ngwr/overlay';\nimport type { WrColor } from 'ngwr/theme';\n\nimport { WR_POPCONFIRM_POSITIONS, type WrPopconfirmPosition } from './interfaces';\nimport { WrPopconfirmPanel } from './popconfirm-panel';\n\n/**\n * Small \"Are you sure?\" panel anchored to its trigger. Fires `confirmed`\n * or `cancelled` and closes automatically. Built on CDK Overlay.\n *\n * @example\n * ```html\n * <wr-btn\n * color=\"danger\"\n * [wrPopconfirm]=\"'Delete this item?'\"\n * confirmColor=\"danger\"\n * confirmText=\"Delete\"\n * (confirmed)=\"remove()\"\n * >Delete</wr-btn>\n * ```\n *\n * @see https://ngwr.dev/reference/components/popconfirm\n */\nlet popconfirmUid = 0;\n\n@Directive({\n selector: '[wrPopconfirm]',\n host: {\n // Marks the trigger the way `[wrPopover]` and `[wrDropdown]` mark theirs. The\n // question is normally BOUND (`[wrPopconfirm]=\"question\"`), which leaves no\n // attribute in the DOM at all, so without this there is nothing to find a\n // trigger by once the panel is shut.\n class: 'wr-popconfirm-trigger',\n '(click)': 'toggle($event)',\n '[attr.aria-haspopup]': '\"dialog\"',\n '[attr.aria-expanded]': 'isOpen()',\n // Names the dialog this trigger opened, as every other overlay trigger in the\n // catalog does. `aria-haspopup=\"dialog\"` promises a dialog and `aria-expanded`\n // says it is showing; without the id, which one is left to guess.\n '[attr.aria-controls]': 'isOpen() ? panelId : null',\n },\n})\nexport class WrPopconfirm {\n /** Confirmation message. */\n readonly message = input.required<string>({ alias: 'wrPopconfirm' });\n\n /** Anchor side. @default 'top' */\n readonly position = input<WrPopconfirmPosition>('top');\n\n /** Label for the confirm button. @default 'Confirm' */\n /** Confirm button text. Falls back to `popconfirm.confirm`. */\n readonly confirmText = input<string | null>(null);\n\n /** Label for the cancel button. @default 'Cancel' */\n /** Cancel button text. Falls back to `popconfirm.cancel`. */\n readonly cancelText = input<string | null>(null);\n\n /**\n * Accessible name of the confirmation dialog. `role=\"dialog\"` with no name\n * announces as a bare \"dialog\". Falls back to `popconfirm.label`.\n */\n readonly ariaLabel = input<string | null>(null);\n\n // The catalog has carried these translated for as long as the component has\n // existed; the labels were hard-coded English defaults, so a localized app got\n // English buttons with the right strings sitting one file away.\n private readonly resolvedConfirm = useI18nText(this.confirmText, 'popconfirm.confirm', 'Confirm');\n private readonly resolvedCancel = useI18nText(this.cancelText, 'popconfirm.cancel', 'Cancel');\n private readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'popconfirm.label', 'Confirm action');\n\n /** Color of the confirm button. @default 'primary' */\n readonly confirmColor = input<WrColor>('primary');\n\n /** Fires when the user clicks confirm. */\n readonly confirmed = output<void>();\n\n /** Fires when the user clicks cancel or dismisses the overlay. */\n readonly cancelled = output<void>();\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly overlay = inject(WR_OVERLAY);\n private readonly dir = inject(Directionality, { optional: true });\n private readonly outsideClick = inject(WrOutsideClick);\n private readonly vcr = inject(ViewContainerRef);\n private readonly scrollStrategies = inject(ScrollStrategyOptions);\n private readonly destroyRef = inject(DestroyRef);\n\n /** @internal Public so the host bindings can read it. */\n readonly isOpen = signal(false);\n\n private overlayRef: OverlayRef | null = null;\n\n private readonly uid = ++popconfirmUid;\n\n /** @internal Public so the host binding can read it. */\n protected readonly panelId = `wr-popconfirm-${this.uid}`;\n\n private readonly messageId = `wr-popconfirm-message-${this.uid}`;\n\n constructor() {\n this.destroyRef.onDestroy(() => this.dispose());\n }\n\n /** @internal */\n protected toggle(event: MouseEvent): void {\n event.stopPropagation();\n if (this.overlayRef) {\n this.close();\n } else {\n this.open();\n }\n }\n\n open(): void {\n if (this.overlayRef) return;\n\n const positionStrategy = this.overlay\n .position()\n .flexibleConnectedTo(this.host)\n .withPositions(wrMirrorOffsets(WR_POPCONFIRM_POSITIONS[this.position()], this.isRtl()))\n .withPush(true);\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n scrollStrategy: this.scrollStrategies.reposition(),\n panelClass: ['wr-popconfirm-overlay', `wr-popconfirm-overlay--${this.position()}`],\n });\n\n // Non-modal by choice, like `wr-popover`: an outside click or Escape closes it,\n // so trapping focus would only make it harder to leave. It still needs a role, a\n // name and the question read out as its description.\n const pane = this.overlayRef.overlayElement;\n pane.id = this.panelId;\n pane.setAttribute('role', 'dialog');\n pane.setAttribute('aria-modal', 'false');\n pane.setAttribute('aria-label', this.resolvedAriaLabel());\n pane.setAttribute('aria-describedby', this.messageId);\n\n const portal = new ComponentPortal(WrPopconfirmPanel, this.vcr);\n const ref = this.overlayRef.attach(portal);\n ref.setInput('message', this.message());\n ref.setInput('messageId', this.messageId);\n ref.setInput('confirmText', this.resolvedConfirm());\n ref.setInput('cancelText', this.resolvedCancel());\n ref.setInput('confirmColor', this.confirmColor());\n // Render now rather than next frame: the buttons have to exist before focus can\n // move to one, and a deferred focus is the class of bug this repo keeps finding.\n ref.changeDetectorRef.detectChanges();\n // Focus has to enter the panel — the overlay container sits at the end of\n // `<body>`, so Tab from the trigger went to the next thing on the PAGE and the\n // only way to confirm was unreachable. Cancel first: the action being confirmed\n // is usually the destructive one.\n pane.querySelector<HTMLElement>('.wr-popconfirm__actions wr-btn')?.focus();\n this.isOpen.set(true);\n\n ref.instance.confirmed.subscribe(() => {\n this.confirmed.emit();\n this.close();\n });\n ref.instance.cancelled.subscribe(() => this.dismiss());\n\n this.outsideClick\n .outsidePointerEvents(this.overlayRef)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (this.host.nativeElement.contains(event.target as Node)) return;\n this.dismiss();\n });\n\n this.overlayRef\n .keydownEvents()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.dismiss();\n }\n });\n }\n\n close(): void {\n this.dispose();\n }\n\n private dismiss(): void {\n if (!this.overlayRef) return;\n this.cancelled.emit();\n this.dispose();\n }\n\n private dispose(): void {\n if (!this.overlayRef) return;\n // Focus lives inside the panel while it is open, and removing the panel would\n // drop it to `<body>` — hand it back to the trigger instead, as `wr-dropdown`\n // does on Escape. Only when focus is still IN there: if the user has already\n // clicked elsewhere, taking it back would be stealing.\n const returnFocus = this.overlayRef.overlayElement.contains(document.activeElement);\n this.overlayRef.dispose();\n this.overlayRef = null;\n this.isOpen.set(false);\n if (returnFocus) this.host.nativeElement.focus();\n }\n\n /**\n * Whether the app reads right-to-left.\n *\n * Optional inject: `Directionality` is root-provided, so this is never null in\n * an app — but a bare `TestBed` that provides nothing should still get a\n * component that works, and defaulting to LTR is the honest fallback.\n */\n private isRtl(): boolean {\n return this.dir?.value === 'rtl';\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngwr-popconfirm.mjs","sources":["../../../projects/lib/popconfirm/interfaces/popconfirm-position.ts","../../../projects/lib/popconfirm/popconfirm-panel.ts","../../../projects/lib/popconfirm/popconfirm-panel.html","../../../projects/lib/popconfirm/popconfirm.ts","../../../projects/lib/popconfirm/ngwr-popconfirm.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { ConnectedPosition } from '@angular/cdk/overlay';\n\nexport type WrPopconfirmPosition = 'top' | 'bottom' | 'left' | 'right';\n\n/** @internal */\nexport const WR_POPCONFIRM_POSITIONS: Record<WrPopconfirmPosition, ConnectedPosition[]> = {\n top: [{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 }],\n bottom: [{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 }],\n left: [{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 }],\n right: [{ originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 }],\n};\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Component, ViewEncapsulation, input, output } from '@angular/core';\n\nimport { WrButton } from 'ngwr/button';\nimport type { WrColor } from 'ngwr/theme';\n\n/**\n * Confirmation panel rendered inside the popconfirm overlay. Not part\n * of the public template API — use `[wrPopconfirm]` instead.\n *\n * @internal\n */\n@Component({\n selector: 'wr-popconfirm',\n templateUrl: './popconfirm-panel.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-popconfirm' },\n imports: [WrButton],\n})\nexport class WrPopconfirmPanel {\n readonly message = input.required<string>();\n\n /** Id the anchoring directive points `aria-describedby` at. */\n readonly messageId = input<string | null>(null);\n readonly confirmText = input<string>('Confirm');\n readonly cancelText = input<string>('Cancel');\n readonly confirmColor = input<WrColor>('primary');\n\n readonly confirmed = output<void>();\n readonly cancelled = output<void>();\n}\n","<p class=\"wr-popconfirm__message\" [attr.id]=\"messageId()\">{{ message() }}</p>\n\n<div class=\"wr-popconfirm__actions\">\n <wr-btn class=\"wr-popconfirm__action wr-popconfirm__action--cancel\" size=\"sm\" (click)=\"cancelled.emit()\">\n {{ cancelText() }}\n </wr-btn>\n <wr-btn\n class=\"wr-popconfirm__action wr-popconfirm__action--confirm\"\n size=\"sm\"\n [color]=\"confirmColor()\"\n (click)=\"confirmed.emit()\"\n >\n {{ confirmText() }}\n </wr-btn>\n</div>\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { type OverlayRef, ScrollStrategyOptions } from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { DestroyRef, Directive, ElementRef, ViewContainerRef, inject, input, output, signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nimport { useI18nText } from 'ngwr/i18n';\nimport { WR_OVERLAY, WrOutsideClick, wrMirrorOffsets } from 'ngwr/overlay';\nimport type { WrColor } from 'ngwr/theme';\n\nimport { WR_POPCONFIRM_POSITIONS, type WrPopconfirmPosition } from './interfaces';\nimport { WrPopconfirmPanel } from './popconfirm-panel';\n\n/**\n * Small \"Are you sure?\" panel anchored to its trigger. Fires `confirmed`\n * or `cancelled` and closes automatically. Built on CDK Overlay.\n *\n * @example\n * ```html\n * <wr-btn\n * color=\"danger\"\n * [wrPopconfirm]=\"'Delete this item?'\"\n * confirmColor=\"danger\"\n * confirmText=\"Delete\"\n * (confirmed)=\"remove()\"\n * >Delete</wr-btn>\n * ```\n *\n * @see https://ngwr.dev/reference/components/popconfirm\n */\nlet popconfirmUid = 0;\n\n@Directive({\n selector: '[wrPopconfirm]',\n exportAs: 'wrPopconfirm',\n host: {\n // Marks the trigger the way `[wrPopover]` and `[wrDropdown]` mark theirs. The\n // question is normally BOUND (`[wrPopconfirm]=\"question\"`), which leaves no\n // attribute in the DOM at all, so without this there is nothing to find a\n // trigger by once the panel is shut.\n class: 'wr-popconfirm-trigger',\n '(click)': 'toggle($event)',\n '[attr.aria-haspopup]': '\"dialog\"',\n '[attr.aria-expanded]': 'isOpen()',\n // Names the dialog this trigger opened, as every other overlay trigger in the\n // catalog does. `aria-haspopup=\"dialog\"` promises a dialog and `aria-expanded`\n // says it is showing; without the id, which one is left to guess.\n '[attr.aria-controls]': 'isOpen() ? panelId : null',\n },\n})\nexport class WrPopconfirm {\n /** Confirmation message. */\n readonly message = input.required<string>({ alias: 'wrPopconfirm' });\n\n /** Anchor side. @default 'top' */\n readonly position = input<WrPopconfirmPosition>('top');\n\n /** Label for the confirm button. @default 'Confirm' */\n /** Confirm button text. Falls back to `popconfirm.confirm`. */\n readonly confirmText = input<string | null>(null);\n\n /** Label for the cancel button. @default 'Cancel' */\n /** Cancel button text. Falls back to `popconfirm.cancel`. */\n readonly cancelText = input<string | null>(null);\n\n /**\n * Accessible name of the confirmation dialog. `role=\"dialog\"` with no name\n * announces as a bare \"dialog\". Falls back to `popconfirm.label`.\n */\n readonly ariaLabel = input<string | null>(null);\n\n // The catalog has carried these translated for as long as the component has\n // existed; the labels were hard-coded English defaults, so a localized app got\n // English buttons with the right strings sitting one file away.\n private readonly resolvedConfirm = useI18nText(this.confirmText, 'popconfirm.confirm', 'Confirm');\n private readonly resolvedCancel = useI18nText(this.cancelText, 'popconfirm.cancel', 'Cancel');\n private readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'popconfirm.label', 'Confirm action');\n\n /** Color of the confirm button. @default 'primary' */\n readonly confirmColor = input<WrColor>('primary');\n\n /** Fires when the user clicks confirm. */\n readonly confirmed = output<void>();\n\n /** Fires when the user clicks cancel or dismisses the overlay. */\n readonly cancelled = output<void>();\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly overlay = inject(WR_OVERLAY);\n private readonly dir = inject(Directionality, { optional: true });\n private readonly outsideClick = inject(WrOutsideClick);\n private readonly vcr = inject(ViewContainerRef);\n private readonly scrollStrategies = inject(ScrollStrategyOptions);\n private readonly destroyRef = inject(DestroyRef);\n\n /** @internal Public so the host bindings can read it. */\n readonly isOpen = signal(false);\n\n private overlayRef: OverlayRef | null = null;\n\n private readonly uid = ++popconfirmUid;\n\n /** @internal Public so the host binding can read it. */\n protected readonly panelId = `wr-popconfirm-${this.uid}`;\n\n private readonly messageId = `wr-popconfirm-message-${this.uid}`;\n\n constructor() {\n this.destroyRef.onDestroy(() => this.dispose());\n }\n\n /** @internal */\n protected toggle(event: MouseEvent): void {\n event.stopPropagation();\n if (this.overlayRef) {\n this.close();\n } else {\n this.open();\n }\n }\n\n open(): void {\n if (this.overlayRef) return;\n\n const positionStrategy = this.overlay\n .position()\n .flexibleConnectedTo(this.host)\n .withPositions(wrMirrorOffsets(WR_POPCONFIRM_POSITIONS[this.position()], this.isRtl()))\n .withPush(true);\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n scrollStrategy: this.scrollStrategies.reposition(),\n panelClass: ['wr-popconfirm-overlay', `wr-popconfirm-overlay--${this.position()}`],\n });\n\n // Non-modal by choice, like `wr-popover`: an outside click or Escape closes it,\n // so trapping focus would only make it harder to leave. It still needs a role, a\n // name and the question read out as its description.\n const pane = this.overlayRef.overlayElement;\n pane.id = this.panelId;\n pane.setAttribute('role', 'dialog');\n pane.setAttribute('aria-modal', 'false');\n pane.setAttribute('aria-label', this.resolvedAriaLabel());\n pane.setAttribute('aria-describedby', this.messageId);\n\n const portal = new ComponentPortal(WrPopconfirmPanel, this.vcr);\n const ref = this.overlayRef.attach(portal);\n ref.setInput('message', this.message());\n ref.setInput('messageId', this.messageId);\n ref.setInput('confirmText', this.resolvedConfirm());\n ref.setInput('cancelText', this.resolvedCancel());\n ref.setInput('confirmColor', this.confirmColor());\n // Render now rather than next frame: the buttons have to exist before focus can\n // move to one, and a deferred focus is the class of bug this repo keeps finding.\n ref.changeDetectorRef.detectChanges();\n // Focus has to enter the panel — the overlay container sits at the end of\n // `<body>`, so Tab from the trigger went to the next thing on the PAGE and the\n // only way to confirm was unreachable. Cancel first: the action being confirmed\n // is usually the destructive one.\n pane.querySelector<HTMLElement>('.wr-popconfirm__actions wr-btn')?.focus();\n this.isOpen.set(true);\n\n ref.instance.confirmed.subscribe(() => {\n this.confirmed.emit();\n this.close();\n });\n ref.instance.cancelled.subscribe(() => this.dismiss());\n\n this.outsideClick\n .outsidePointerEvents(this.overlayRef)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (this.host.nativeElement.contains(event.target as Node)) return;\n this.dismiss();\n });\n\n this.overlayRef\n .keydownEvents()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.dismiss();\n }\n });\n }\n\n close(): void {\n this.dispose();\n }\n\n private dismiss(): void {\n if (!this.overlayRef) return;\n this.cancelled.emit();\n this.dispose();\n }\n\n private dispose(): void {\n if (!this.overlayRef) return;\n // Focus lives inside the panel while it is open, and removing the panel would\n // drop it to `<body>` — hand it back to the trigger instead, as `wr-dropdown`\n // does on Escape. Only when focus is still IN there: if the user has already\n // clicked elsewhere, taking it back would be stealing.\n const returnFocus = this.overlayRef.overlayElement.contains(document.activeElement);\n this.overlayRef.dispose();\n this.overlayRef = null;\n this.isOpen.set(false);\n if (returnFocus) this.host.nativeElement.focus();\n }\n\n /**\n * Whether the app reads right-to-left.\n *\n * Optional inject: `Directionality` is root-provided, so this is never null in\n * an app — but a bare `TestBed` that provides nothing should still get a\n * component that works, and defaulting to LTR is the honest fallback.\n */\n private isRtl(): boolean {\n return this.dir?.value === 'rtl';\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -537,12 +537,13 @@ class WrPopover {
537
537
  return this.dir?.value === 'rtl';
538
538
  }
539
539
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: WrPopover, deps: [], target: i0.ɵɵFactoryTarget.Directive });
540
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.4", type: WrPopover, isStandalone: true, selector: "[wrPopover]", inputs: { content: { classPropertyName: "content", publicName: "wrPopover", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, showDelay: { classPropertyName: "showDelay", publicName: "showDelay", isSignal: true, isRequired: false, transformFunction: null }, hideDelay: { classPropertyName: "hideDelay", publicName: "hideDelay", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed" }, host: { listeners: { "click": "onClick($event)", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave($event)", "focus": "onFocus()", "blur": "onBlur()", "keydown.escape": "onEscape()" }, properties: { "attr.aria-haspopup": "isTooltip() ? null : \"dialog\"", "attr.aria-expanded": "isTooltip() ? null : isOpen()", "attr.aria-controls": "!isTooltip() && isOpen() ? panelId : null", "attr.aria-describedby": "isTooltip() && isOpen() ? panelId : null" }, classAttribute: "wr-popover-trigger" }, ngImport: i0 });
540
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.4", type: WrPopover, isStandalone: true, selector: "[wrPopover]", inputs: { content: { classPropertyName: "content", publicName: "wrPopover", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, showDelay: { classPropertyName: "showDelay", publicName: "showDelay", isSignal: true, isRequired: false, transformFunction: null }, hideDelay: { classPropertyName: "hideDelay", publicName: "hideDelay", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed" }, host: { listeners: { "click": "onClick($event)", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave($event)", "focus": "onFocus()", "blur": "onBlur()", "keydown.escape": "onEscape()" }, properties: { "attr.aria-haspopup": "isTooltip() ? null : \"dialog\"", "attr.aria-expanded": "isTooltip() ? null : isOpen()", "attr.aria-controls": "!isTooltip() && isOpen() ? panelId : null", "attr.aria-describedby": "isTooltip() && isOpen() ? panelId : null" }, classAttribute: "wr-popover-trigger" }, exportAs: ["wrPopover"], ngImport: i0 });
541
541
  }
542
542
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: WrPopover, decorators: [{
543
543
  type: Directive,
544
544
  args: [{
545
545
  selector: '[wrPopover]',
546
+ exportAs: 'wrPopover',
546
547
  host: {
547
548
  // Marks the trigger the way `[wrDropdown]` marks its own. Popover-mode
548
549
  // content is a `TemplateRef`, so it is always bound as `[wrPopover]="…"`,