ngwr 7.1.0 → 7.3.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 (99) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +5 -3
  3. package/alert/styles/_index.scss +2 -0
  4. package/back-top/styles/_index.scss +4 -2
  5. package/carousel/styles/_index.scss +2 -0
  6. package/cascader/styles/_index.scss +16 -0
  7. package/color-picker/styles/_index.scss +7 -0
  8. package/command-palette/styles/_index.scss +28 -0
  9. package/density/styles/_index.scss +10 -0
  10. package/descriptions/styles/_index.scss +59 -0
  11. package/dialog/styles/_index.scss +2 -0
  12. package/drawer/styles/_index.scss +2 -0
  13. package/dropdown/styles/_index.scss +1 -0
  14. package/fesm2022/ngwr-carousel.mjs +45 -4
  15. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  16. package/fesm2022/ngwr-cascader.mjs +2 -2
  17. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  18. package/fesm2022/ngwr-command-palette.mjs +17 -3
  19. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  20. package/fesm2022/ngwr-context-menu.mjs +77 -5
  21. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  22. package/fesm2022/ngwr-density.mjs +3 -3
  23. package/fesm2022/ngwr-density.mjs.map +1 -1
  24. package/fesm2022/ngwr-descriptions.mjs +11 -2
  25. package/fesm2022/ngwr-descriptions.mjs.map +1 -1
  26. package/fesm2022/ngwr-dialog.mjs +11 -4
  27. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  28. package/fesm2022/ngwr-drag-drop.mjs +13 -3
  29. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  30. package/fesm2022/ngwr-drawer.mjs +66 -5
  31. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  32. package/fesm2022/ngwr-dropdown.mjs +35 -11
  33. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  34. package/fesm2022/ngwr-lightbox.mjs +45 -2
  35. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  36. package/fesm2022/ngwr-overlay.mjs +70 -1
  37. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  38. package/fesm2022/ngwr-page-header.mjs +11 -3
  39. package/fesm2022/ngwr-page-header.mjs.map +1 -1
  40. package/fesm2022/ngwr-pagination.mjs +11 -3
  41. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  42. package/fesm2022/ngwr-popover.mjs +36 -10
  43. package/fesm2022/ngwr-popover.mjs.map +1 -1
  44. package/fesm2022/ngwr-rotating-text.mjs +15 -4
  45. package/fesm2022/ngwr-rotating-text.mjs.map +1 -1
  46. package/fesm2022/ngwr-select.mjs +35 -14
  47. package/fesm2022/ngwr-select.mjs.map +1 -1
  48. package/fesm2022/ngwr-stepper.mjs +11 -2
  49. package/fesm2022/ngwr-stepper.mjs.map +1 -1
  50. package/fesm2022/ngwr-table.mjs +10 -4
  51. package/fesm2022/ngwr-table.mjs.map +1 -1
  52. package/fesm2022/ngwr-tabs.mjs +38 -6
  53. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  54. package/fesm2022/ngwr-toast.mjs +54 -2
  55. package/fesm2022/ngwr-toast.mjs.map +1 -1
  56. package/fesm2022/ngwr-toolbar.mjs +11 -4
  57. package/fesm2022/ngwr-toolbar.mjs.map +1 -1
  58. package/fesm2022/ngwr-version.mjs +1 -1
  59. package/fesm2022/ngwr-version.mjs.map +1 -1
  60. package/lightbox/styles/_index.scss +4 -0
  61. package/llms-full.txt +673 -0
  62. package/llms.txt +106 -0
  63. package/overlay/styles/_index.scss +31 -0
  64. package/package.json +6 -5
  65. package/page-header/styles/_index.scss +16 -0
  66. package/pagination/styles/_index.scss +34 -0
  67. package/popover/styles/_index.scss +1 -0
  68. package/select/styles/_index.scss +27 -0
  69. package/slider/styles/_index.scss +3 -0
  70. package/splitter/styles/_index.scss +3 -0
  71. package/stepper/styles/_index.scss +30 -0
  72. package/styles.scss +1 -0
  73. package/table/styles/_index.scss +61 -0
  74. package/tabs/styles/_index.scss +24 -0
  75. package/theme/styles/_mixins.scss +47 -0
  76. package/toast/styles/_index.scss +32 -1
  77. package/toolbar/styles/_index.scss +29 -0
  78. package/tree/styles/_index.scss +15 -0
  79. package/types/ngwr-carousel.d.ts +8 -1
  80. package/types/ngwr-command-palette.d.ts +13 -1
  81. package/types/ngwr-context-menu.d.ts +25 -3
  82. package/types/ngwr-density.d.ts +2 -2
  83. package/types/ngwr-descriptions.d.ts +8 -1
  84. package/types/ngwr-dialog.d.ts +7 -0
  85. package/types/ngwr-drag-drop.d.ts +13 -1
  86. package/types/ngwr-drawer.d.ts +11 -3
  87. package/types/ngwr-dropdown.d.ts +10 -1
  88. package/types/ngwr-lightbox.d.ts +5 -0
  89. package/types/ngwr-overlay.d.ts +69 -1
  90. package/types/ngwr-page-header.d.ts +8 -1
  91. package/types/ngwr-pagination.d.ts +7 -1
  92. package/types/ngwr-popover.d.ts +10 -1
  93. package/types/ngwr-rotating-text.d.ts +1 -0
  94. package/types/ngwr-select.d.ts +10 -1
  95. package/types/ngwr-stepper.d.ts +8 -1
  96. package/types/ngwr-table.d.ts +7 -1
  97. package/types/ngwr-tabs.d.ts +6 -0
  98. package/types/ngwr-toolbar.d.ts +7 -1
  99. package/types/ngwr-version.d.ts +1 -1
@@ -1,3 +1,4 @@
1
+ import { coerceBooleanProperty } from '@angular/cdk/coercion';
1
2
  import * as i0 from '@angular/core';
2
3
  import { input, ViewEncapsulation, Component } from '@angular/core';
3
4
 
@@ -37,13 +38,20 @@ class WrPageHeader {
37
38
  /** Secondary line below the title. */
38
39
  subtitle = input('', /* @ts-ignore */
39
40
  ...(ngDevMode ? [{ debugName: "subtitle" }] : /* istanbul ignore next */ []));
41
+ /**
42
+ * Stack the title and actions vertically when the header's own box is too
43
+ * narrow to sit them side by side (a container query on its own width, not
44
+ * the viewport — so it adapts inside a narrow column or split pane).
45
+ * @default false
46
+ */
47
+ responsive = input(false, { ...(ngDevMode ? { debugName: "responsive" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
40
48
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrPageHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
41
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: WrPageHeader, isStandalone: true, selector: "wr-page-header", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-page-header" }, ngImport: i0, template: "<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
49
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: WrPageHeader, isStandalone: true, selector: "wr-page-header", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.wr-page-header--responsive": "responsive()" }, classAttribute: "wr-page-header" }, ngImport: i0, template: "<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
42
50
  }
43
51
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrPageHeader, decorators: [{
44
52
  type: Component,
45
- args: [{ selector: 'wr-page-header', encapsulation: ViewEncapsulation.None, host: { class: 'wr-page-header' }, template: "<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n" }]
46
- }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }] } });
53
+ args: [{ selector: 'wr-page-header', encapsulation: ViewEncapsulation.None, host: { class: 'wr-page-header', '[class.wr-page-header--responsive]': 'responsive()' }, template: "<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n" }]
54
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }] } });
47
55
 
48
56
  /**
49
57
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-page-header.mjs","sources":["../../../projects/lib/page-header/page-header.ts","../../../projects/lib/page-header/page-header.html","../../../projects/lib/page-header/ngwr-page-header.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 { Component, ViewEncapsulation, input } from '@angular/core';\n\n/**\n * Top-of-page heading block. Three named slots via attribute selectors:\n * `[wrPageHeaderBreadcrumbs]` (top row), `[wrPageHeaderActions]` (right\n * side), `[wrPageHeaderExtra]` (bottom row of tags / metadata). Title +\n * subtitle come from inputs.\n *\n * @example\n * ```html\n * <wr-page-header title=\"Settings\" subtitle=\"Manage your workspace\">\n * <nav wrPageHeaderBreadcrumbs>…</nav>\n * <div wrPageHeaderActions>\n * <button wrButton>Invite</button>\n * <button wrButton color=\"primary\">Save</button>\n * </div>\n * <div wrPageHeaderExtra>\n * <wr-tag>v2.4</wr-tag>\n * <wr-tag color=\"success\">Stable</wr-tag>\n * </div>\n * </wr-page-header>\n * ```\n *\n * @see https://ngwr.dev/components/page-header\n */\n@Component({\n selector: 'wr-page-header',\n templateUrl: './page-header.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-page-header' },\n})\nexport class WrPageHeader {\n /** Primary title shown as an h1. */\n readonly title = input<string>('');\n\n /** Secondary line below the title. */\n readonly subtitle = input<string>('');\n}\n","<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;AAAA;;;;;AAKG;AAIH;;;;;;;;;;;;;;;;;;;;;;AAsBG;MAOU,YAAY,CAAA;;IAEd,KAAK,GAAG,KAAK,CAAS,EAAE;8EAAC;;IAGzB,QAAQ,GAAG,KAAK,CAAS,EAAE;iFAAC;uGAL1B,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAY,2XCtCzB,0lBAqBA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FDiBa,YAAY,EAAA,UAAA,EAAA,CAAA;kBANxB,SAAS;+BACE,gBAAgB,EAAA,aAAA,EAEX,iBAAiB,CAAC,IAAI,QAC/B,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAA,QAAA,EAAA,0lBAAA,EAAA;;;AEpCnC;;AAEG;;;;"}
1
+ {"version":3,"file":"ngwr-page-header.mjs","sources":["../../../projects/lib/page-header/page-header.ts","../../../projects/lib/page-header/page-header.html","../../../projects/lib/page-header/ngwr-page-header.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, input } from '@angular/core';\n\n/**\n * Top-of-page heading block. Three named slots via attribute selectors:\n * `[wrPageHeaderBreadcrumbs]` (top row), `[wrPageHeaderActions]` (right\n * side), `[wrPageHeaderExtra]` (bottom row of tags / metadata). Title +\n * subtitle come from inputs.\n *\n * @example\n * ```html\n * <wr-page-header title=\"Settings\" subtitle=\"Manage your workspace\">\n * <nav wrPageHeaderBreadcrumbs>…</nav>\n * <div wrPageHeaderActions>\n * <button wrButton>Invite</button>\n * <button wrButton color=\"primary\">Save</button>\n * </div>\n * <div wrPageHeaderExtra>\n * <wr-tag>v2.4</wr-tag>\n * <wr-tag color=\"success\">Stable</wr-tag>\n * </div>\n * </wr-page-header>\n * ```\n *\n * @see https://ngwr.dev/components/page-header\n */\n@Component({\n selector: 'wr-page-header',\n templateUrl: './page-header.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-page-header', '[class.wr-page-header--responsive]': 'responsive()' },\n})\nexport class WrPageHeader {\n /** Primary title shown as an h1. */\n readonly title = input<string>('');\n\n /** Secondary line below the title. */\n readonly subtitle = input<string>('');\n\n /**\n * Stack the title and actions vertically when the header's own box is too\n * narrow to sit them side by side (a container query on its own width, not\n * the viewport — so it adapts inside a narrow column or split pane).\n * @default false\n */\n readonly responsive = input(false, { transform: coerceBooleanProperty });\n}\n","<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;AAAA;;;;;AAKG;AAKH;;;;;;;;;;;;;;;;;;;;;;AAsBG;MAOU,YAAY,CAAA;;IAEd,KAAK,GAAG,KAAK,CAAS,EAAE;8EAAC;;IAGzB,QAAQ,GAAG,KAAK,CAAS,EAAE;iFAAC;AAErC;;;;;AAKG;IACM,UAAU,GAAG,KAAK,CAAC,KAAK,kFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;uGAb7D,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAY,skBCvCzB,0lBAqBA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FDkBa,YAAY,EAAA,UAAA,EAAA,CAAA;kBANxB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,gBAAgB,EAAA,aAAA,EAEX,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B,EAAE,KAAK,EAAE,gBAAgB,EAAE,oCAAoC,EAAE,cAAc,EAAE,EAAA,QAAA,EAAA,0lBAAA,EAAA;;;AErCzF;;AAEG;;;;"}
@@ -70,6 +70,12 @@ class WrPagination {
70
70
  ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
71
71
  /** Disable interaction. @default false */
72
72
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
73
+ /**
74
+ * Collapse to a compact `‹ page / total ›` pager when the control's own box
75
+ * is too narrow for the full numbered strip (a container query on its own
76
+ * width, not the viewport). @default false
77
+ */
78
+ responsive = input(false, { ...(ngDevMode ? { debugName: "responsive" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
73
79
  /** Localised text between range and total ("X–Y of Z"). Falls back to `pagination.of` then `'of'`. */
74
80
  ofLabel = input(null, /* @ts-ignore */
75
81
  ...(ngDevMode ? [{ debugName: "ofLabel" }] : /* istanbul ignore next */ []));
@@ -144,6 +150,8 @@ class WrPagination {
144
150
  ];
145
151
  if (this.disabled())
146
152
  parts.push('wr-pagination--disabled');
153
+ if (this.responsive())
154
+ parts.push('wr-pagination--responsive');
147
155
  return parts.join(' ');
148
156
  }, /* @ts-ignore */
149
157
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
@@ -166,12 +174,12 @@ class WrPagination {
166
174
  this.currentPage.set(cap);
167
175
  }
168
176
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrPagination, deps: [], target: i0.ɵɵFactoryTarget.Component });
169
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", 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 }, 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 } }, outputs: { currentPage: "currentPageChange", pageSize: "pageSizeChange" }, host: { attributes: { "role": "navigation", "aria-label": "Pagination" }, properties: { "class": "classes()" } }, 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 <wr-btn\n [size]=\"buttonSize()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || currentPage() === 1\"\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=\"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 [size]=\"buttonSize()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"`Go to page ${page}`\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <wr-btn\n [size]=\"buttonSize()\"\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 <wr-select\n class=\"wr-pagination__size\"\n [attr.aria-label]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"pageSize()\"\n (ngModelChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ option }} / page</wr-option>\n }\n </wr-select>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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", "disabled", "rounded", "mode", "options", "displayWith", "loader", "debounceMs", "minChars", "freeText", "noResultsText", "loadingText", "separators", "allowDuplicates", "validate", "clearable", "maxItems", "maxTagCount"] }, { kind: "component", type: WrOption, selector: "wr-option", inputs: ["value", "disabled"] }], encapsulation: i0.ViewEncapsulation.None });
177
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", 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 } }, outputs: { currentPage: "currentPageChange", pageSize: "pageSizeChange" }, host: { attributes: { "role": "navigation", "aria-label": "Pagination" }, properties: { "class": "classes()" } }, 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 <wr-btn\n [size]=\"buttonSize()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || currentPage() === 1\"\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=\"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]=\"buttonSize()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"`Go to page ${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 [size]=\"buttonSize()\"\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 <wr-select\n class=\"wr-pagination__size\"\n [attr.aria-label]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"pageSize()\"\n (ngModelChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ option }} / page</wr-option>\n }\n </wr-select>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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", "disabled", "rounded", "responsive", "mode", "options", "displayWith", "loader", "debounceMs", "minChars", "freeText", "noResultsText", "loadingText", "separators", "allowDuplicates", "validate", "clearable", "maxItems", "maxTagCount"] }, { kind: "component", type: WrOption, selector: "wr-option", inputs: ["value", "disabled"] }], encapsulation: i0.ViewEncapsulation.None });
170
178
  }
171
179
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrPagination, decorators: [{
172
180
  type: Component,
173
- args: [{ selector: 'wr-pagination', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()', role: 'navigation', 'aria-label': 'Pagination' }, imports: [FormsModule, 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 <wr-btn\n [size]=\"buttonSize()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || currentPage() === 1\"\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=\"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 [size]=\"buttonSize()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"`Go to page ${page}`\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <wr-btn\n [size]=\"buttonSize()\"\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 <wr-select\n class=\"wr-pagination__size\"\n [attr.aria-label]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"pageSize()\"\n (ngModelChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ option }} / page</wr-option>\n }\n </wr-select>\n }\n</div>\n" }]
174
- }], 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 }] }], 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 }] }] } });
181
+ args: [{ selector: 'wr-pagination', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()', role: 'navigation', 'aria-label': 'Pagination' }, imports: [FormsModule, 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 <wr-btn\n [size]=\"buttonSize()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || currentPage() === 1\"\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=\"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]=\"buttonSize()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"`Go to page ${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 [size]=\"buttonSize()\"\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 <wr-select\n class=\"wr-pagination__size\"\n [attr.aria-label]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"pageSize()\"\n (ngModelChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ option }} / page</wr-option>\n }\n </wr-select>\n }\n</div>\n" }]
182
+ }], 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 }] }] } });
175
183
 
176
184
  /**
177
185
  * 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, input, model } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { WrButton, type WrButtonSize } from 'ngwr/button';\nimport { 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/components/pagination\n */\n@Component({\n selector: 'wr-pagination',\n templateUrl: './pagination.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()', role: 'navigation', 'aria-label': 'Pagination' },\n imports: [FormsModule, 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 'md' */\n readonly size = input<WrPaginationSize>('sm');\n\n /** Resolved button size — clamps xs/xl to the closest button size. @internal */\n protected readonly buttonSize = computed<WrButtonSize>(() => {\n const s = this.size();\n if (s === 'xs') return 'sm';\n if (s === 'xl') return 'lg';\n return s;\n });\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 /** 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 /** 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 /** Internal: total page count. */\n protected readonly totalPages = computed(() => Math.max(1, Math.ceil(this.total() / this.pageSize())));\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 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 protected onSizeChange(size: number): void {\n if (this.disabled() || size === this.pageSize()) return;\n this.pageSize.set(size);\n const cap = Math.max(1, Math.ceil(this.total() / size));\n if (this.currentPage() > cap) this.currentPage.set(cap);\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 <wr-btn\n [size]=\"buttonSize()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || currentPage() === 1\"\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=\"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 [size]=\"buttonSize()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"`Go to page ${page}`\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <wr-btn\n [size]=\"buttonSize()\"\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 <wr-select\n class=\"wr-pagination__size\"\n [attr.aria-label]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"pageSize()\"\n (ngModelChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ option }} / page</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, ViewEncapsulation, computed, input, model } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { WrButton, type WrButtonSize } from 'ngwr/button';\nimport { 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/components/pagination\n */\n@Component({\n selector: 'wr-pagination',\n templateUrl: './pagination.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()', role: 'navigation', 'aria-label': 'Pagination' },\n imports: [FormsModule, 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 'md' */\n readonly size = input<WrPaginationSize>('sm');\n\n /** Resolved button size — clamps xs/xl to the closest button size. @internal */\n protected readonly buttonSize = computed<WrButtonSize>(() => {\n const s = this.size();\n if (s === 'xs') return 'sm';\n if (s === 'xl') return 'lg';\n return s;\n });\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 /** 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 /** Internal: total page count. */\n protected readonly totalPages = computed(() => Math.max(1, Math.ceil(this.total() / this.pageSize())));\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 protected onSizeChange(size: number): void {\n if (this.disabled() || size === this.pageSize()) return;\n this.pageSize.set(size);\n const cap = Math.max(1, Math.ceil(this.total() / size));\n if (this.currentPage() > cap) this.currentPage.set(cap);\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 <wr-btn\n [size]=\"buttonSize()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || currentPage() === 1\"\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=\"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]=\"buttonSize()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"`Go to page ${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 [size]=\"buttonSize()\"\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 <wr-select\n class=\"wr-pagination__size\"\n [attr.aria-label]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"pageSize()\"\n (ngModelChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ option }} / page</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,9 +1,10 @@
1
+ import { coerceBooleanProperty } from '@angular/cdk/coercion';
1
2
  import { ScrollStrategyOptions } from '@angular/cdk/overlay';
2
3
  import { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';
3
4
  import * as i0 from '@angular/core';
4
5
  import { input, ViewEncapsulation, Component, output, inject, ElementRef, ViewContainerRef, DestroyRef, signal, computed, effect, Directive } from '@angular/core';
5
6
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
- import { WR_OVERLAY } from 'ngwr/overlay';
7
+ import { WR_OVERLAY, WR_RESPONSIVE_OVERLAYS, wrPresentAsSheet } from 'ngwr/overlay';
7
8
  import { numAttr } from 'ngwr/utils';
8
9
 
9
10
  /**
@@ -124,12 +125,20 @@ class WrPopover {
124
125
  showDelay = input(120, { ...(ngDevMode ? { debugName: "showDelay" } : /* istanbul ignore next */ {}), transform: numAttr(120) });
125
126
  /** Tooltip only — delay before hiding, in ms. @default 60 */
126
127
  hideDelay = input(60, { ...(ngDevMode ? { debugName: "hideDelay" } : /* istanbul ignore next */ {}), transform: numAttr(60) });
128
+ /**
129
+ * Popover mode only — present the panel as a full-width bottom-sheet on
130
+ * small viewports instead of an anchored panel. `undefined` follows the
131
+ * app-wide `provideWrResponsiveOverlays()` setting; `true`/`false`
132
+ * overrides it. Tooltips never become sheets. @default undefined
133
+ */
134
+ responsive = input(undefined, { ...(ngDevMode ? { debugName: "responsive" } : /* istanbul ignore next */ {}), transform: (v) => (v == null ? undefined : coerceBooleanProperty(v)) });
127
135
  /** Fires after the panel opens. */
128
136
  opened = output();
129
137
  /** Fires after the panel closes. */
130
138
  closed = output();
131
139
  host = inject(ElementRef);
132
140
  overlay = inject(WR_OVERLAY);
141
+ responsiveConfig = inject(WR_RESPONSIVE_OVERLAYS);
133
142
  vcr = inject(ViewContainerRef);
134
143
  scrollStrategies = inject(ScrollStrategyOptions);
135
144
  destroyRef = inject(DestroyRef);
@@ -255,19 +264,36 @@ class WrPopover {
255
264
  return;
256
265
  const tooltip = this.isTooltip();
257
266
  const position = this.resolvedPosition();
258
- const positionStrategy = this.overlay
259
- .position()
260
- .flexibleConnectedTo(this.host)
261
- .withPositions(WR_POPOVER_POSITIONS[position])
262
- .withPush(true);
267
+ // Sheet presentation is popover-only — tooltips are transient labels and
268
+ // never dock to the bottom. On small viewports (when opted in) detach
269
+ // from the trigger and slide the panel up from the bottom edge.
270
+ const asSheet = !tooltip && wrPresentAsSheet(this.responsive(), this.responsiveConfig);
271
+ const positionStrategy = asSheet
272
+ ? this.overlay.position().global().centerHorizontally().bottom('0')
273
+ : this.overlay
274
+ .position()
275
+ .flexibleConnectedTo(this.host)
276
+ .withPositions(WR_POPOVER_POSITIONS[position])
277
+ .withPush(true);
263
278
  const overlayClass = tooltip
264
279
  ? ['wr-tooltip-overlay', `wr-tooltip-overlay--${position}`]
265
- : ['wr-popover-overlay', `wr-popover-overlay--${position}`];
280
+ : asSheet
281
+ ? ['wr-popover-overlay', 'wr-overlay-sheet']
282
+ : ['wr-popover-overlay', `wr-popover-overlay--${position}`];
266
283
  this.overlayRef = this.overlay.create({
267
284
  positionStrategy,
268
- scrollStrategy: this.scrollStrategies.reposition(),
285
+ scrollStrategy: asSheet ? this.scrollStrategies.block() : this.scrollStrategies.reposition(),
286
+ width: asSheet ? '100%' : undefined,
287
+ hasBackdrop: asSheet,
288
+ backdropClass: asSheet ? 'wr-overlay-backdrop' : undefined,
269
289
  panelClass: overlayClass,
270
290
  });
291
+ if (asSheet) {
292
+ this.overlayRef
293
+ .backdropClick()
294
+ .pipe(takeUntilDestroyed(this.destroyRef))
295
+ .subscribe(() => this.isOpen.set(false));
296
+ }
271
297
  const content = this.content();
272
298
  if (tooltip) {
273
299
  // Text content rendered via the internal text panel — accepts a
@@ -336,7 +362,7 @@ class WrPopover {
336
362
  }
337
363
  }
338
364
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrPopover, deps: [], target: i0.ɵɵFactoryTarget.Directive });
339
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", 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 } }, 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" } }, ngImport: i0 });
365
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", 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 } }, 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" } }, ngImport: i0 });
340
366
  }
341
367
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrPopover, decorators: [{
342
368
  type: Directive,
@@ -355,7 +381,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
355
381
  '(keydown.escape)': 'onEscape()',
356
382
  },
357
383
  }]
358
- }], ctorParameters: () => [], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrPopover", required: true }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], showDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDelay", required: false }] }], hideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideDelay", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
384
+ }], ctorParameters: () => [], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrPopover", required: true }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], showDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDelay", required: false }] }], hideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideDelay", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
359
385
 
360
386
  /**
361
387
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-popover.mjs","sources":["../../../projects/lib/popover/interfaces/popover-position.ts","../../../projects/lib/popover/internal/text-panel.ts","../../../projects/lib/popover/popover.ts","../../../projects/lib/popover/ngwr-popover.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 WrPopoverPosition =\n | 'top'\n | 'top-start'\n | 'top-end'\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'left'\n | 'left-start'\n | 'left-end'\n | 'right'\n | 'right-start'\n | 'right-end';\n\n/** @internal */\nexport const WR_POPOVER_POSITIONS: Record<WrPopoverPosition, ConnectedPosition[]> = {\n top: [{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 }],\n 'top-start': [{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -8 }],\n 'top-end': [{ originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -8 }],\n bottom: [{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 }],\n 'bottom-start': [{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 8 }],\n 'bottom-end': [{ originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 8 }],\n left: [{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 }],\n 'left-start': [{ originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top', offsetX: -8 }],\n 'left-end': [{ originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom', offsetX: -8 }],\n right: [{ originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 }],\n 'right-start': [{ originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top', offsetX: 8 }],\n 'right-end': [{ originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom', 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 } from '@angular/core';\n\n/**\n * Internal floating label rendered when `<… [wrPopover]=\"'…'\" mode=\"tooltip\">`\n * receives a string instead of a template. Not part of the public template\n * API — use the `WrPopover` directive in tooltip mode instead.\n *\n * @internal\n */\n@Component({\n selector: 'wr-popover-text',\n template: '{{ text() }}',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-tooltip', role: 'tooltip' },\n})\nexport class WrPopoverTextPanel {\n readonly text = input.required<string>();\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 { type OverlayRef, ScrollStrategyOptions } from '@angular/cdk/overlay';\nimport { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';\nimport type { TemplateRef } from '@angular/core';\nimport {\n DestroyRef,\n Directive,\n ElementRef,\n ViewContainerRef,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nimport { WR_OVERLAY } from 'ngwr/overlay';\nimport { numAttr } from 'ngwr/utils';\n\nimport { WR_POPOVER_POSITIONS, type WrPopoverPosition } from './interfaces';\nimport { WrPopoverTextPanel } from './internal/text-panel';\n\n/**\n * Anchored content panel. The same directive covers two shapes:\n *\n * - **Popover** (default, `mode=\"popover\"`) — `[wrPopover]` takes a\n * `TemplateRef`. Opens on click or hover. Use for rich anchored content:\n * forms, summaries, menus.\n *\n * - **Tooltip** (`mode=\"tooltip\"`) — `[wrPopover]` takes a plain string.\n * Shown on hover and focus, dismissed on blur / pointer-leave / Escape.\n * Uses `aria-describedby` instead of `aria-haspopup` and is rendered into\n * a small dark text panel.\n *\n * Built on CDK Overlay so it auto-flips, closes on outside-click and Escape.\n *\n * @example\n * ```html\n * <!-- Popover with template content -->\n * <button wr-btn [wrPopover]=\"info\">Details</button>\n * <ng-template #info>\n * <div style=\"padding: 1rem; max-width: 18rem\">Anything you can render.</div>\n * </ng-template>\n *\n * <!-- Tooltip with plain text -->\n * <button wr-btn [wrPopover]=\"'Save changes'\" mode=\"tooltip\" position=\"top\">\n * Save\n * </button>\n * ```\n *\n * @see https://ngwr.dev/components/popover\n */\nlet popoverUid = 0;\n\n@Directive({\n selector: '[wrPopover]',\n host: {\n '[attr.aria-haspopup]': 'isTooltip() ? null : \"dialog\"',\n '[attr.aria-expanded]': 'isTooltip() ? null : isOpen()',\n '[attr.aria-controls]': '!isTooltip() && isOpen() ? panelId : null',\n '[attr.aria-describedby]': 'isTooltip() && isOpen() ? panelId : null',\n '(click)': 'onClick($event)',\n '(mouseenter)': 'onMouseEnter()',\n '(mouseleave)': 'onMouseLeave($event)',\n '(focus)': 'onFocus()',\n '(blur)': 'onBlur()',\n '(keydown.escape)': 'onEscape()',\n },\n})\nexport class WrPopover {\n /**\n * Content to render inside the panel.\n * - In **popover** mode (default): pass a `TemplateRef`.\n * - In **tooltip** mode: pass a plain string.\n */\n readonly content = input.required<TemplateRef<unknown> | string>({ alias: 'wrPopover' });\n\n /**\n * Shape preset.\n *\n * - `'popover'` (default) — template content, click trigger, dialog\n * semantics.\n * - `'tooltip'` — text content, hover+focus trigger, `role=\"tooltip\"`,\n * `aria-describedby` on the host.\n */\n readonly mode = input<'popover' | 'tooltip'>('popover');\n\n /**\n * How the popover opens. Ignored in tooltip mode — tooltips are always\n * hover+focus. @default 'click'\n */\n readonly trigger = input<'click' | 'hover'>('click');\n\n /** Anchor side. @default 'bottom' for popover, 'top' for tooltip */\n readonly position = input<WrPopoverPosition | null>(null);\n\n /** Tooltip only — delay before showing, in ms. @default 120 */\n readonly showDelay = input(120, { transform: numAttr(120) });\n\n /** Tooltip only — delay before hiding, in ms. @default 60 */\n readonly hideDelay = input(60, { transform: numAttr(60) });\n\n /** Fires after the panel opens. */\n readonly opened = output<void>();\n\n /** Fires after the panel closes. */\n readonly closed = output<void>();\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly overlay = inject(WR_OVERLAY);\n private readonly vcr = inject(ViewContainerRef);\n private readonly scrollStrategies = inject(ScrollStrategyOptions);\n private readonly destroyRef = inject(DestroyRef);\n\n /** @internal */\n readonly isOpen = signal(false);\n\n /** @internal */\n protected readonly isTooltip = computed(() => this.mode() === 'tooltip');\n\n /** Auto-generated id for `aria-controls` / `aria-describedby`. */\n protected readonly panelId = `wr-popover-${++popoverUid}`;\n\n private readonly resolvedPosition = computed<WrPopoverPosition>(\n () => this.position() ?? (this.isTooltip() ? 'top' : 'bottom')\n );\n\n private overlayRef: OverlayRef | null = null;\n private hoverCloseTimer: ReturnType<typeof setTimeout> | null = null;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n effect(() => {\n if (this.isOpen()) {\n this.openOverlay();\n } else {\n this.closeOverlay();\n }\n });\n this.destroyRef.onDestroy(() => {\n this.clearTimers();\n this.closeOverlay();\n });\n }\n\n open(): void {\n this.isOpen.set(true);\n }\n\n close(): void {\n this.isOpen.set(false);\n }\n\n toggle(): void {\n this.isOpen.update(v => !v);\n }\n\n // Host listeners\n\n /** @internal */\n protected onClick(event: MouseEvent): void {\n if (this.isTooltip() || this.trigger() !== 'click') return;\n event.stopPropagation();\n this.toggle();\n }\n\n /** @internal */\n protected onMouseEnter(): void {\n if (this.isTooltip()) {\n this.scheduleShow();\n return;\n }\n if (this.trigger() !== 'hover') return;\n this.clearHoverClose();\n this.isOpen.set(true);\n }\n\n /** @internal */\n protected onMouseLeave(event: MouseEvent): void {\n if (this.isTooltip()) {\n this.scheduleHide();\n return;\n }\n if (this.trigger() !== 'hover') return;\n const related = event.relatedTarget as Node | null;\n if (related && this.overlayRef?.overlayElement.contains(related)) return;\n // Delay so the pointer can cross the gap between trigger and panel —\n // entering the panel cancels the close (see attach listeners).\n this.scheduleHoverClose();\n }\n\n /** @internal */\n protected onFocus(): void {\n if (!this.isTooltip()) return;\n this.scheduleShow();\n }\n\n /** @internal */\n protected onBlur(): void {\n if (!this.isTooltip()) return;\n this.scheduleHide();\n }\n\n /** @internal */\n protected onEscape(): void {\n if (!this.isTooltip()) return;\n this.clearTimers();\n this.isOpen.set(false);\n }\n\n // Tooltip timers\n\n private scheduleShow(): void {\n if (this.isOpen()) {\n this.clearTimers();\n return;\n }\n const text = this.content();\n if (typeof text === 'string' && !text) return;\n this.clearTimers();\n this.showTimer = setTimeout(() => this.isOpen.set(true), this.showDelay());\n }\n\n private scheduleHide(): void {\n this.clearTimers();\n this.hideTimer = setTimeout(() => this.isOpen.set(false), this.hideDelay());\n }\n\n private clearTimers(): void {\n if (this.showTimer) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n\n // Overlay\n\n private openOverlay(): void {\n if (this.overlayRef) return;\n\n const tooltip = this.isTooltip();\n const position = this.resolvedPosition();\n\n const positionStrategy = this.overlay\n .position()\n .flexibleConnectedTo(this.host)\n .withPositions(WR_POPOVER_POSITIONS[position])\n .withPush(true);\n\n const overlayClass = tooltip\n ? ['wr-tooltip-overlay', `wr-tooltip-overlay--${position}`]\n : ['wr-popover-overlay', `wr-popover-overlay--${position}`];\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n scrollStrategy: this.scrollStrategies.reposition(),\n panelClass: overlayClass,\n });\n\n const content = this.content();\n\n if (tooltip) {\n // Text content rendered via the internal text panel — accepts a\n // string and wraps it in the `.wr-tooltip` shell.\n const text = typeof content === 'string' ? content : '';\n const ref = this.overlayRef.attach(new ComponentPortal(WrPopoverTextPanel, this.vcr));\n ref.setInput('text', text);\n this.overlayRef.overlayElement.setAttribute('role', 'tooltip');\n } else if (typeof content !== 'string') {\n this.overlayRef.attach(new TemplatePortal(content, this.vcr));\n }\n this.overlayRef.overlayElement.id = this.panelId;\n\n this.overlayRef\n .outsidePointerEvents()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (this.host.nativeElement.contains(event.target as Node)) return;\n this.isOpen.set(false);\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.isOpen.set(false);\n }\n });\n\n if (!tooltip && this.trigger() === 'hover') {\n this.overlayRef.overlayElement.addEventListener('mouseenter', this.onOverlayEnter);\n this.overlayRef.overlayElement.addEventListener('mouseleave', this.onOverlayLeave);\n }\n\n this.opened.emit();\n }\n\n private closeOverlay(): void {\n if (!this.overlayRef) return;\n if (!this.isTooltip() && this.trigger() === 'hover') {\n this.overlayRef.overlayElement.removeEventListener('mouseenter', this.onOverlayEnter);\n this.overlayRef.overlayElement.removeEventListener('mouseleave', this.onOverlayLeave);\n }\n this.clearHoverClose();\n this.overlayRef.dispose();\n this.overlayRef = null;\n this.closed.emit();\n }\n\n private readonly onOverlayLeave = (event: MouseEvent): void => {\n const related = event.relatedTarget as Node | null;\n if (related && this.host.nativeElement.contains(related)) return;\n this.scheduleHoverClose();\n };\n\n private readonly onOverlayEnter = (): void => {\n this.clearHoverClose();\n };\n\n private scheduleHoverClose(): void {\n this.clearHoverClose();\n this.hoverCloseTimer = setTimeout(() => this.isOpen.set(false), 120);\n }\n\n private clearHoverClose(): void {\n if (this.hoverCloseTimer) {\n clearTimeout(this.hoverCloseTimer);\n this.hoverCloseTimer = null;\n }\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-popover.mjs","sources":["../../../projects/lib/popover/interfaces/popover-position.ts","../../../projects/lib/popover/internal/text-panel.ts","../../../projects/lib/popover/popover.ts","../../../projects/lib/popover/ngwr-popover.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 WrPopoverPosition =\n | 'top'\n | 'top-start'\n | 'top-end'\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'left'\n | 'left-start'\n | 'left-end'\n | 'right'\n | 'right-start'\n | 'right-end';\n\n/** @internal */\nexport const WR_POPOVER_POSITIONS: Record<WrPopoverPosition, ConnectedPosition[]> = {\n top: [{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 }],\n 'top-start': [{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -8 }],\n 'top-end': [{ originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -8 }],\n bottom: [{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 }],\n 'bottom-start': [{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 8 }],\n 'bottom-end': [{ originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 8 }],\n left: [{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 }],\n 'left-start': [{ originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top', offsetX: -8 }],\n 'left-end': [{ originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom', offsetX: -8 }],\n right: [{ originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 }],\n 'right-start': [{ originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top', offsetX: 8 }],\n 'right-end': [{ originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom', 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 } from '@angular/core';\n\n/**\n * Internal floating label rendered when `<… [wrPopover]=\"'…'\" mode=\"tooltip\">`\n * receives a string instead of a template. Not part of the public template\n * API — use the `WrPopover` directive in tooltip mode instead.\n *\n * @internal\n */\n@Component({\n selector: 'wr-popover-text',\n template: '{{ text() }}',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-tooltip', role: 'tooltip' },\n})\nexport class WrPopoverTextPanel {\n readonly text = input.required<string>();\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 { type BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { type OverlayRef, ScrollStrategyOptions } from '@angular/cdk/overlay';\nimport { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';\nimport type { TemplateRef } from '@angular/core';\nimport {\n DestroyRef,\n Directive,\n ElementRef,\n ViewContainerRef,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nimport { WR_OVERLAY, WR_RESPONSIVE_OVERLAYS, wrPresentAsSheet } from 'ngwr/overlay';\nimport { numAttr } from 'ngwr/utils';\n\nimport { WR_POPOVER_POSITIONS, type WrPopoverPosition } from './interfaces';\nimport { WrPopoverTextPanel } from './internal/text-panel';\n\n/**\n * Anchored content panel. The same directive covers two shapes:\n *\n * - **Popover** (default, `mode=\"popover\"`) — `[wrPopover]` takes a\n * `TemplateRef`. Opens on click or hover. Use for rich anchored content:\n * forms, summaries, menus.\n *\n * - **Tooltip** (`mode=\"tooltip\"`) — `[wrPopover]` takes a plain string.\n * Shown on hover and focus, dismissed on blur / pointer-leave / Escape.\n * Uses `aria-describedby` instead of `aria-haspopup` and is rendered into\n * a small dark text panel.\n *\n * Built on CDK Overlay so it auto-flips, closes on outside-click and Escape.\n *\n * @example\n * ```html\n * <!-- Popover with template content -->\n * <button wr-btn [wrPopover]=\"info\">Details</button>\n * <ng-template #info>\n * <div style=\"padding: 1rem; max-width: 18rem\">Anything you can render.</div>\n * </ng-template>\n *\n * <!-- Tooltip with plain text -->\n * <button wr-btn [wrPopover]=\"'Save changes'\" mode=\"tooltip\" position=\"top\">\n * Save\n * </button>\n * ```\n *\n * @see https://ngwr.dev/components/popover\n */\nlet popoverUid = 0;\n\n@Directive({\n selector: '[wrPopover]',\n host: {\n '[attr.aria-haspopup]': 'isTooltip() ? null : \"dialog\"',\n '[attr.aria-expanded]': 'isTooltip() ? null : isOpen()',\n '[attr.aria-controls]': '!isTooltip() && isOpen() ? panelId : null',\n '[attr.aria-describedby]': 'isTooltip() && isOpen() ? panelId : null',\n '(click)': 'onClick($event)',\n '(mouseenter)': 'onMouseEnter()',\n '(mouseleave)': 'onMouseLeave($event)',\n '(focus)': 'onFocus()',\n '(blur)': 'onBlur()',\n '(keydown.escape)': 'onEscape()',\n },\n})\nexport class WrPopover {\n /**\n * Content to render inside the panel.\n * - In **popover** mode (default): pass a `TemplateRef`.\n * - In **tooltip** mode: pass a plain string.\n */\n readonly content = input.required<TemplateRef<unknown> | string>({ alias: 'wrPopover' });\n\n /**\n * Shape preset.\n *\n * - `'popover'` (default) — template content, click trigger, dialog\n * semantics.\n * - `'tooltip'` — text content, hover+focus trigger, `role=\"tooltip\"`,\n * `aria-describedby` on the host.\n */\n readonly mode = input<'popover' | 'tooltip'>('popover');\n\n /**\n * How the popover opens. Ignored in tooltip mode — tooltips are always\n * hover+focus. @default 'click'\n */\n readonly trigger = input<'click' | 'hover'>('click');\n\n /** Anchor side. @default 'bottom' for popover, 'top' for tooltip */\n readonly position = input<WrPopoverPosition | null>(null);\n\n /** Tooltip only — delay before showing, in ms. @default 120 */\n readonly showDelay = input(120, { transform: numAttr(120) });\n\n /** Tooltip only — delay before hiding, in ms. @default 60 */\n readonly hideDelay = input(60, { transform: numAttr(60) });\n\n /**\n * Popover mode only — present the panel as a full-width bottom-sheet on\n * small viewports instead of an anchored panel. `undefined` follows the\n * app-wide `provideWrResponsiveOverlays()` setting; `true`/`false`\n * overrides it. Tooltips never become sheets. @default undefined\n */\n readonly responsive = input<boolean | undefined, BooleanInput>(undefined, {\n transform: (v: BooleanInput): boolean | undefined => (v == null ? undefined : coerceBooleanProperty(v)),\n });\n\n /** Fires after the panel opens. */\n readonly opened = output<void>();\n\n /** Fires after the panel closes. */\n readonly closed = output<void>();\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly overlay = inject(WR_OVERLAY);\n private readonly responsiveConfig = inject(WR_RESPONSIVE_OVERLAYS);\n private readonly vcr = inject(ViewContainerRef);\n private readonly scrollStrategies = inject(ScrollStrategyOptions);\n private readonly destroyRef = inject(DestroyRef);\n\n /** @internal */\n readonly isOpen = signal(false);\n\n /** @internal */\n protected readonly isTooltip = computed(() => this.mode() === 'tooltip');\n\n /** Auto-generated id for `aria-controls` / `aria-describedby`. */\n protected readonly panelId = `wr-popover-${++popoverUid}`;\n\n private readonly resolvedPosition = computed<WrPopoverPosition>(\n () => this.position() ?? (this.isTooltip() ? 'top' : 'bottom')\n );\n\n private overlayRef: OverlayRef | null = null;\n private hoverCloseTimer: ReturnType<typeof setTimeout> | null = null;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n effect(() => {\n if (this.isOpen()) {\n this.openOverlay();\n } else {\n this.closeOverlay();\n }\n });\n this.destroyRef.onDestroy(() => {\n this.clearTimers();\n this.closeOverlay();\n });\n }\n\n open(): void {\n this.isOpen.set(true);\n }\n\n close(): void {\n this.isOpen.set(false);\n }\n\n toggle(): void {\n this.isOpen.update(v => !v);\n }\n\n // Host listeners\n\n /** @internal */\n protected onClick(event: MouseEvent): void {\n if (this.isTooltip() || this.trigger() !== 'click') return;\n event.stopPropagation();\n this.toggle();\n }\n\n /** @internal */\n protected onMouseEnter(): void {\n if (this.isTooltip()) {\n this.scheduleShow();\n return;\n }\n if (this.trigger() !== 'hover') return;\n this.clearHoverClose();\n this.isOpen.set(true);\n }\n\n /** @internal */\n protected onMouseLeave(event: MouseEvent): void {\n if (this.isTooltip()) {\n this.scheduleHide();\n return;\n }\n if (this.trigger() !== 'hover') return;\n const related = event.relatedTarget as Node | null;\n if (related && this.overlayRef?.overlayElement.contains(related)) return;\n // Delay so the pointer can cross the gap between trigger and panel —\n // entering the panel cancels the close (see attach listeners).\n this.scheduleHoverClose();\n }\n\n /** @internal */\n protected onFocus(): void {\n if (!this.isTooltip()) return;\n this.scheduleShow();\n }\n\n /** @internal */\n protected onBlur(): void {\n if (!this.isTooltip()) return;\n this.scheduleHide();\n }\n\n /** @internal */\n protected onEscape(): void {\n if (!this.isTooltip()) return;\n this.clearTimers();\n this.isOpen.set(false);\n }\n\n // Tooltip timers\n\n private scheduleShow(): void {\n if (this.isOpen()) {\n this.clearTimers();\n return;\n }\n const text = this.content();\n if (typeof text === 'string' && !text) return;\n this.clearTimers();\n this.showTimer = setTimeout(() => this.isOpen.set(true), this.showDelay());\n }\n\n private scheduleHide(): void {\n this.clearTimers();\n this.hideTimer = setTimeout(() => this.isOpen.set(false), this.hideDelay());\n }\n\n private clearTimers(): void {\n if (this.showTimer) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n\n // Overlay\n\n private openOverlay(): void {\n if (this.overlayRef) return;\n\n const tooltip = this.isTooltip();\n const position = this.resolvedPosition();\n\n // Sheet presentation is popover-only — tooltips are transient labels and\n // never dock to the bottom. On small viewports (when opted in) detach\n // from the trigger and slide the panel up from the bottom edge.\n const asSheet = !tooltip && wrPresentAsSheet(this.responsive(), this.responsiveConfig);\n\n const positionStrategy = asSheet\n ? this.overlay.position().global().centerHorizontally().bottom('0')\n : this.overlay\n .position()\n .flexibleConnectedTo(this.host)\n .withPositions(WR_POPOVER_POSITIONS[position])\n .withPush(true);\n\n const overlayClass = tooltip\n ? ['wr-tooltip-overlay', `wr-tooltip-overlay--${position}`]\n : asSheet\n ? ['wr-popover-overlay', 'wr-overlay-sheet']\n : ['wr-popover-overlay', `wr-popover-overlay--${position}`];\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n scrollStrategy: asSheet ? this.scrollStrategies.block() : this.scrollStrategies.reposition(),\n width: asSheet ? '100%' : undefined,\n hasBackdrop: asSheet,\n backdropClass: asSheet ? 'wr-overlay-backdrop' : undefined,\n panelClass: overlayClass,\n });\n\n if (asSheet) {\n this.overlayRef\n .backdropClick()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this.isOpen.set(false));\n }\n\n const content = this.content();\n\n if (tooltip) {\n // Text content rendered via the internal text panel — accepts a\n // string and wraps it in the `.wr-tooltip` shell.\n const text = typeof content === 'string' ? content : '';\n const ref = this.overlayRef.attach(new ComponentPortal(WrPopoverTextPanel, this.vcr));\n ref.setInput('text', text);\n this.overlayRef.overlayElement.setAttribute('role', 'tooltip');\n } else if (typeof content !== 'string') {\n this.overlayRef.attach(new TemplatePortal(content, this.vcr));\n }\n this.overlayRef.overlayElement.id = this.panelId;\n\n this.overlayRef\n .outsidePointerEvents()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (this.host.nativeElement.contains(event.target as Node)) return;\n this.isOpen.set(false);\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.isOpen.set(false);\n }\n });\n\n if (!tooltip && this.trigger() === 'hover') {\n this.overlayRef.overlayElement.addEventListener('mouseenter', this.onOverlayEnter);\n this.overlayRef.overlayElement.addEventListener('mouseleave', this.onOverlayLeave);\n }\n\n this.opened.emit();\n }\n\n private closeOverlay(): void {\n if (!this.overlayRef) return;\n if (!this.isTooltip() && this.trigger() === 'hover') {\n this.overlayRef.overlayElement.removeEventListener('mouseenter', this.onOverlayEnter);\n this.overlayRef.overlayElement.removeEventListener('mouseleave', this.onOverlayLeave);\n }\n this.clearHoverClose();\n this.overlayRef.dispose();\n this.overlayRef = null;\n this.closed.emit();\n }\n\n private readonly onOverlayLeave = (event: MouseEvent): void => {\n const related = event.relatedTarget as Node | null;\n if (related && this.host.nativeElement.contains(related)) return;\n this.scheduleHoverClose();\n };\n\n private readonly onOverlayEnter = (): void => {\n this.clearHoverClose();\n };\n\n private scheduleHoverClose(): void {\n this.clearHoverClose();\n this.hoverCloseTimer = setTimeout(() => this.isOpen.set(false), 120);\n }\n\n private clearHoverClose(): void {\n if (this.hoverCloseTimer) {\n clearTimeout(this.hoverCloseTimer);\n this.hoverCloseTimer = null;\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
2
2
  import { isPlatformBrowser } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { input, output, signal, computed, inject, ElementRef, DestroyRef, PLATFORM_ID, afterNextRender, effect, ViewEncapsulation, Component } from '@angular/core';
4
+ import { input, output, signal, computed, inject, ElementRef, Injector, DestroyRef, PLATFORM_ID, afterNextRender, effect, ViewEncapsulation, Component } from '@angular/core';
5
5
  import { WrPlatform } from 'ngwr/platform';
6
6
  import { numAttr } from 'ngwr/utils';
7
7
 
@@ -93,6 +93,7 @@ class WrRotatingText {
93
93
  words = computed(() => splitWords(this.current(), this.splitBy()), /* @ts-ignore */
94
94
  ...(ngDevMode ? [{ debugName: "words" }] : /* istanbul ignore next */ []));
95
95
  host = inject(ElementRef);
96
+ injector = inject(Injector);
96
97
  destroyRef = inject(DestroyRef);
97
98
  isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
98
99
  platform = inject(WrPlatform);
@@ -157,11 +158,16 @@ class WrRotatingText {
157
158
  await this.animateOut();
158
159
  this.index.set(target);
159
160
  this.nextChange.emit(target);
160
- // Wait one microtask so the new spans are rendered, then animate in.
161
- queueMicrotask(() => {
161
+ // Animate in only AFTER Angular has rendered the new word's spans. A single
162
+ // microtask isn't enough under zoneless change detection — the re-render
163
+ // hasn't flushed yet, so `animateIn()` would query the OLD spans, animate
164
+ // them, and then the render would swap their content mid-flight (and any
165
+ // spans the longer word adds would never get animated). `afterNextRender`
166
+ // fires after the render the `index` change schedules.
167
+ afterNextRender(() => {
162
168
  this.animateIn();
163
169
  this.isAnimating = false;
164
- });
170
+ }, { injector: this.injector });
165
171
  }
166
172
  animateIn() {
167
173
  const targets = this.host.nativeElement.querySelectorAll('.wr-rotating-text__char');
@@ -213,6 +219,11 @@ class WrRotatingText {
213
219
  ], { duration: this.duration() * 1000, delay, easing: this.easing(), fill: 'forwards' });
214
220
  promises.push(new Promise(resolve => {
215
221
  anim.onfinish = () => {
222
+ // Commit the exited (hidden, lifted) state to inline style before
223
+ // cancelling, so the char stays out instead of snapping back to
224
+ // visible-in-place between the swap and the enter animation.
225
+ el.style.opacity = '0';
226
+ el.style.transform = 'translate3d(0, -120%, 0)';
216
227
  try {
217
228
  anim.cancel();
218
229
  }