ngwr 10.0.0 → 10.2.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 (238) hide show
  1. package/README.md +9 -8
  2. package/action-sheet/styles/_index.scss +6 -1
  3. package/alert/styles/_index.scss +7 -3
  4. package/badge/styles/_index.scss +1 -1
  5. package/badge/styles/_tag.scss +2 -2
  6. package/border-glow/styles/_index.scss +5 -0
  7. package/breadcrumbs/styles/_index.scss +1 -1
  8. package/button/styles/_index.scss +6 -6
  9. package/calendar/styles/_index.scss +9 -1
  10. package/circular-text/styles/_index.scss +6 -1
  11. package/density/styles/_index.scss +3 -1
  12. package/dialog/styles/_index.scss +1 -2
  13. package/drag-drop/styles/_index.scss +20 -7
  14. package/event-calendar/styles/_index.scss +284 -0
  15. package/falling-text/styles/_index.scss +5 -0
  16. package/fesm2022/ngwr-alert.mjs +8 -3
  17. package/fesm2022/ngwr-alert.mjs.map +1 -1
  18. package/fesm2022/ngwr-back-top.mjs +6 -4
  19. package/fesm2022/ngwr-back-top.mjs.map +1 -1
  20. package/fesm2022/ngwr-border-glow.mjs +12 -9
  21. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  22. package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
  23. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  24. package/fesm2022/ngwr-calendar.mjs +5 -3
  25. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  26. package/fesm2022/ngwr-card.mjs +2 -2
  27. package/fesm2022/ngwr-card.mjs.map +1 -1
  28. package/fesm2022/ngwr-carousel.mjs +17 -4
  29. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  30. package/fesm2022/ngwr-cascader.mjs +31 -4
  31. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  32. package/fesm2022/ngwr-checkbox.mjs +12 -3
  33. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  34. package/fesm2022/ngwr-circular-text.mjs +2 -2
  35. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  36. package/fesm2022/ngwr-command-palette.mjs +7 -3
  37. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  38. package/fesm2022/ngwr-counter.mjs +9 -1
  39. package/fesm2022/ngwr-counter.mjs.map +1 -1
  40. package/fesm2022/ngwr-date-picker.mjs +23 -6
  41. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  42. package/fesm2022/ngwr-descriptions.mjs +5 -4
  43. package/fesm2022/ngwr-descriptions.mjs.map +1 -1
  44. package/fesm2022/ngwr-drag-drop.mjs +2 -2
  45. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  46. package/fesm2022/ngwr-dropdown.mjs +4 -0
  47. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  48. package/fesm2022/ngwr-event-calendar.mjs +723 -0
  49. package/fesm2022/ngwr-event-calendar.mjs.map +1 -0
  50. package/fesm2022/ngwr-falling-text.mjs +2 -2
  51. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  52. package/fesm2022/ngwr-file-upload.mjs +2 -2
  53. package/fesm2022/ngwr-file-upload.mjs.map +1 -1
  54. package/fesm2022/ngwr-form.mjs +258 -42
  55. package/fesm2022/ngwr-form.mjs.map +1 -1
  56. package/fesm2022/ngwr-fuzzy-text.mjs +15 -1
  57. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  58. package/fesm2022/ngwr-gauge.mjs +8 -3
  59. package/fesm2022/ngwr-gauge.mjs.map +1 -1
  60. package/fesm2022/ngwr-glitch-text.mjs +2 -2
  61. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  62. package/fesm2022/ngwr-gradient-text.mjs +2 -2
  63. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  64. package/fesm2022/ngwr-i18n-en.mjs +73 -5
  65. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  66. package/fesm2022/ngwr-i18n-ru.mjs +73 -5
  67. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  68. package/fesm2022/ngwr-i18n.mjs +20 -2
  69. package/fesm2022/ngwr-i18n.mjs.map +1 -1
  70. package/fesm2022/ngwr-icon.mjs +5 -0
  71. package/fesm2022/ngwr-icon.mjs.map +1 -1
  72. package/fesm2022/ngwr-input-number.mjs +19 -3
  73. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  74. package/fesm2022/ngwr-input.mjs +48 -6
  75. package/fesm2022/ngwr-input.mjs.map +1 -1
  76. package/fesm2022/ngwr-knob.mjs +8 -3
  77. package/fesm2022/ngwr-knob.mjs.map +1 -1
  78. package/fesm2022/ngwr-lightbox.mjs +32 -3
  79. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  80. package/fesm2022/ngwr-line-chart.mjs +3 -3
  81. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  82. package/fesm2022/ngwr-list.mjs +2 -2
  83. package/fesm2022/ngwr-list.mjs.map +1 -1
  84. package/fesm2022/ngwr-loading-bar.mjs +2 -2
  85. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  86. package/fesm2022/ngwr-marquee.mjs +2 -2
  87. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  88. package/fesm2022/ngwr-media.mjs +3 -0
  89. package/fesm2022/ngwr-media.mjs.map +1 -1
  90. package/fesm2022/ngwr-meter-group.mjs +14 -3
  91. package/fesm2022/ngwr-meter-group.mjs.map +1 -1
  92. package/fesm2022/ngwr-page-header.mjs +2 -2
  93. package/fesm2022/ngwr-page-header.mjs.map +1 -1
  94. package/fesm2022/ngwr-pagination.mjs +1 -1
  95. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  96. package/fesm2022/ngwr-progress.mjs +8 -2
  97. package/fesm2022/ngwr-progress.mjs.map +1 -1
  98. package/fesm2022/ngwr-qr.mjs.map +1 -1
  99. package/fesm2022/ngwr-rating.mjs +6 -4
  100. package/fesm2022/ngwr-rating.mjs.map +1 -1
  101. package/fesm2022/ngwr-result.mjs +19 -12
  102. package/fesm2022/ngwr-result.mjs.map +1 -1
  103. package/fesm2022/ngwr-segmented.mjs +2 -2
  104. package/fesm2022/ngwr-segmented.mjs.map +1 -1
  105. package/fesm2022/ngwr-select.mjs +28 -8
  106. package/fesm2022/ngwr-select.mjs.map +1 -1
  107. package/fesm2022/ngwr-shiny-text.mjs +4 -6
  108. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  109. package/fesm2022/ngwr-speed-dial.mjs +11 -3
  110. package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
  111. package/fesm2022/ngwr-spotlight-card.mjs +2 -2
  112. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  113. package/fesm2022/ngwr-squircle.mjs +1 -1
  114. package/fesm2022/ngwr-squircle.mjs.map +1 -1
  115. package/fesm2022/ngwr-star-border.mjs +2 -2
  116. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  117. package/fesm2022/ngwr-switch.mjs +10 -3
  118. package/fesm2022/ngwr-switch.mjs.map +1 -1
  119. package/fesm2022/ngwr-table.mjs +233 -19
  120. package/fesm2022/ngwr-table.mjs.map +1 -1
  121. package/fesm2022/ngwr-tabs.mjs +21 -4
  122. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  123. package/fesm2022/ngwr-textarea.mjs +20 -4
  124. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  125. package/fesm2022/ngwr-tilt-card.mjs +2 -2
  126. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  127. package/fesm2022/ngwr-toolbar.mjs +2 -2
  128. package/fesm2022/ngwr-toolbar.mjs.map +1 -1
  129. package/fesm2022/ngwr-tour.mjs +264 -0
  130. package/fesm2022/ngwr-tour.mjs.map +1 -0
  131. package/fesm2022/ngwr-transfer.mjs +184 -0
  132. package/fesm2022/ngwr-transfer.mjs.map +1 -0
  133. package/fesm2022/ngwr-tree.mjs +23 -6
  134. package/fesm2022/ngwr-tree.mjs.map +1 -1
  135. package/fesm2022/ngwr-typewriter.mjs +2 -2
  136. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  137. package/fesm2022/ngwr-validators.mjs +118 -2
  138. package/fesm2022/ngwr-validators.mjs.map +1 -1
  139. package/fesm2022/ngwr-version.mjs +2 -2
  140. package/fesm2022/ngwr-version.mjs.map +1 -1
  141. package/fesm2022/ngwr-virtual-scroll.mjs +2 -2
  142. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  143. package/fesm2022/ngwr-waves.mjs +2 -2
  144. package/fesm2022/ngwr-waves.mjs.map +1 -1
  145. package/form/styles/_index.scss +8 -4
  146. package/glitch-text/styles/_index.scss +5 -0
  147. package/gradient-text/styles/_index.scss +5 -0
  148. package/i18n/en.json +74 -6
  149. package/i18n/ru.json +74 -6
  150. package/icon/styles/_index.scss +5 -0
  151. package/keyboard/styles/_index.scss +5 -0
  152. package/llms-full.txt +123 -62
  153. package/llms.txt +29 -8
  154. package/loading-bar/styles/_index.scss +5 -0
  155. package/marquee/styles/_index.scss +7 -2
  156. package/overlay/styles/_index.scss +5 -0
  157. package/package.json +13 -1
  158. package/popover/styles/_index.scss +48 -12
  159. package/pull-to-refresh/styles/_index.scss +5 -0
  160. package/result/styles/_index.scss +3 -3
  161. package/schematics/icon-set/index.js +80 -34
  162. package/schematics/icon-set/schema.json +8 -3
  163. package/schematics/ng-add/index.js +5 -2
  164. package/schematics/page/templates.js +17 -21
  165. package/schematics/provider/index.js +31 -13
  166. package/schematics/provider/schema.json +40 -24
  167. package/schematics/use/index.js +5 -1
  168. package/schematics/use/schema.json +8 -3
  169. package/schematics/use/symbol-map.json +6 -177
  170. package/segmented/styles/_index.scss +1 -1
  171. package/select/styles/_index.scss +7 -3
  172. package/shiny-text/styles/_index.scss +5 -0
  173. package/sidebar/styles/_index.scss +3 -3
  174. package/speed-dial/styles/_index.scss +12 -1
  175. package/spotlight-card/styles/_index.scss +5 -0
  176. package/squircle/styles/_index.scss +5 -0
  177. package/star-border/styles/_index.scss +5 -0
  178. package/statistic/styles/_index.scss +2 -2
  179. package/stepper/styles/_index.scss +3 -3
  180. package/styles/_animations.scss +6 -0
  181. package/styles.scss +3 -0
  182. package/table/styles/_index.scss +100 -2
  183. package/tabs/styles/_index.scss +1 -1
  184. package/theme/styles/_colors.scss +65 -2
  185. package/theme/styles/_dark.scss +18 -6
  186. package/theme/styles/_focus.scss +2 -8
  187. package/tilt-card/styles/_index.scss +5 -0
  188. package/toast/styles/_index.scss +6 -3
  189. package/tour/styles/_index.scss +63 -0
  190. package/transfer/styles/_index.scss +105 -0
  191. package/types/ngwr-alert.d.ts +4 -1
  192. package/types/ngwr-avatar.d.ts +1 -1
  193. package/types/ngwr-back-top.d.ts +3 -2
  194. package/types/ngwr-badge.d.ts +1 -1
  195. package/types/ngwr-border-glow.d.ts +0 -1
  196. package/types/ngwr-carousel.d.ts +10 -1
  197. package/types/ngwr-cascader.d.ts +12 -1
  198. package/types/ngwr-checkbox.d.ts +9 -1
  199. package/types/ngwr-command-palette.d.ts +4 -1
  200. package/types/ngwr-date-picker.d.ts +9 -1
  201. package/types/ngwr-density.d.ts +1 -1
  202. package/types/ngwr-divider.d.ts +1 -1
  203. package/types/ngwr-event-calendar.d.ts +358 -0
  204. package/types/ngwr-form.d.ts +177 -20
  205. package/types/ngwr-fuzzy-text.d.ts +8 -0
  206. package/types/ngwr-gauge.d.ts +4 -1
  207. package/types/ngwr-i18n.d.ts +15 -0
  208. package/types/ngwr-input-number.d.ts +8 -1
  209. package/types/ngwr-input.d.ts +50 -20
  210. package/types/ngwr-knob.d.ts +4 -1
  211. package/types/ngwr-lightbox.d.ts +7 -1
  212. package/types/ngwr-line-chart.d.ts +1 -1
  213. package/types/ngwr-media.d.ts +1 -1
  214. package/types/ngwr-meter-group.d.ts +9 -1
  215. package/types/ngwr-page-header.d.ts +2 -2
  216. package/types/ngwr-pagination.d.ts +1 -1
  217. package/types/ngwr-progress.d.ts +4 -1
  218. package/types/ngwr-rating.d.ts +3 -2
  219. package/types/ngwr-result.d.ts +12 -6
  220. package/types/ngwr-segmented.d.ts +6 -0
  221. package/types/ngwr-select.d.ts +13 -7
  222. package/types/ngwr-shiny-text.d.ts +2 -4
  223. package/types/ngwr-speed-dial.d.ts +7 -1
  224. package/types/ngwr-squircle.d.ts +1 -1
  225. package/types/ngwr-switch.d.ts +7 -1
  226. package/types/ngwr-table.d.ts +126 -6
  227. package/types/ngwr-tabs.d.ts +1 -4
  228. package/types/ngwr-textarea.d.ts +8 -1
  229. package/types/ngwr-toolbar.d.ts +2 -2
  230. package/types/ngwr-tour.d.ts +132 -0
  231. package/types/ngwr-transfer.d.ts +118 -0
  232. package/types/ngwr-tree.d.ts +10 -2
  233. package/types/ngwr-validators.d.ts +62 -2
  234. package/types/ngwr-version.d.ts +2 -2
  235. package/typewriter/styles/_index.scss +5 -0
  236. package/typography/styles/_index.scss +5 -5
  237. package/virtual-scroll/styles/_index.scss +6 -1
  238. package/waves/styles/_index.scss +5 -0
@@ -151,14 +151,14 @@ class WrCircularText {
151
151
  this.rotation.currentTime = ratio * newDurMs;
152
152
  }
153
153
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrCircularText, deps: [], target: i0.ɵɵFactoryTarget.Component });
154
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrCircularText, isStandalone: true, selector: "wr-circular-text", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, spinDuration: { classPropertyName: "spinDuration", publicName: "spinDuration", isSignal: true, isRequired: false, transformFunction: null }, onHover: { classPropertyName: "onHover", publicName: "onHover", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.wr-circular-text--bonkers": "onHover() === 'goBonkers'" }, classAttribute: "wr-circular-text" }, viewQueries: [{ propertyName: "spinEl", first: true, predicate: ["spin"], descendants: true, isSignal: true }], ngImport: i0, template: "<span class=\"wr-circular-text__spin\" #spin>\n @for (c of chars(); track $index) {\n <span class=\"wr-circular-text__char\" [style.transform]=\"c.transform\">{{ c.ch }}</span>\n }\n</span>\n", styles: [".wr-circular-text{--wr-circular-text-size: 12rem;--wr-circular-text-radius: calc(var(--wr-circular-text-size) / 2);position:relative;display:inline-block;width:var(--wr-circular-text-size);height:var(--wr-circular-text-size);border-radius:50%;font-weight:700;text-align:center;-webkit-user-select:none;user-select:none;transition:transform .6s cubic-bezier(.2,.9,.3,1.4)}.wr-circular-text__spin{position:absolute;inset:0;will-change:transform}.wr-circular-text__char{position:absolute;top:50%;left:50%;display:inline-block;margin-left:-.5em;margin-top:-.5em;line-height:1}.wr-circular-text--bonkers:hover{transform:scale(.8)}\n"], encapsulation: i0.ViewEncapsulation.None });
154
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrCircularText, isStandalone: true, selector: "wr-circular-text", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, spinDuration: { classPropertyName: "spinDuration", publicName: "spinDuration", isSignal: true, isRequired: false, transformFunction: null }, onHover: { classPropertyName: "onHover", publicName: "onHover", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.wr-circular-text--bonkers": "onHover() === 'goBonkers'" }, classAttribute: "wr-circular-text" }, viewQueries: [{ propertyName: "spinEl", first: true, predicate: ["spin"], descendants: true, isSignal: true }], ngImport: i0, template: "<span class=\"wr-circular-text__spin\" #spin>\n @for (c of chars(); track $index) {\n <span class=\"wr-circular-text__char\" [style.transform]=\"c.transform\">{{ c.ch }}</span>\n }\n</span>\n", styles: ["@charset \"UTF-8\";:where([class^=wr-],[class*=\" wr-\"]),:where([class^=wr-],[class*=\" wr-\"]):before,:where([class^=wr-],[class*=\" wr-\"]):after{box-sizing:border-box}:root{color-scheme:light;--wr-color-white: #ffffff;--wr-color-white-rgb: 255, 255, 255;--wr-color-black: #000000;--wr-color-black-rgb: 0, 0, 0;--wr-color-backdrop-rgb: 0, 0, 0;--wr-color-hover: rgba(var(--wr-color-light-rgb), .4);--wr-color-border: rgba(var(--wr-color-light-rgb), .5);--wr-color-border-subtle: rgba(var(--wr-color-light-rgb), .35);--wr-color-border-strong: rgba(var(--wr-color-light-rgb), .6);--wr-color-overlay: rgba(var(--wr-color-backdrop-rgb), .45);--wr-color-muted-text: #5f6c7d;--wr-color-muted-text-rgb: 95, 108, 125;--wr-color-text-muted: rgba(var(--wr-color-muted-text-rgb), .95);--wr-color-text-faint: rgba(var(--wr-color-muted-text-rgb), .6);--wr-color-gray-50: #f8fafc;--wr-color-gray-100: #f1f5f9;--wr-color-gray-200: #e2e8f0;--wr-color-gray-300: #cbd5e1;--wr-color-gray-400: #94a3b8;--wr-color-gray-500: #64748b;--wr-color-gray-600: #475569;--wr-color-gray-700: #334155;--wr-color-gray-800: #1e293b;--wr-color-gray-900: #0f172a;--wr-color-gray-950: #020617;--wr-color-surface: var(--wr-color-white);--wr-color-surface-rgb: var(--wr-color-white-rgb);--wr-color-on-surface: var(--wr-color-dark);--wr-color-on-surface-rgb: var(--wr-color-dark-rgb);--wr-color-on-surface-muted: var(--wr-color-muted-text);--wr-color-on-surface-muted-rgb: var(--wr-color-muted-text-rgb);--wr-color-outline: var(--wr-color-light);--wr-color-outline-rgb: var(--wr-color-light-rgb);--wr-color-primary: #3969e2;--wr-color-primary-rgb: 57, 105, 226;--wr-color-primary-contrast: #ffffff;--wr-color-primary-dark: rgb(34.7577092511, 88.1497797357, 222.7422907489);--wr-color-primary-darker: rgb(29.6387665198, 78.6960352423, 202.3612334802);--wr-color-primary-light: rgb(79.2422907489, 121.8502202643, 229.2577092511);--wr-color-primary-lighter: rgb(101.4845814978, 138.7004405286, 232.5154185022);--wr-color-secondary: #f51c6a;--wr-color-secondary-rgb: 245, 28, 106;--wr-color-secondary-contrast: #000000;--wr-color-secondary-dark: rgb(237.0569620253, 10.4430379747, 91.8987341772);--wr-color-secondary-darker: rgb(212.6329113924, 9.3670886076, 82.4303797468);--wr-color-secondary-light: rgb(246.0759493671, 52.4240506329, 122.0316455696);--wr-color-secondary-lighter: rgb(247.1518987342, 76.8481012658, 138.0632911392);--wr-color-success: #00a400;--wr-color-success-rgb: 0, 164, 0;--wr-color-success-contrast: #000000;--wr-color-success-dark: rgb(0, 138.5, 0);--wr-color-success-darker: #007100;--wr-color-success-light: rgb(0, 189.5, 0);--wr-color-success-lighter: #00d700;--wr-color-warning: #ffba00;--wr-color-warning-rgb: 255, 186, 0;--wr-color-warning-contrast: #000000;--wr-color-warning-dark: rgb(229.5, 167.4, 0);--wr-color-warning-darker: rgb(204, 148.8, 0);--wr-color-warning-light: rgb(255, 192.9, 25.5);--wr-color-warning-lighter: rgb(255, 199.8, 51);--wr-color-danger: #fa383e;--wr-color-danger-rgb: 250, 56, 62;--wr-color-danger-contrast: #000000;--wr-color-danger-dark: rgb(249.375, 31.125, 37.875);--wr-color-danger-darker: rgb(248.75, 6.25, 13.75);--wr-color-danger-light: rgb(250.625, 80.875, 86.125);--wr-color-danger-lighter: rgb(251.25, 105.75, 110.25);--wr-color-info: #3b82f6;--wr-color-info-rgb: 59, 130, 246;--wr-color-info-contrast: #000000;--wr-color-info-dark: rgb(34.6195121951, 114.4512195122, 244.8804878049);--wr-color-info-darker: rgb(11.1512195122, 99.1219512195, 242.8487804878);--wr-color-info-light: rgb(83.3804878049, 145.5487804878, 247.1195121951);--wr-color-info-lighter: rgb(107.7609756098, 161.0975609756, 248.2390243902);--wr-color-light: #cbd5e1;--wr-color-light-rgb: 203, 213, 225;--wr-color-light-contrast: #000000;--wr-color-light-dark: rgb(186.8292682927, 199.9390243902, 215.6707317073);--wr-color-light-darker: rgb(170.6585365854, 186.8780487805, 206.3414634146);--wr-color-light-light: rgb(219.1707317073, 226.0609756098, 234.3292682927);--wr-color-light-lighter: rgb(235.3414634146, 239.1219512195, 243.6585365854);--wr-color-medium: #8594a4;--wr-color-medium-rgb: 133, 148, 164;--wr-color-medium-contrast: #000000;--wr-color-medium-dark: rgb(118.3943661972, 135.1901408451, 153.1056338028);--wr-color-medium-darker: rgb(105.0985915493, 122.4225352113, 140.9014084507);--wr-color-medium-light: rgb(147.6056338028, 160.8098591549, 174.8943661972);--wr-color-medium-lighter: rgb(162.2112676056, 173.6197183099, 185.7887323944);--wr-color-dark: #0f172a;--wr-color-dark-rgb: 15, 23, 42;--wr-color-dark-contrast: #ffffff;--wr-color-dark-dark: rgb(8.2894736842, 12.7105263158, 23.2105263158);--wr-color-dark-darker: rgb(1.5789473684, 2.4210526316, 4.4210526316);--wr-color-dark-light: rgb(21.7105263158, 33.2894736842, 60.7894736842);--wr-color-dark-lighter: rgb(28.4210526316, 43.5789473684, 79.5789473684);--wr-color-primary-soft: rgba(var(--wr-color-primary-rgb), .12);--wr-color-primary-soft-border: rgba(var(--wr-color-primary-rgb), .3);--wr-color-primary-soft-contrast: color-mix(in srgb, var(--wr-color-primary) 62%, var(--wr-color-dark));--wr-color-primary-active: rgba(var(--wr-color-primary-rgb), .2);--wr-color-secondary-soft: rgba(var(--wr-color-secondary-rgb), .12);--wr-color-secondary-soft-border: rgba(var(--wr-color-secondary-rgb), .3);--wr-color-secondary-soft-contrast: color-mix(in srgb, var(--wr-color-secondary) 62%, var(--wr-color-dark));--wr-color-secondary-active: rgba(var(--wr-color-secondary-rgb), .2);--wr-color-success-soft: rgba(var(--wr-color-success-rgb), .12);--wr-color-success-soft-border: rgba(var(--wr-color-success-rgb), .3);--wr-color-success-soft-contrast: color-mix(in srgb, var(--wr-color-success) 62%, var(--wr-color-dark));--wr-color-success-active: rgba(var(--wr-color-success-rgb), .2);--wr-color-warning-soft: rgba(var(--wr-color-warning-rgb), .12);--wr-color-warning-soft-border: rgba(var(--wr-color-warning-rgb), .3);--wr-color-warning-soft-contrast: color-mix(in srgb, var(--wr-color-warning) 62%, var(--wr-color-dark));--wr-color-warning-active: rgba(var(--wr-color-warning-rgb), .2);--wr-color-danger-soft: rgba(var(--wr-color-danger-rgb), .12);--wr-color-danger-soft-border: rgba(var(--wr-color-danger-rgb), .3);--wr-color-danger-soft-contrast: color-mix(in srgb, var(--wr-color-danger) 62%, var(--wr-color-dark));--wr-color-danger-active: rgba(var(--wr-color-danger-rgb), .2);--wr-color-info-soft: rgba(var(--wr-color-info-rgb), .12);--wr-color-info-soft-border: rgba(var(--wr-color-info-rgb), .3);--wr-color-info-soft-contrast: color-mix(in srgb, var(--wr-color-info) 62%, var(--wr-color-dark));--wr-color-info-active: rgba(var(--wr-color-info-rgb), .2);--wr-color-medium-soft: rgba(var(--wr-color-medium-rgb), .12);--wr-color-medium-soft-border: rgba(var(--wr-color-medium-rgb), .3);--wr-color-medium-soft-contrast: color-mix(in srgb, var(--wr-color-medium) 62%, var(--wr-color-dark));--wr-color-medium-active: rgba(var(--wr-color-medium-rgb), .2);--wr-color-primary-ink: color-mix(in srgb, var(--wr-color-primary) 86%, var(--wr-color-dark));--wr-color-secondary-ink: color-mix(in srgb, var(--wr-color-secondary) 75%, var(--wr-color-dark));--wr-color-success-ink: color-mix(in srgb, var(--wr-color-success) 67%, var(--wr-color-dark));--wr-color-warning-ink: color-mix(in srgb, var(--wr-color-warning) 48%, var(--wr-color-dark));--wr-color-danger-ink: color-mix(in srgb, var(--wr-color-danger) 72%, var(--wr-color-dark));--wr-color-info-ink: color-mix(in srgb, var(--wr-color-info) 71%, var(--wr-color-dark));--wr-color-medium-ink: color-mix(in srgb, var(--wr-color-medium) 65%, var(--wr-color-dark));--wr-color-light-ink: var(--wr-color-on-surface);--wr-color-dark-ink: var(--wr-color-dark)}:root{--wr-border-radius-sm: .375rem;--wr-border-radius-base: .625rem;--wr-border-radius-lg: 1rem;--wr-border-radius-pill: 50rem;--wr-control-padding-y-sm: .125rem;--wr-control-padding-y-md: .25rem;--wr-control-padding-y-lg: .3125rem;--wr-control-padding-x-sm: .5rem;--wr-control-padding-x-md: .75rem;--wr-control-padding-x-lg: 1rem;--wr-control-line-height-sm: 1rem;--wr-control-line-height-md: 1.25rem;--wr-control-line-height-lg: 1.5rem;--wr-control-font-size-sm: var(--wr-text-xs);--wr-control-font-size-md: var(--wr-text-sm);--wr-control-font-size-lg: var(--wr-text-base);--wr-control-radius-sm: 5px;--wr-control-radius-md: 6px;--wr-control-radius-lg: 7px;--wr-ease-linear: linear;--wr-ease-out: cubic-bezier(.16, 1, .3, 1);--wr-ease-in: cubic-bezier(.7, 0, .84, 0);--wr-ease-in-out: cubic-bezier(.65, 0, .35, 1);--wr-ease-spring: cubic-bezier(.34, 1.56, .64, 1);--wr-duration-fast: .1s;--wr-duration-base: .15s;--wr-duration-slow: .3s;--wr-duration-slower: .5s;--wr-transition-short: var(--wr-duration-fast) var(--wr-ease-out);--wr-transition-base: var(--wr-duration-base) var(--wr-ease-linear);--wr-transition-long: var(--wr-duration-slow) var(--wr-ease-out);--wr-shadow-xs: 0 1px 2px rgb(0 0 0 / 5%);--wr-shadow-sm: 0 2px 8px rgb(0 0 0 / 15%);--wr-shadow-overlay: 0 8px 24px rgb(0 0 0 / 12%), 0 2px 4px rgb(0 0 0 / 6%);--wr-shadow-float: 0 8px 24px rgb(0 0 0 / 18%);--wr-shadow-modal: 0 20px 48px rgb(0 0 0 / 25%);--wr-z-overlay: 1000;--wr-z-window: 1100;--wr-z-top: 9999;--wr-overlay-duration: var(--wr-duration-base);--wr-overlay-ease: var(--wr-ease-out);--wr-font-family-base: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;--wr-font-family-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;--wr-text-xs: .75rem;--wr-text-sm: .875rem;--wr-text-base: 1rem;--wr-text-lg: 1.125rem;--wr-text-xl: 1.25rem;--wr-text-2xl: 1.5rem;--wr-text-3xl: 1.875rem;--wr-text-4xl: 2.25rem;--wr-text-5xl: 3rem;--wr-font-weight-thin: 200;--wr-font-weight-light: 300;--wr-font-weight-regular: 400;--wr-font-weight-medium: 500;--wr-font-weight-semibold: 600;--wr-font-weight-bold: 700;--wr-font-weight-extrabold: 800;--wr-leading-none: 1;--wr-leading-tight: 1.25;--wr-leading-snug: 1.375;--wr-leading-normal: 1.5;--wr-leading-relaxed: 1.625;--wr-leading-loose: 2;--wr-tracking-tighter: -.05em;--wr-tracking-tight: -.025em;--wr-tracking-normal: 0;--wr-tracking-wide: .025em;--wr-tracking-wider: .05em;--wr-tracking-widest: .1em}@keyframes wr-overlay-in{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}[data-theme=dark]{--wr-color-white: #0b1120;--wr-color-white-rgb: 11, 17, 32;--wr-color-dark: #e6ebf3;--wr-color-dark-rgb: 230, 235, 243;--wr-color-dark-contrast: #0b1120;--wr-color-white-contrast: #e6ebf3;--wr-color-dark-light: rgb(247.5, 249, 251.4);--wr-color-dark-lighter: rgb(251.25, 252, 253.2);--wr-color-dark-dark: rgb(212.7702702703, 221.2162162162, 234.7297297297);--wr-color-dark-darker: rgb(195.5405405405, 207.4324324324, 226.4594594595);--wr-color-light: #262f44;--wr-color-light-rgb: 38, 47, 68;--wr-color-light-contrast: #e6ebf3;--wr-color-light-lighter: #1a2236;--wr-color-light-darker: #3a4661;--wr-color-light-light: rgb(33.429245283, 41.3466981132, 59.820754717);--wr-color-light-dark: rgb(47.141509434, 58.3066037736, 84.358490566);--wr-color-medium: #9aa6b8;--wr-color-medium-rgb: 154, 166, 184;--wr-color-medium-contrast: #000000;--wr-color-medium-light: rgb(168.9738372093, 179.1947674419, 194.5261627907);--wr-color-medium-lighter: rgb(183.9476744186, 192.3895348837, 205.0523255814);--wr-color-medium-dark: rgb(139.0261627907, 152.8052325581, 173.4738372093);--wr-color-medium-darker: rgb(124.0523255814, 139.6104651163, 162.9476744186);--wr-color-muted-text: #9aa6b8;--wr-color-muted-text-rgb: 154, 166, 184;--wr-color-primary: #5b85ff;--wr-color-primary-contrast: #000000;--wr-color-primary-rgb: 91, 133, 255;--wr-color-primary-light: #7a9eff;--wr-color-primary-dark: #2f56c9;--wr-color-primary-lighter: #99b6ff;--wr-color-primary-darker: #1f3a99;--wr-color-success: #34c759;--wr-color-success-contrast: #000000;--wr-color-success-rgb: 52, 199, 89;--wr-color-success-light: rgb(69.874501992, 206.625498008, 104.2948207171);--wr-color-success-lighter: rgb(90.0916334661, 211.9083665339, 120.7529880478);--wr-color-success-dark: rgb(46.7171314741, 178.7828685259, 79.9581673307);--wr-color-success-darker: rgb(41.4342629482, 158.5657370518, 70.9163346614);--wr-color-warning: #ffcc33;--wr-color-warning-contrast: #000000;--wr-color-warning-rgb: 255, 204, 51;--wr-color-warning-light: rgb(255, 210.375, 76.5);--wr-color-warning-lighter: rgb(255, 216.75, 102);--wr-color-warning-dark: rgb(255, 197.625, 25.5);--wr-color-warning-darker: rgb(255, 191.25, 0);--wr-color-danger: #ff5c5c;--wr-color-danger-contrast: #000000;--wr-color-danger-rgb: 255, 92, 92;--wr-color-danger-light: rgb(255, 117.5, 117.5);--wr-color-danger-lighter: #ff8f8f;--wr-color-danger-dark: rgb(255, 66.5, 66.5);--wr-color-danger-darker: #ff2929;--wr-shadow-xs: 0 1px 2px rgb(0 0 0 / 35%);--wr-shadow-sm: 0 2px 8px rgb(0 0 0 / 45%);--wr-shadow-overlay: 0 8px 24px rgb(0 0 0 / 50%), 0 2px 4px rgb(0 0 0 / 35%);--wr-shadow-float: 0 8px 24px rgb(0 0 0 / 55%);--wr-shadow-modal: 0 24px 56px rgb(0 0 0 / 60%);color-scheme:dark}.wr-tabs__tab:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-sidebar__entry:focus-visible,.wr-sidebar__item:focus-visible,.wr-sidebar__group-toggle:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-anchor__link:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-collapse__header:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-command-palette__option:focus-visible,.wr-command-palette__panel input:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-mention-panel__option:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-segmented__option:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-back-top:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-carousel__nav:focus-visible,.wr-carousel__dot:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-speed-dial__trigger:focus-visible,.wr-speed-dial__action:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-stepper__header:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-window__chrome-action:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-date-picker__trigger:focus-visible,.wr-time-picker__step:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-dropdown-item:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-alert__close:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-circular-text{--wr-circular-text-size: 12rem;--wr-circular-text-radius: calc(var(--wr-circular-text-size) / 2);position:relative;display:inline-block;width:var(--wr-circular-text-size);height:var(--wr-circular-text-size);border-radius:50%;font-weight:700;text-align:center;-webkit-user-select:none;user-select:none;transition:transform .6s var(--wr-ease-spring)}.wr-circular-text__spin{position:absolute;inset:0;will-change:transform}.wr-circular-text__char{position:absolute;top:50%;left:50%;display:inline-block;margin-left:-.5em;margin-top:-.5em;line-height:1}.wr-circular-text--bonkers:hover{transform:scale(.8)}\n"], encapsulation: i0.ViewEncapsulation.None });
155
155
  }
156
156
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrCircularText, decorators: [{
157
157
  type: Component,
158
158
  args: [{ selector: 'wr-circular-text', encapsulation: ViewEncapsulation.None, host: {
159
159
  class: 'wr-circular-text',
160
160
  '[class.wr-circular-text--bonkers]': "onHover() === 'goBonkers'",
161
- }, template: "<span class=\"wr-circular-text__spin\" #spin>\n @for (c of chars(); track $index) {\n <span class=\"wr-circular-text__char\" [style.transform]=\"c.transform\">{{ c.ch }}</span>\n }\n</span>\n", styles: [".wr-circular-text{--wr-circular-text-size: 12rem;--wr-circular-text-radius: calc(var(--wr-circular-text-size) / 2);position:relative;display:inline-block;width:var(--wr-circular-text-size);height:var(--wr-circular-text-size);border-radius:50%;font-weight:700;text-align:center;-webkit-user-select:none;user-select:none;transition:transform .6s cubic-bezier(.2,.9,.3,1.4)}.wr-circular-text__spin{position:absolute;inset:0;will-change:transform}.wr-circular-text__char{position:absolute;top:50%;left:50%;display:inline-block;margin-left:-.5em;margin-top:-.5em;line-height:1}.wr-circular-text--bonkers:hover{transform:scale(.8)}\n"] }]
161
+ }, template: "<span class=\"wr-circular-text__spin\" #spin>\n @for (c of chars(); track $index) {\n <span class=\"wr-circular-text__char\" [style.transform]=\"c.transform\">{{ c.ch }}</span>\n }\n</span>\n", styles: ["@charset \"UTF-8\";:where([class^=wr-],[class*=\" wr-\"]),:where([class^=wr-],[class*=\" wr-\"]):before,:where([class^=wr-],[class*=\" wr-\"]):after{box-sizing:border-box}:root{color-scheme:light;--wr-color-white: #ffffff;--wr-color-white-rgb: 255, 255, 255;--wr-color-black: #000000;--wr-color-black-rgb: 0, 0, 0;--wr-color-backdrop-rgb: 0, 0, 0;--wr-color-hover: rgba(var(--wr-color-light-rgb), .4);--wr-color-border: rgba(var(--wr-color-light-rgb), .5);--wr-color-border-subtle: rgba(var(--wr-color-light-rgb), .35);--wr-color-border-strong: rgba(var(--wr-color-light-rgb), .6);--wr-color-overlay: rgba(var(--wr-color-backdrop-rgb), .45);--wr-color-muted-text: #5f6c7d;--wr-color-muted-text-rgb: 95, 108, 125;--wr-color-text-muted: rgba(var(--wr-color-muted-text-rgb), .95);--wr-color-text-faint: rgba(var(--wr-color-muted-text-rgb), .6);--wr-color-gray-50: #f8fafc;--wr-color-gray-100: #f1f5f9;--wr-color-gray-200: #e2e8f0;--wr-color-gray-300: #cbd5e1;--wr-color-gray-400: #94a3b8;--wr-color-gray-500: #64748b;--wr-color-gray-600: #475569;--wr-color-gray-700: #334155;--wr-color-gray-800: #1e293b;--wr-color-gray-900: #0f172a;--wr-color-gray-950: #020617;--wr-color-surface: var(--wr-color-white);--wr-color-surface-rgb: var(--wr-color-white-rgb);--wr-color-on-surface: var(--wr-color-dark);--wr-color-on-surface-rgb: var(--wr-color-dark-rgb);--wr-color-on-surface-muted: var(--wr-color-muted-text);--wr-color-on-surface-muted-rgb: var(--wr-color-muted-text-rgb);--wr-color-outline: var(--wr-color-light);--wr-color-outline-rgb: var(--wr-color-light-rgb);--wr-color-primary: #3969e2;--wr-color-primary-rgb: 57, 105, 226;--wr-color-primary-contrast: #ffffff;--wr-color-primary-dark: rgb(34.7577092511, 88.1497797357, 222.7422907489);--wr-color-primary-darker: rgb(29.6387665198, 78.6960352423, 202.3612334802);--wr-color-primary-light: rgb(79.2422907489, 121.8502202643, 229.2577092511);--wr-color-primary-lighter: rgb(101.4845814978, 138.7004405286, 232.5154185022);--wr-color-secondary: #f51c6a;--wr-color-secondary-rgb: 245, 28, 106;--wr-color-secondary-contrast: #000000;--wr-color-secondary-dark: rgb(237.0569620253, 10.4430379747, 91.8987341772);--wr-color-secondary-darker: rgb(212.6329113924, 9.3670886076, 82.4303797468);--wr-color-secondary-light: rgb(246.0759493671, 52.4240506329, 122.0316455696);--wr-color-secondary-lighter: rgb(247.1518987342, 76.8481012658, 138.0632911392);--wr-color-success: #00a400;--wr-color-success-rgb: 0, 164, 0;--wr-color-success-contrast: #000000;--wr-color-success-dark: rgb(0, 138.5, 0);--wr-color-success-darker: #007100;--wr-color-success-light: rgb(0, 189.5, 0);--wr-color-success-lighter: #00d700;--wr-color-warning: #ffba00;--wr-color-warning-rgb: 255, 186, 0;--wr-color-warning-contrast: #000000;--wr-color-warning-dark: rgb(229.5, 167.4, 0);--wr-color-warning-darker: rgb(204, 148.8, 0);--wr-color-warning-light: rgb(255, 192.9, 25.5);--wr-color-warning-lighter: rgb(255, 199.8, 51);--wr-color-danger: #fa383e;--wr-color-danger-rgb: 250, 56, 62;--wr-color-danger-contrast: #000000;--wr-color-danger-dark: rgb(249.375, 31.125, 37.875);--wr-color-danger-darker: rgb(248.75, 6.25, 13.75);--wr-color-danger-light: rgb(250.625, 80.875, 86.125);--wr-color-danger-lighter: rgb(251.25, 105.75, 110.25);--wr-color-info: #3b82f6;--wr-color-info-rgb: 59, 130, 246;--wr-color-info-contrast: #000000;--wr-color-info-dark: rgb(34.6195121951, 114.4512195122, 244.8804878049);--wr-color-info-darker: rgb(11.1512195122, 99.1219512195, 242.8487804878);--wr-color-info-light: rgb(83.3804878049, 145.5487804878, 247.1195121951);--wr-color-info-lighter: rgb(107.7609756098, 161.0975609756, 248.2390243902);--wr-color-light: #cbd5e1;--wr-color-light-rgb: 203, 213, 225;--wr-color-light-contrast: #000000;--wr-color-light-dark: rgb(186.8292682927, 199.9390243902, 215.6707317073);--wr-color-light-darker: rgb(170.6585365854, 186.8780487805, 206.3414634146);--wr-color-light-light: rgb(219.1707317073, 226.0609756098, 234.3292682927);--wr-color-light-lighter: rgb(235.3414634146, 239.1219512195, 243.6585365854);--wr-color-medium: #8594a4;--wr-color-medium-rgb: 133, 148, 164;--wr-color-medium-contrast: #000000;--wr-color-medium-dark: rgb(118.3943661972, 135.1901408451, 153.1056338028);--wr-color-medium-darker: rgb(105.0985915493, 122.4225352113, 140.9014084507);--wr-color-medium-light: rgb(147.6056338028, 160.8098591549, 174.8943661972);--wr-color-medium-lighter: rgb(162.2112676056, 173.6197183099, 185.7887323944);--wr-color-dark: #0f172a;--wr-color-dark-rgb: 15, 23, 42;--wr-color-dark-contrast: #ffffff;--wr-color-dark-dark: rgb(8.2894736842, 12.7105263158, 23.2105263158);--wr-color-dark-darker: rgb(1.5789473684, 2.4210526316, 4.4210526316);--wr-color-dark-light: rgb(21.7105263158, 33.2894736842, 60.7894736842);--wr-color-dark-lighter: rgb(28.4210526316, 43.5789473684, 79.5789473684);--wr-color-primary-soft: rgba(var(--wr-color-primary-rgb), .12);--wr-color-primary-soft-border: rgba(var(--wr-color-primary-rgb), .3);--wr-color-primary-soft-contrast: color-mix(in srgb, var(--wr-color-primary) 62%, var(--wr-color-dark));--wr-color-primary-active: rgba(var(--wr-color-primary-rgb), .2);--wr-color-secondary-soft: rgba(var(--wr-color-secondary-rgb), .12);--wr-color-secondary-soft-border: rgba(var(--wr-color-secondary-rgb), .3);--wr-color-secondary-soft-contrast: color-mix(in srgb, var(--wr-color-secondary) 62%, var(--wr-color-dark));--wr-color-secondary-active: rgba(var(--wr-color-secondary-rgb), .2);--wr-color-success-soft: rgba(var(--wr-color-success-rgb), .12);--wr-color-success-soft-border: rgba(var(--wr-color-success-rgb), .3);--wr-color-success-soft-contrast: color-mix(in srgb, var(--wr-color-success) 62%, var(--wr-color-dark));--wr-color-success-active: rgba(var(--wr-color-success-rgb), .2);--wr-color-warning-soft: rgba(var(--wr-color-warning-rgb), .12);--wr-color-warning-soft-border: rgba(var(--wr-color-warning-rgb), .3);--wr-color-warning-soft-contrast: color-mix(in srgb, var(--wr-color-warning) 62%, var(--wr-color-dark));--wr-color-warning-active: rgba(var(--wr-color-warning-rgb), .2);--wr-color-danger-soft: rgba(var(--wr-color-danger-rgb), .12);--wr-color-danger-soft-border: rgba(var(--wr-color-danger-rgb), .3);--wr-color-danger-soft-contrast: color-mix(in srgb, var(--wr-color-danger) 62%, var(--wr-color-dark));--wr-color-danger-active: rgba(var(--wr-color-danger-rgb), .2);--wr-color-info-soft: rgba(var(--wr-color-info-rgb), .12);--wr-color-info-soft-border: rgba(var(--wr-color-info-rgb), .3);--wr-color-info-soft-contrast: color-mix(in srgb, var(--wr-color-info) 62%, var(--wr-color-dark));--wr-color-info-active: rgba(var(--wr-color-info-rgb), .2);--wr-color-medium-soft: rgba(var(--wr-color-medium-rgb), .12);--wr-color-medium-soft-border: rgba(var(--wr-color-medium-rgb), .3);--wr-color-medium-soft-contrast: color-mix(in srgb, var(--wr-color-medium) 62%, var(--wr-color-dark));--wr-color-medium-active: rgba(var(--wr-color-medium-rgb), .2);--wr-color-primary-ink: color-mix(in srgb, var(--wr-color-primary) 86%, var(--wr-color-dark));--wr-color-secondary-ink: color-mix(in srgb, var(--wr-color-secondary) 75%, var(--wr-color-dark));--wr-color-success-ink: color-mix(in srgb, var(--wr-color-success) 67%, var(--wr-color-dark));--wr-color-warning-ink: color-mix(in srgb, var(--wr-color-warning) 48%, var(--wr-color-dark));--wr-color-danger-ink: color-mix(in srgb, var(--wr-color-danger) 72%, var(--wr-color-dark));--wr-color-info-ink: color-mix(in srgb, var(--wr-color-info) 71%, var(--wr-color-dark));--wr-color-medium-ink: color-mix(in srgb, var(--wr-color-medium) 65%, var(--wr-color-dark));--wr-color-light-ink: var(--wr-color-on-surface);--wr-color-dark-ink: var(--wr-color-dark)}:root{--wr-border-radius-sm: .375rem;--wr-border-radius-base: .625rem;--wr-border-radius-lg: 1rem;--wr-border-radius-pill: 50rem;--wr-control-padding-y-sm: .125rem;--wr-control-padding-y-md: .25rem;--wr-control-padding-y-lg: .3125rem;--wr-control-padding-x-sm: .5rem;--wr-control-padding-x-md: .75rem;--wr-control-padding-x-lg: 1rem;--wr-control-line-height-sm: 1rem;--wr-control-line-height-md: 1.25rem;--wr-control-line-height-lg: 1.5rem;--wr-control-font-size-sm: var(--wr-text-xs);--wr-control-font-size-md: var(--wr-text-sm);--wr-control-font-size-lg: var(--wr-text-base);--wr-control-radius-sm: 5px;--wr-control-radius-md: 6px;--wr-control-radius-lg: 7px;--wr-ease-linear: linear;--wr-ease-out: cubic-bezier(.16, 1, .3, 1);--wr-ease-in: cubic-bezier(.7, 0, .84, 0);--wr-ease-in-out: cubic-bezier(.65, 0, .35, 1);--wr-ease-spring: cubic-bezier(.34, 1.56, .64, 1);--wr-duration-fast: .1s;--wr-duration-base: .15s;--wr-duration-slow: .3s;--wr-duration-slower: .5s;--wr-transition-short: var(--wr-duration-fast) var(--wr-ease-out);--wr-transition-base: var(--wr-duration-base) var(--wr-ease-linear);--wr-transition-long: var(--wr-duration-slow) var(--wr-ease-out);--wr-shadow-xs: 0 1px 2px rgb(0 0 0 / 5%);--wr-shadow-sm: 0 2px 8px rgb(0 0 0 / 15%);--wr-shadow-overlay: 0 8px 24px rgb(0 0 0 / 12%), 0 2px 4px rgb(0 0 0 / 6%);--wr-shadow-float: 0 8px 24px rgb(0 0 0 / 18%);--wr-shadow-modal: 0 20px 48px rgb(0 0 0 / 25%);--wr-z-overlay: 1000;--wr-z-window: 1100;--wr-z-top: 9999;--wr-overlay-duration: var(--wr-duration-base);--wr-overlay-ease: var(--wr-ease-out);--wr-font-family-base: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;--wr-font-family-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;--wr-text-xs: .75rem;--wr-text-sm: .875rem;--wr-text-base: 1rem;--wr-text-lg: 1.125rem;--wr-text-xl: 1.25rem;--wr-text-2xl: 1.5rem;--wr-text-3xl: 1.875rem;--wr-text-4xl: 2.25rem;--wr-text-5xl: 3rem;--wr-font-weight-thin: 200;--wr-font-weight-light: 300;--wr-font-weight-regular: 400;--wr-font-weight-medium: 500;--wr-font-weight-semibold: 600;--wr-font-weight-bold: 700;--wr-font-weight-extrabold: 800;--wr-leading-none: 1;--wr-leading-tight: 1.25;--wr-leading-snug: 1.375;--wr-leading-normal: 1.5;--wr-leading-relaxed: 1.625;--wr-leading-loose: 2;--wr-tracking-tighter: -.05em;--wr-tracking-tight: -.025em;--wr-tracking-normal: 0;--wr-tracking-wide: .025em;--wr-tracking-wider: .05em;--wr-tracking-widest: .1em}@keyframes wr-overlay-in{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}[data-theme=dark]{--wr-color-white: #0b1120;--wr-color-white-rgb: 11, 17, 32;--wr-color-dark: #e6ebf3;--wr-color-dark-rgb: 230, 235, 243;--wr-color-dark-contrast: #0b1120;--wr-color-white-contrast: #e6ebf3;--wr-color-dark-light: rgb(247.5, 249, 251.4);--wr-color-dark-lighter: rgb(251.25, 252, 253.2);--wr-color-dark-dark: rgb(212.7702702703, 221.2162162162, 234.7297297297);--wr-color-dark-darker: rgb(195.5405405405, 207.4324324324, 226.4594594595);--wr-color-light: #262f44;--wr-color-light-rgb: 38, 47, 68;--wr-color-light-contrast: #e6ebf3;--wr-color-light-lighter: #1a2236;--wr-color-light-darker: #3a4661;--wr-color-light-light: rgb(33.429245283, 41.3466981132, 59.820754717);--wr-color-light-dark: rgb(47.141509434, 58.3066037736, 84.358490566);--wr-color-medium: #9aa6b8;--wr-color-medium-rgb: 154, 166, 184;--wr-color-medium-contrast: #000000;--wr-color-medium-light: rgb(168.9738372093, 179.1947674419, 194.5261627907);--wr-color-medium-lighter: rgb(183.9476744186, 192.3895348837, 205.0523255814);--wr-color-medium-dark: rgb(139.0261627907, 152.8052325581, 173.4738372093);--wr-color-medium-darker: rgb(124.0523255814, 139.6104651163, 162.9476744186);--wr-color-muted-text: #9aa6b8;--wr-color-muted-text-rgb: 154, 166, 184;--wr-color-primary: #5b85ff;--wr-color-primary-contrast: #000000;--wr-color-primary-rgb: 91, 133, 255;--wr-color-primary-light: #7a9eff;--wr-color-primary-dark: #2f56c9;--wr-color-primary-lighter: #99b6ff;--wr-color-primary-darker: #1f3a99;--wr-color-success: #34c759;--wr-color-success-contrast: #000000;--wr-color-success-rgb: 52, 199, 89;--wr-color-success-light: rgb(69.874501992, 206.625498008, 104.2948207171);--wr-color-success-lighter: rgb(90.0916334661, 211.9083665339, 120.7529880478);--wr-color-success-dark: rgb(46.7171314741, 178.7828685259, 79.9581673307);--wr-color-success-darker: rgb(41.4342629482, 158.5657370518, 70.9163346614);--wr-color-warning: #ffcc33;--wr-color-warning-contrast: #000000;--wr-color-warning-rgb: 255, 204, 51;--wr-color-warning-light: rgb(255, 210.375, 76.5);--wr-color-warning-lighter: rgb(255, 216.75, 102);--wr-color-warning-dark: rgb(255, 197.625, 25.5);--wr-color-warning-darker: rgb(255, 191.25, 0);--wr-color-danger: #ff5c5c;--wr-color-danger-contrast: #000000;--wr-color-danger-rgb: 255, 92, 92;--wr-color-danger-light: rgb(255, 117.5, 117.5);--wr-color-danger-lighter: #ff8f8f;--wr-color-danger-dark: rgb(255, 66.5, 66.5);--wr-color-danger-darker: #ff2929;--wr-shadow-xs: 0 1px 2px rgb(0 0 0 / 35%);--wr-shadow-sm: 0 2px 8px rgb(0 0 0 / 45%);--wr-shadow-overlay: 0 8px 24px rgb(0 0 0 / 50%), 0 2px 4px rgb(0 0 0 / 35%);--wr-shadow-float: 0 8px 24px rgb(0 0 0 / 55%);--wr-shadow-modal: 0 24px 56px rgb(0 0 0 / 60%);color-scheme:dark}.wr-tabs__tab:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-sidebar__entry:focus-visible,.wr-sidebar__item:focus-visible,.wr-sidebar__group-toggle:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-anchor__link:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-collapse__header:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-command-palette__option:focus-visible,.wr-command-palette__panel input:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-mention-panel__option:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-segmented__option:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-back-top:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-carousel__nav:focus-visible,.wr-carousel__dot:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-speed-dial__trigger:focus-visible,.wr-speed-dial__action:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-stepper__header:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-window__chrome-action:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-date-picker__trigger:focus-visible,.wr-time-picker__step:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-dropdown-item:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-alert__close:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.25)}.wr-circular-text{--wr-circular-text-size: 12rem;--wr-circular-text-radius: calc(var(--wr-circular-text-size) / 2);position:relative;display:inline-block;width:var(--wr-circular-text-size);height:var(--wr-circular-text-size);border-radius:50%;font-weight:700;text-align:center;-webkit-user-select:none;user-select:none;transition:transform .6s var(--wr-ease-spring)}.wr-circular-text__spin{position:absolute;inset:0;will-change:transform}.wr-circular-text__char{position:absolute;top:50%;left:50%;display:inline-block;margin-left:-.5em;margin-top:-.5em;line-height:1}.wr-circular-text--bonkers:hover{transform:scale(.8)}\n"] }]
162
162
  }], ctorParameters: () => [], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], spinDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "spinDuration", required: false }] }], onHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "onHover", required: false }] }], spinEl: [{ type: i0.ViewChild, args: ['spin', { isSignal: true }] }] } });
163
163
 
164
164
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-circular-text.mjs","sources":["../../../projects/lib/circular-text/circular-text.ts","../../../projects/lib/circular-text/circular-text.html","../../../projects/lib/circular-text/ngwr-circular-text.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 * Angular adaptation of the CircularText effect by David Haz / reactbits.dev.\n * Original: https://www.reactbits.dev/text-animations/circular-text\n *\n * Reactbits drives the rotation with `motion/react`, which lets the spin\n * angle persist across speed changes. CSS keyframes can't do that — when\n * `animation-duration` changes mid-flight, the browser recomputes the\n * progress as `(elapsed % newDuration) / newDuration`, which visibly\n * jumps the rotation. So this port drives the rotation through the\n * Web Animations API and preserves the current angle when hover swaps\n * the duration. Bonkers `scale` is still CSS-driven (no conflict — the\n * rotation lives on an inner wrapper).\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n type ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n viewChild,\n} from '@angular/core';\n\nimport { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\nimport type { WrCircularTextHover } from './interfaces';\n\ninterface Char {\n readonly ch: string;\n readonly transform: string;\n}\n\n/**\n * Text laid out around a circle, with the whole circle spinning. Hover\n * behaviour swaps the spin rate (or pauses it) — the current rotation\n * angle is preserved across the swap so there's no visible jump.\n *\n * @example\n * ```html\n * <wr-circular-text text=\"HELLO * NGWR * \" />\n * <wr-circular-text text=\"GO BONKERS\" onHover=\"goBonkers\" [spinDuration]=\"12\" />\n * ```\n *\n * @see https://www.reactbits.dev/text-animations/circular-text\n */\n@Component({\n selector: 'wr-circular-text',\n templateUrl: './circular-text.html',\n styleUrl: './circular-text.scss',\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-circular-text',\n '[class.wr-circular-text--bonkers]': \"onHover() === 'goBonkers'\",\n },\n})\nexport class WrCircularText {\n /** Text to lay out around the circle. */\n readonly text = input.required<string>();\n\n /** Seconds per full revolution at rest. @default 20 */\n readonly spinDuration = input(20, { transform: numAttr(20) });\n\n /** Hover behaviour. `null` disables hover reactivity. @default 'speedUp' */\n readonly onHover = input<WrCircularTextHover>('speedUp');\n\n protected readonly chars = computed<readonly Char[]>(() => {\n const letters = Array.from(this.text());\n const len = letters.length;\n if (len === 0) return [];\n return letters.map((ch, i) => {\n const rotation = (360 / len) * i;\n // Rotate around the spinner's centre, then push each char outward\n // by the orbit radius (set via CSS var). All chars end up on a\n // circle of constant radius — not a diagonal line.\n const transform = `rotate(${rotation}deg) translateY(calc(-1 * var(--wr-circular-text-radius)))`;\n return { ch, transform };\n });\n });\n\n private readonly spinEl = viewChild.required<ElementRef<HTMLElement>>('spin');\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly platform = inject(WrPlatform);\n private rotation: Animation | null = null;\n private hovered = false;\n\n /** Active spin duration in seconds — base, or hover-modified. */\n private effectiveDuration(): number | 'pause' {\n const base = this.spinDuration();\n if (!this.hovered) return base;\n switch (this.onHover()) {\n case 'speedUp':\n return base / 4;\n case 'slowDown':\n return base * 2;\n case 'pause':\n return 'pause';\n case 'goBonkers':\n return base / 20;\n default:\n return base;\n }\n }\n\n constructor() {\n if (!this.isBrowser) return;\n\n afterNextRender(() => {\n this.startOrSwap();\n\n const host = this.spinEl().nativeElement.parentElement!;\n const onEnter = (): void => {\n this.hovered = true;\n this.startOrSwap();\n };\n const onLeave = (): void => {\n this.hovered = false;\n this.startOrSwap();\n };\n host.addEventListener('mouseenter', onEnter);\n host.addEventListener('mouseleave', onLeave);\n this.destroyRef.onDestroy(() => {\n host.removeEventListener('mouseenter', onEnter);\n host.removeEventListener('mouseleave', onLeave);\n this.rotation?.cancel();\n });\n });\n\n // React to input changes (spinDuration, onHover) — and the OS\n // reduced-motion setting — without losing angle.\n effect(() => {\n this.spinDuration();\n this.onHover();\n this.platform.prefersReducedMotion();\n queueMicrotask(() => this.startOrSwap());\n });\n }\n\n /**\n * Start the rotation, or swap its duration while preserving the\n * current angle. If the new mode is `pause`, just pause the animation.\n */\n private startOrSwap(): void {\n if (!this.spinEl()) return;\n\n // Reduced motion: hold the ring still — the circular layout is the\n // point of the component; only the revolution is decorative.\n if (this.platform.prefersReducedMotion()) {\n this.rotation?.pause();\n return;\n }\n\n const target = this.effectiveDuration();\n\n if (target === 'pause') {\n this.rotation?.pause();\n return;\n }\n\n const newDurMs = Math.max(1, target * 1000);\n\n // First start — no previous animation to preserve.\n if (!this.rotation) {\n this.rotation = this.spinEl().nativeElement.animate(\n [{ transform: 'rotate(0deg)' }, { transform: 'rotate(360deg)' }],\n { duration: newDurMs, iterations: Infinity, easing: 'linear' }\n );\n return;\n }\n\n // Compute the current angle (0..1 of a full turn) under the old\n // timing, then restart with the new duration seeked to the same\n // angle — keeps the visual continuous across speed changes.\n const oldEffect = this.rotation.effect as KeyframeEffect | null;\n const oldDurMs = (oldEffect?.getTiming().duration as number) || newDurMs || newDurMs;\n const oldTime = (this.rotation.currentTime as number) ?? 0;\n const ratio = (((oldTime % oldDurMs) + oldDurMs) % oldDurMs) / oldDurMs;\n\n this.rotation.cancel();\n this.rotation = this.spinEl().nativeElement.animate(\n [{ transform: 'rotate(0deg)' }, { transform: 'rotate(360deg)' }],\n { duration: newDurMs, iterations: Infinity, easing: 'linear' }\n );\n this.rotation.currentTime = ratio * newDurMs;\n }\n}\n\nexport type { WrCircularTextHover } from './interfaces';\n","<span class=\"wr-circular-text__spin\" #spin>\n @for (c of chars(); track $index) {\n <span class=\"wr-circular-text__char\" [style.transform]=\"c.transform\">{{ c.ch }}</span>\n }\n</span>\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-circular-text.mjs","sources":["../../../projects/lib/circular-text/circular-text.ts","../../../projects/lib/circular-text/circular-text.html","../../../projects/lib/circular-text/ngwr-circular-text.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 * Angular adaptation of the CircularText effect by David Haz / reactbits.dev.\n * Original: https://www.reactbits.dev/text-animations/circular-text\n *\n * Reactbits drives the rotation with `motion/react`, which lets the spin\n * angle persist across speed changes. CSS keyframes can't do that — when\n * `animation-duration` changes mid-flight, the browser recomputes the\n * progress as `(elapsed % newDuration) / newDuration`, which visibly\n * jumps the rotation. So this port drives the rotation through the\n * Web Animations API and preserves the current angle when hover swaps\n * the duration. Bonkers `scale` is still CSS-driven (no conflict — the\n * rotation lives on an inner wrapper).\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n type ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n viewChild,\n} from '@angular/core';\n\nimport { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\nimport type { WrCircularTextHover } from './interfaces';\n\ninterface Char {\n readonly ch: string;\n readonly transform: string;\n}\n\n/**\n * Text laid out around a circle, with the whole circle spinning. Hover\n * behaviour swaps the spin rate (or pauses it) — the current rotation\n * angle is preserved across the swap so there's no visible jump.\n *\n * @example\n * ```html\n * <wr-circular-text text=\"HELLO * NGWR * \" />\n * <wr-circular-text text=\"GO BONKERS\" onHover=\"goBonkers\" [spinDuration]=\"12\" />\n * ```\n *\n * @see https://www.reactbits.dev/text-animations/circular-text\n */\n@Component({\n selector: 'wr-circular-text',\n templateUrl: './circular-text.html',\n styleUrl: './circular-text.scss',\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-circular-text',\n '[class.wr-circular-text--bonkers]': \"onHover() === 'goBonkers'\",\n },\n})\nexport class WrCircularText {\n /** Text to lay out around the circle. */\n readonly text = input.required<string>();\n\n /** Seconds per full revolution at rest. @default 20 */\n readonly spinDuration = input(20, { transform: numAttr(20) });\n\n /** Hover behaviour. `null` disables hover reactivity. @default 'speedUp' */\n readonly onHover = input<WrCircularTextHover>('speedUp');\n\n protected readonly chars = computed<readonly Char[]>(() => {\n const letters = Array.from(this.text());\n const len = letters.length;\n if (len === 0) return [];\n return letters.map((ch, i) => {\n const rotation = (360 / len) * i;\n // Rotate around the spinner's centre, then push each char outward\n // by the orbit radius (set via CSS var). All chars end up on a\n // circle of constant radius — not a diagonal line.\n const transform = `rotate(${rotation}deg) translateY(calc(-1 * var(--wr-circular-text-radius)))`;\n return { ch, transform };\n });\n });\n\n private readonly spinEl = viewChild.required<ElementRef<HTMLElement>>('spin');\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly platform = inject(WrPlatform);\n private rotation: Animation | null = null;\n private hovered = false;\n\n /** Active spin duration in seconds — base, or hover-modified. */\n private effectiveDuration(): number | 'pause' {\n const base = this.spinDuration();\n if (!this.hovered) return base;\n switch (this.onHover()) {\n case 'speedUp':\n return base / 4;\n case 'slowDown':\n return base * 2;\n case 'pause':\n return 'pause';\n case 'goBonkers':\n return base / 20;\n default:\n return base;\n }\n }\n\n constructor() {\n if (!this.isBrowser) return;\n\n afterNextRender(() => {\n this.startOrSwap();\n\n const host = this.spinEl().nativeElement.parentElement!;\n const onEnter = (): void => {\n this.hovered = true;\n this.startOrSwap();\n };\n const onLeave = (): void => {\n this.hovered = false;\n this.startOrSwap();\n };\n host.addEventListener('mouseenter', onEnter);\n host.addEventListener('mouseleave', onLeave);\n this.destroyRef.onDestroy(() => {\n host.removeEventListener('mouseenter', onEnter);\n host.removeEventListener('mouseleave', onLeave);\n this.rotation?.cancel();\n });\n });\n\n // React to input changes (spinDuration, onHover) — and the OS\n // reduced-motion setting — without losing angle.\n effect(() => {\n this.spinDuration();\n this.onHover();\n this.platform.prefersReducedMotion();\n queueMicrotask(() => this.startOrSwap());\n });\n }\n\n /**\n * Start the rotation, or swap its duration while preserving the\n * current angle. If the new mode is `pause`, just pause the animation.\n */\n private startOrSwap(): void {\n if (!this.spinEl()) return;\n\n // Reduced motion: hold the ring still — the circular layout is the\n // point of the component; only the revolution is decorative.\n if (this.platform.prefersReducedMotion()) {\n this.rotation?.pause();\n return;\n }\n\n const target = this.effectiveDuration();\n\n if (target === 'pause') {\n this.rotation?.pause();\n return;\n }\n\n const newDurMs = Math.max(1, target * 1000);\n\n // First start — no previous animation to preserve.\n if (!this.rotation) {\n this.rotation = this.spinEl().nativeElement.animate(\n [{ transform: 'rotate(0deg)' }, { transform: 'rotate(360deg)' }],\n { duration: newDurMs, iterations: Infinity, easing: 'linear' }\n );\n return;\n }\n\n // Compute the current angle (0..1 of a full turn) under the old\n // timing, then restart with the new duration seeked to the same\n // angle — keeps the visual continuous across speed changes.\n const oldEffect = this.rotation.effect as KeyframeEffect | null;\n const oldDurMs = (oldEffect?.getTiming().duration as number) || newDurMs || newDurMs;\n const oldTime = (this.rotation.currentTime as number) ?? 0;\n const ratio = (((oldTime % oldDurMs) + oldDurMs) % oldDurMs) / oldDurMs;\n\n this.rotation.cancel();\n this.rotation = this.spinEl().nativeElement.animate(\n [{ transform: 'rotate(0deg)' }, { transform: 'rotate(360deg)' }],\n { duration: newDurMs, iterations: Infinity, easing: 'linear' }\n );\n this.rotation.currentTime = ratio * newDurMs;\n }\n}\n\nexport type { WrCircularTextHover } from './interfaces';\n","<span class=\"wr-circular-text__spin\" #spin>\n @for (c of chars(); track $index) {\n <span class=\"wr-circular-text__char\" [style.transform]=\"c.transform\">{{ c.ch }}</span>\n }\n</span>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -58,6 +58,10 @@ function matches(item, query) {
58
58
  * @see https://ngwr.dev/reference/components/command-palette
59
59
  */
60
60
  class WrCommandPalette {
61
+ /** Accessible name. Falls back to `commandPalette.label`, then `'Command palette'`. */
62
+ paletteLabel = input(null, /* @ts-ignore */
63
+ ...(ngDevMode ? [{ debugName: "paletteLabel" }] : /* istanbul ignore next */ []));
64
+ resolvedPaletteLabel = useI18nText(this.paletteLabel, 'commandPalette.label', 'Command palette');
61
65
  /** Items shown in the palette. */
62
66
  items = input([], /* @ts-ignore */
63
67
  ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
@@ -258,12 +262,12 @@ class WrCommandPalette {
258
262
  this.close();
259
263
  }
260
264
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrCommandPalette, deps: [], target: i0.ɵɵFactoryTarget.Component });
261
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrCommandPalette, isStandalone: true, selector: "wr-command-palette", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, closeOnPick: { classPropertyName: "closeOnPick", publicName: "closeOnPick", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", picked: "picked" }, viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["input"], descendants: true, isSignal: true }, { propertyName: "panelEl", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (open()) {\n <div\n class=\"wr-command-palette\"\n [class.wr-command-palette--sheet]=\"presentAsSheet()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Command palette\"\n >\n <!-- Backdrop captures clicks to close. Not focusable \u2014 keyboard users use\n Esc on the panel below. -->\n\n <div class=\"wr-command-palette__backdrop\" aria-hidden=\"true\" (click)=\"onBackdropClick()\"></div>\n\n <!-- Keydown is delegated from the search input; tabindex enables Esc when\n the input is unfocused. -->\n <div #panel class=\"wr-command-palette__panel\" tabindex=\"-1\" (keydown)=\"onKeydown($event)\">\n <div class=\"wr-command-palette__search\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle cx=\"7\" cy=\"7\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M11 11 L14 14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n <input\n #input\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-activedescendant]=\"activeOptionId() || null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"query()\"\n (input)=\"onQueryInput($event)\"\n />\n <kbd class=\"wr-command-palette__hint\">esc</kbd>\n </div>\n\n <div class=\"wr-command-palette__body\" role=\"listbox\" [attr.id]=\"listboxId\">\n @if (filtered().length === 0) {\n <div class=\"wr-command-palette__empty\">{{ resolvedEmpty() }}</div>\n } @else {\n @for (bucket of buckets(); track bucket.title) {\n <div class=\"wr-command-palette__group\">\n @if (bucket.title) {\n <div class=\"wr-command-palette__group-title\">{{ bucket.title }}</div>\n }\n @for (item of bucket.items; track item.id) {\n <div\n class=\"wr-command-palette__option\"\n role=\"option\"\n [attr.id]=\"optionId(indexOf(item))\"\n [class.wr-command-palette__option--active]=\"indexOf(item) === activeIndex()\"\n [attr.aria-selected]=\"indexOf(item) === activeIndex()\"\n (mouseenter)=\"onItemHover(item)\"\n (mousedown)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <wr-icon class=\"wr-command-palette__option-icon\" [name]=\"item.icon\" size=\"16\" />\n } @else {\n <span class=\"wr-command-palette__option-icon\" aria-hidden=\"true\"></span>\n }\n <div class=\"wr-command-palette__option-body\">\n <div class=\"wr-command-palette__option-label\">{{ item.label }}</div>\n @if (item.description) {\n <div class=\"wr-command-palette__option-description\">{{ item.description }}</div>\n }\n </div>\n @if (item.shortcut) {\n <kbd class=\"wr-command-palette__option-shortcut\">{{ item.shortcut }}</kbd>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </div>\n}\n", dependencies: [{ kind: "component", type: WrIcon, selector: "wr-icon", inputs: ["name"] }], encapsulation: i0.ViewEncapsulation.None });
265
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrCommandPalette, isStandalone: true, selector: "wr-command-palette", inputs: { paletteLabel: { classPropertyName: "paletteLabel", publicName: "paletteLabel", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, closeOnPick: { classPropertyName: "closeOnPick", publicName: "closeOnPick", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", picked: "picked" }, viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["input"], descendants: true, isSignal: true }, { propertyName: "panelEl", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (open()) {\n <div\n class=\"wr-command-palette\"\n [class.wr-command-palette--sheet]=\"presentAsSheet()\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"resolvedPaletteLabel()\"\n >\n <!-- Backdrop captures clicks to close. Not focusable \u2014 keyboard users use\n Esc on the panel below. -->\n\n <div class=\"wr-command-palette__backdrop\" aria-hidden=\"true\" (click)=\"onBackdropClick()\"></div>\n\n <!-- Keydown is delegated from the search input; tabindex enables Esc when\n the input is unfocused. -->\n <div #panel class=\"wr-command-palette__panel\" tabindex=\"-1\" (keydown)=\"onKeydown($event)\">\n <div class=\"wr-command-palette__search\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle cx=\"7\" cy=\"7\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M11 11 L14 14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n <input\n #input\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-activedescendant]=\"activeOptionId() || null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"query()\"\n (input)=\"onQueryInput($event)\"\n />\n <kbd class=\"wr-command-palette__hint\">esc</kbd>\n </div>\n\n <div class=\"wr-command-palette__body\" role=\"listbox\" [attr.id]=\"listboxId\">\n @if (filtered().length === 0) {\n <div class=\"wr-command-palette__empty\">{{ resolvedEmpty() }}</div>\n } @else {\n @for (bucket of buckets(); track bucket.title) {\n <div class=\"wr-command-palette__group\">\n @if (bucket.title) {\n <div class=\"wr-command-palette__group-title\">{{ bucket.title }}</div>\n }\n @for (item of bucket.items; track item.id) {\n <div\n class=\"wr-command-palette__option\"\n role=\"option\"\n [attr.id]=\"optionId(indexOf(item))\"\n [class.wr-command-palette__option--active]=\"indexOf(item) === activeIndex()\"\n [attr.aria-selected]=\"indexOf(item) === activeIndex()\"\n (mouseenter)=\"onItemHover(item)\"\n (mousedown)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <wr-icon class=\"wr-command-palette__option-icon\" [name]=\"item.icon\" size=\"16\" />\n } @else {\n <span class=\"wr-command-palette__option-icon\" aria-hidden=\"true\"></span>\n }\n <div class=\"wr-command-palette__option-body\">\n <div class=\"wr-command-palette__option-label\">{{ item.label }}</div>\n @if (item.description) {\n <div class=\"wr-command-palette__option-description\">{{ item.description }}</div>\n }\n </div>\n @if (item.shortcut) {\n <kbd class=\"wr-command-palette__option-shortcut\">{{ item.shortcut }}</kbd>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </div>\n}\n", dependencies: [{ kind: "component", type: WrIcon, selector: "wr-icon", inputs: ["name"] }], encapsulation: i0.ViewEncapsulation.None });
262
266
  }
263
267
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrCommandPalette, decorators: [{
264
268
  type: Component,
265
- args: [{ selector: 'wr-command-palette', encapsulation: ViewEncapsulation.None, imports: [WrIcon], template: "@if (open()) {\n <div\n class=\"wr-command-palette\"\n [class.wr-command-palette--sheet]=\"presentAsSheet()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Command palette\"\n >\n <!-- Backdrop captures clicks to close. Not focusable \u2014 keyboard users use\n Esc on the panel below. -->\n\n <div class=\"wr-command-palette__backdrop\" aria-hidden=\"true\" (click)=\"onBackdropClick()\"></div>\n\n <!-- Keydown is delegated from the search input; tabindex enables Esc when\n the input is unfocused. -->\n <div #panel class=\"wr-command-palette__panel\" tabindex=\"-1\" (keydown)=\"onKeydown($event)\">\n <div class=\"wr-command-palette__search\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle cx=\"7\" cy=\"7\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M11 11 L14 14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n <input\n #input\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-activedescendant]=\"activeOptionId() || null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"query()\"\n (input)=\"onQueryInput($event)\"\n />\n <kbd class=\"wr-command-palette__hint\">esc</kbd>\n </div>\n\n <div class=\"wr-command-palette__body\" role=\"listbox\" [attr.id]=\"listboxId\">\n @if (filtered().length === 0) {\n <div class=\"wr-command-palette__empty\">{{ resolvedEmpty() }}</div>\n } @else {\n @for (bucket of buckets(); track bucket.title) {\n <div class=\"wr-command-palette__group\">\n @if (bucket.title) {\n <div class=\"wr-command-palette__group-title\">{{ bucket.title }}</div>\n }\n @for (item of bucket.items; track item.id) {\n <div\n class=\"wr-command-palette__option\"\n role=\"option\"\n [attr.id]=\"optionId(indexOf(item))\"\n [class.wr-command-palette__option--active]=\"indexOf(item) === activeIndex()\"\n [attr.aria-selected]=\"indexOf(item) === activeIndex()\"\n (mouseenter)=\"onItemHover(item)\"\n (mousedown)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <wr-icon class=\"wr-command-palette__option-icon\" [name]=\"item.icon\" size=\"16\" />\n } @else {\n <span class=\"wr-command-palette__option-icon\" aria-hidden=\"true\"></span>\n }\n <div class=\"wr-command-palette__option-body\">\n <div class=\"wr-command-palette__option-label\">{{ item.label }}</div>\n @if (item.description) {\n <div class=\"wr-command-palette__option-description\">{{ item.description }}</div>\n }\n </div>\n @if (item.shortcut) {\n <kbd class=\"wr-command-palette__option-shortcut\">{{ item.shortcut }}</kbd>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </div>\n}\n" }]
266
- }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], closeOnPick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnPick", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], picked: [{ type: i0.Output, args: ["picked"] }], inputEl: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], panelEl: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
269
+ args: [{ selector: 'wr-command-palette', encapsulation: ViewEncapsulation.None, imports: [WrIcon], template: "@if (open()) {\n <div\n class=\"wr-command-palette\"\n [class.wr-command-palette--sheet]=\"presentAsSheet()\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"resolvedPaletteLabel()\"\n >\n <!-- Backdrop captures clicks to close. Not focusable \u2014 keyboard users use\n Esc on the panel below. -->\n\n <div class=\"wr-command-palette__backdrop\" aria-hidden=\"true\" (click)=\"onBackdropClick()\"></div>\n\n <!-- Keydown is delegated from the search input; tabindex enables Esc when\n the input is unfocused. -->\n <div #panel class=\"wr-command-palette__panel\" tabindex=\"-1\" (keydown)=\"onKeydown($event)\">\n <div class=\"wr-command-palette__search\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle cx=\"7\" cy=\"7\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M11 11 L14 14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n <input\n #input\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-activedescendant]=\"activeOptionId() || null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"query()\"\n (input)=\"onQueryInput($event)\"\n />\n <kbd class=\"wr-command-palette__hint\">esc</kbd>\n </div>\n\n <div class=\"wr-command-palette__body\" role=\"listbox\" [attr.id]=\"listboxId\">\n @if (filtered().length === 0) {\n <div class=\"wr-command-palette__empty\">{{ resolvedEmpty() }}</div>\n } @else {\n @for (bucket of buckets(); track bucket.title) {\n <div class=\"wr-command-palette__group\">\n @if (bucket.title) {\n <div class=\"wr-command-palette__group-title\">{{ bucket.title }}</div>\n }\n @for (item of bucket.items; track item.id) {\n <div\n class=\"wr-command-palette__option\"\n role=\"option\"\n [attr.id]=\"optionId(indexOf(item))\"\n [class.wr-command-palette__option--active]=\"indexOf(item) === activeIndex()\"\n [attr.aria-selected]=\"indexOf(item) === activeIndex()\"\n (mouseenter)=\"onItemHover(item)\"\n (mousedown)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <wr-icon class=\"wr-command-palette__option-icon\" [name]=\"item.icon\" size=\"16\" />\n } @else {\n <span class=\"wr-command-palette__option-icon\" aria-hidden=\"true\"></span>\n }\n <div class=\"wr-command-palette__option-body\">\n <div class=\"wr-command-palette__option-label\">{{ item.label }}</div>\n @if (item.description) {\n <div class=\"wr-command-palette__option-description\">{{ item.description }}</div>\n }\n </div>\n @if (item.shortcut) {\n <kbd class=\"wr-command-palette__option-shortcut\">{{ item.shortcut }}</kbd>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </div>\n}\n" }]
270
+ }], ctorParameters: () => [], propDecorators: { paletteLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "paletteLabel", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], closeOnPick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnPick", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], picked: [{ type: i0.Output, args: ["picked"] }], inputEl: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], panelEl: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
267
271
 
268
272
  /**
269
273
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-command-palette.mjs","sources":["../../../projects/lib/command-palette/command-palette.ts","../../../projects/lib/command-palette/command-palette.html","../../../projects/lib/command-palette/ngwr-command-palette.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 ConfigurableFocusTrap, ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';\nimport { type BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n type ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n viewChild,\n} from '@angular/core';\n\nimport { WrHotkey, type WrHotkeyHandle, type WrHotkeySpec } from 'ngwr/hotkey';\nimport { useI18nText } from 'ngwr/i18n';\nimport { WrIcon } from 'ngwr/icon';\nimport { WR_RESPONSIVE_OVERLAYS, wrPresentAsSheet } from 'ngwr/overlay';\n\nimport type { WrCommandItem } from './interfaces';\n\ninterface Bucket {\n readonly title: string | null;\n readonly items: readonly WrCommandItem[];\n}\n\nlet listboxUid = 0;\n\nfunction bucketize(items: readonly WrCommandItem[]): readonly Bucket[] {\n const map = new Map<string | null, WrCommandItem[]>();\n for (const item of items) {\n const key = item.group ?? null;\n const bucket = map.get(key);\n if (bucket) bucket.push(item);\n else map.set(key, [item]);\n }\n return [...map.entries()].map(([title, items]) => ({ title, items }));\n}\n\nfunction matches(item: WrCommandItem, query: string): boolean {\n if (!query) return true;\n const q = query.toLowerCase();\n if (item.label.toLowerCase().includes(q)) return true;\n if (item.description?.toLowerCase().includes(q)) return true;\n if (item.group?.toLowerCase().includes(q)) return true;\n if (item.keywords?.some(k => k.toLowerCase().includes(q))) return true;\n return false;\n}\n\n/**\n * `⌘K`-style command palette — a centred modal with a search input and\n * filtered list of actions. Items can be grouped, have icons, descriptions,\n * and visual shortcut hints.\n *\n * Drop one at the root of the app, pass it the list of commands, and bind\n * a global hotkey (default `'mod+k'`). Use `[(open)]` for controlled\n * visibility, or let it manage itself.\n *\n * @example\n * ```html\n * <wr-command-palette [items]=\"commands\" trigger=\"mod+k\" (picked)=\"onPicked($event)\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/command-palette\n */\n@Component({\n selector: 'wr-command-palette',\n templateUrl: './command-palette.html',\n encapsulation: ViewEncapsulation.None,\n imports: [WrIcon],\n})\nexport class WrCommandPalette {\n /** Items shown in the palette. */\n readonly items = input<readonly WrCommandItem[]>([]);\n\n /** Controlled open state (two-way bindable). @default false */\n readonly open = model(false);\n\n /** Global hotkey that opens the palette. `null` disables auto-binding. @default 'mod+k' */\n readonly trigger = input<WrHotkeySpec | null>('mod+k');\n\n /** Search input placeholder. Falls back to `commandPalette.placeholder`. */\n readonly placeholder = input<string | null>(null);\n\n /** Text shown when no items match. Falls back to `commandPalette.noResults`. */\n readonly emptyText = input<string | null>(null);\n\n protected readonly resolvedPlaceholder = useI18nText(\n this.placeholder,\n 'commandPalette.placeholder',\n 'Type a command or search…'\n );\n protected readonly resolvedEmpty = useI18nText(this.emptyText, 'commandPalette.noResults', 'No results');\n\n /** Auto-close on `(picked)`. Set false to keep open. @default true */\n readonly closeOnPick = input(true, { transform: coerceBooleanProperty });\n\n /**\n * Present the palette full-screen on small viewports instead of a centred\n * modal. `undefined` follows the app-wide `provideWrResponsiveOverlays()`\n * setting; `true`/`false` overrides it. The palette docks to the top (it\n * auto-focuses its input, so the on-screen keyboard stays clear).\n * @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 when the user commits an item (Enter / click). */\n readonly picked = output<WrCommandItem>();\n\n protected readonly query = signal('');\n protected readonly activeIndex = signal(0);\n\n /** Whether the current opening is presented full-screen. Decided on open. */\n protected readonly presentAsSheet = signal(false);\n protected readonly inputEl = viewChild<ElementRef<HTMLInputElement>>('input');\n protected readonly panelEl = viewChild<ElementRef<HTMLElement>>('panel');\n\n /** Listbox id (referenced by the input's `aria-controls`). */\n protected readonly listboxId = `wr-command-palette-listbox-${++listboxUid}`;\n\n /** @internal Build a stable option id for a given flat index. */\n protected optionId(i: number): string {\n return `${this.listboxId}-opt-${i}`;\n }\n\n /** Id of the active option for `aria-activedescendant`. */\n protected readonly activeOptionId = computed<string | null>(() => {\n const i = this.activeIndex();\n return i >= 0 && i < this.filtered().length ? this.optionId(i) : null;\n });\n\n private readonly hotkeys = inject(WrHotkey);\n private readonly responsiveConfig = inject(WR_RESPONSIVE_OVERLAYS);\n private readonly destroyRef = inject(DestroyRef);\n private readonly focusTrapFactory = inject(ConfigurableFocusTrapFactory);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private bindingHandle: WrHotkeyHandle | null = null;\n private focusTrap: ConfigurableFocusTrap | null = null;\n private previouslyFocused: HTMLElement | null = null;\n\n /** Flat filtered list — what keyboard navigation walks. */\n protected readonly filtered = computed<readonly WrCommandItem[]>(() =>\n this.items().filter(item => matches(item, this.query()))\n );\n\n /** Grouped view — what the template renders. */\n protected readonly buckets = computed<readonly Bucket[]>(() => bucketize(this.filtered()));\n\n constructor() {\n // Bind / re-bind the global trigger whenever the spec changes.\n effect(() => {\n this.bindingHandle?.unbind();\n const spec = this.trigger();\n if (!spec) return;\n this.bindingHandle = this.hotkeys.bind(spec, () => this.open.update(v => !v), { allowInInput: true });\n });\n\n // Reset query + active index whenever we open; focus the input.\n effect(() => {\n if (!this.open()) return;\n this.query.set('');\n this.activeIndex.set(0);\n this.presentAsSheet.set(wrPresentAsSheet(this.responsive(), this.responsiveConfig));\n });\n\n // Focus trap + restore.\n effect(() => {\n if (!this.isBrowser) return;\n if (this.open()) {\n const active = document.activeElement;\n this.previouslyFocused = active instanceof HTMLElement ? active : null;\n queueMicrotask(() => {\n const host = this.panelEl()?.nativeElement;\n if (!host) return;\n this.focusTrap?.destroy();\n this.focusTrap = this.focusTrapFactory.create(host);\n void this.focusTrap.focusInitialElementWhenReady();\n });\n } else {\n this.focusTrap?.destroy();\n this.focusTrap = null;\n const restore = this.previouslyFocused;\n this.previouslyFocused = null;\n if (restore && typeof restore.focus === 'function') restore.focus();\n }\n });\n\n afterNextRender(() => {\n if (this.open()) this.inputEl()?.nativeElement.focus();\n });\n\n // Auto-focus the input when opened.\n effect(() => {\n if (!this.open()) return;\n queueMicrotask(() => this.inputEl()?.nativeElement.focus());\n });\n\n // Clamp the active index when the filtered list shrinks.\n effect(() => {\n const max = Math.max(0, this.filtered().length - 1);\n if (this.activeIndex() > max) this.activeIndex.set(max);\n });\n\n this.destroyRef.onDestroy(() => this.bindingHandle?.unbind());\n }\n\n // Template handlers\n\n protected onQueryInput(event: Event): void {\n this.query.set((event.target as HTMLInputElement).value);\n this.activeIndex.set(0);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n const list = this.filtered();\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n if (list.length > 0) this.activeIndex.set((this.activeIndex() + 1) % list.length);\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (list.length > 0) this.activeIndex.set((this.activeIndex() - 1 + list.length) % list.length);\n break;\n case 'Home':\n event.preventDefault();\n this.activeIndex.set(0);\n break;\n case 'End':\n event.preventDefault();\n this.activeIndex.set(Math.max(0, list.length - 1));\n break;\n case 'Enter': {\n event.preventDefault();\n const item = list[this.activeIndex()];\n if (item) this.commit(item);\n break;\n }\n case 'Escape':\n event.preventDefault();\n this.close();\n break;\n default:\n break;\n }\n }\n\n protected onBackdropClick(): void {\n this.close();\n }\n\n protected onItemClick(item: WrCommandItem, event: MouseEvent): void {\n event.preventDefault();\n this.commit(item);\n }\n\n protected onItemHover(item: WrCommandItem): void {\n const i = this.filtered().indexOf(item);\n if (i >= 0) this.activeIndex.set(i);\n }\n\n /** Flat index of an item within the filtered list — for highlight checks. */\n protected indexOf(item: WrCommandItem): number {\n return this.filtered().indexOf(item);\n }\n\n // Public API\n\n /** Open the palette. */\n show(): void {\n this.open.set(true);\n }\n\n /** Close the palette. */\n close(): void {\n this.open.set(false);\n }\n\n // Internals\n\n private commit(item: WrCommandItem): void {\n item.action?.();\n this.picked.emit(item);\n if (this.closeOnPick()) this.close();\n }\n}\n","@if (open()) {\n <div\n class=\"wr-command-palette\"\n [class.wr-command-palette--sheet]=\"presentAsSheet()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Command palette\"\n >\n <!-- Backdrop captures clicks to close. Not focusable — keyboard users use\n Esc on the panel below. -->\n\n <div class=\"wr-command-palette__backdrop\" aria-hidden=\"true\" (click)=\"onBackdropClick()\"></div>\n\n <!-- Keydown is delegated from the search input; tabindex enables Esc when\n the input is unfocused. -->\n <div #panel class=\"wr-command-palette__panel\" tabindex=\"-1\" (keydown)=\"onKeydown($event)\">\n <div class=\"wr-command-palette__search\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle cx=\"7\" cy=\"7\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M11 11 L14 14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n <input\n #input\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-activedescendant]=\"activeOptionId() || null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"query()\"\n (input)=\"onQueryInput($event)\"\n />\n <kbd class=\"wr-command-palette__hint\">esc</kbd>\n </div>\n\n <div class=\"wr-command-palette__body\" role=\"listbox\" [attr.id]=\"listboxId\">\n @if (filtered().length === 0) {\n <div class=\"wr-command-palette__empty\">{{ resolvedEmpty() }}</div>\n } @else {\n @for (bucket of buckets(); track bucket.title) {\n <div class=\"wr-command-palette__group\">\n @if (bucket.title) {\n <div class=\"wr-command-palette__group-title\">{{ bucket.title }}</div>\n }\n @for (item of bucket.items; track item.id) {\n <div\n class=\"wr-command-palette__option\"\n role=\"option\"\n [attr.id]=\"optionId(indexOf(item))\"\n [class.wr-command-palette__option--active]=\"indexOf(item) === activeIndex()\"\n [attr.aria-selected]=\"indexOf(item) === activeIndex()\"\n (mouseenter)=\"onItemHover(item)\"\n (mousedown)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <wr-icon class=\"wr-command-palette__option-icon\" [name]=\"item.icon\" size=\"16\" />\n } @else {\n <span class=\"wr-command-palette__option-icon\" aria-hidden=\"true\"></span>\n }\n <div class=\"wr-command-palette__option-body\">\n <div class=\"wr-command-palette__option-label\">{{ item.label }}</div>\n @if (item.description) {\n <div class=\"wr-command-palette__option-description\">{{ item.description }}</div>\n }\n </div>\n @if (item.shortcut) {\n <kbd class=\"wr-command-palette__option-shortcut\">{{ item.shortcut }}</kbd>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </div>\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-command-palette.mjs","sources":["../../../projects/lib/command-palette/command-palette.ts","../../../projects/lib/command-palette/command-palette.html","../../../projects/lib/command-palette/ngwr-command-palette.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 ConfigurableFocusTrap, ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';\nimport { type BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n type ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n viewChild,\n} from '@angular/core';\n\nimport { WrHotkey, type WrHotkeyHandle, type WrHotkeySpec } from 'ngwr/hotkey';\nimport { useI18nText } from 'ngwr/i18n';\nimport { WrIcon } from 'ngwr/icon';\nimport { WR_RESPONSIVE_OVERLAYS, wrPresentAsSheet } from 'ngwr/overlay';\n\nimport type { WrCommandItem } from './interfaces';\n\ninterface Bucket {\n readonly title: string | null;\n readonly items: readonly WrCommandItem[];\n}\n\nlet listboxUid = 0;\n\nfunction bucketize(items: readonly WrCommandItem[]): readonly Bucket[] {\n const map = new Map<string | null, WrCommandItem[]>();\n for (const item of items) {\n const key = item.group ?? null;\n const bucket = map.get(key);\n if (bucket) bucket.push(item);\n else map.set(key, [item]);\n }\n return [...map.entries()].map(([title, items]) => ({ title, items }));\n}\n\nfunction matches(item: WrCommandItem, query: string): boolean {\n if (!query) return true;\n const q = query.toLowerCase();\n if (item.label.toLowerCase().includes(q)) return true;\n if (item.description?.toLowerCase().includes(q)) return true;\n if (item.group?.toLowerCase().includes(q)) return true;\n if (item.keywords?.some(k => k.toLowerCase().includes(q))) return true;\n return false;\n}\n\n/**\n * `⌘K`-style command palette — a centred modal with a search input and\n * filtered list of actions. Items can be grouped, have icons, descriptions,\n * and visual shortcut hints.\n *\n * Drop one at the root of the app, pass it the list of commands, and bind\n * a global hotkey (default `'mod+k'`). Use `[(open)]` for controlled\n * visibility, or let it manage itself.\n *\n * @example\n * ```html\n * <wr-command-palette [items]=\"commands\" trigger=\"mod+k\" (picked)=\"onPicked($event)\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/command-palette\n */\n@Component({\n selector: 'wr-command-palette',\n templateUrl: './command-palette.html',\n encapsulation: ViewEncapsulation.None,\n imports: [WrIcon],\n})\nexport class WrCommandPalette {\n /** Accessible name. Falls back to `commandPalette.label`, then `'Command palette'`. */\n readonly paletteLabel = input<string | null>(null);\n\n protected readonly resolvedPaletteLabel = useI18nText(this.paletteLabel, 'commandPalette.label', 'Command palette');\n\n /** Items shown in the palette. */\n readonly items = input<readonly WrCommandItem[]>([]);\n\n /** Controlled open state (two-way bindable). @default false */\n readonly open = model(false);\n\n /** Global hotkey that opens the palette. `null` disables auto-binding. @default 'mod+k' */\n readonly trigger = input<WrHotkeySpec | null>('mod+k');\n\n /** Search input placeholder. Falls back to `commandPalette.placeholder`. */\n readonly placeholder = input<string | null>(null);\n\n /** Text shown when no items match. Falls back to `commandPalette.noResults`. */\n readonly emptyText = input<string | null>(null);\n\n protected readonly resolvedPlaceholder = useI18nText(\n this.placeholder,\n 'commandPalette.placeholder',\n 'Type a command or search…'\n );\n protected readonly resolvedEmpty = useI18nText(this.emptyText, 'commandPalette.noResults', 'No results');\n\n /** Auto-close on `(picked)`. Set false to keep open. @default true */\n readonly closeOnPick = input(true, { transform: coerceBooleanProperty });\n\n /**\n * Present the palette full-screen on small viewports instead of a centred\n * modal. `undefined` follows the app-wide `provideWrResponsiveOverlays()`\n * setting; `true`/`false` overrides it. The palette docks to the top (it\n * auto-focuses its input, so the on-screen keyboard stays clear).\n * @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 when the user commits an item (Enter / click). */\n readonly picked = output<WrCommandItem>();\n\n protected readonly query = signal('');\n protected readonly activeIndex = signal(0);\n\n /** Whether the current opening is presented full-screen. Decided on open. */\n protected readonly presentAsSheet = signal(false);\n protected readonly inputEl = viewChild<ElementRef<HTMLInputElement>>('input');\n protected readonly panelEl = viewChild<ElementRef<HTMLElement>>('panel');\n\n /** Listbox id (referenced by the input's `aria-controls`). */\n protected readonly listboxId = `wr-command-palette-listbox-${++listboxUid}`;\n\n /** @internal Build a stable option id for a given flat index. */\n protected optionId(i: number): string {\n return `${this.listboxId}-opt-${i}`;\n }\n\n /** Id of the active option for `aria-activedescendant`. */\n protected readonly activeOptionId = computed<string | null>(() => {\n const i = this.activeIndex();\n return i >= 0 && i < this.filtered().length ? this.optionId(i) : null;\n });\n\n private readonly hotkeys = inject(WrHotkey);\n private readonly responsiveConfig = inject(WR_RESPONSIVE_OVERLAYS);\n private readonly destroyRef = inject(DestroyRef);\n private readonly focusTrapFactory = inject(ConfigurableFocusTrapFactory);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private bindingHandle: WrHotkeyHandle | null = null;\n private focusTrap: ConfigurableFocusTrap | null = null;\n private previouslyFocused: HTMLElement | null = null;\n\n /** Flat filtered list — what keyboard navigation walks. */\n protected readonly filtered = computed<readonly WrCommandItem[]>(() =>\n this.items().filter(item => matches(item, this.query()))\n );\n\n /** Grouped view — what the template renders. */\n protected readonly buckets = computed<readonly Bucket[]>(() => bucketize(this.filtered()));\n\n constructor() {\n // Bind / re-bind the global trigger whenever the spec changes.\n effect(() => {\n this.bindingHandle?.unbind();\n const spec = this.trigger();\n if (!spec) return;\n this.bindingHandle = this.hotkeys.bind(spec, () => this.open.update(v => !v), { allowInInput: true });\n });\n\n // Reset query + active index whenever we open; focus the input.\n effect(() => {\n if (!this.open()) return;\n this.query.set('');\n this.activeIndex.set(0);\n this.presentAsSheet.set(wrPresentAsSheet(this.responsive(), this.responsiveConfig));\n });\n\n // Focus trap + restore.\n effect(() => {\n if (!this.isBrowser) return;\n if (this.open()) {\n const active = document.activeElement;\n this.previouslyFocused = active instanceof HTMLElement ? active : null;\n queueMicrotask(() => {\n const host = this.panelEl()?.nativeElement;\n if (!host) return;\n this.focusTrap?.destroy();\n this.focusTrap = this.focusTrapFactory.create(host);\n void this.focusTrap.focusInitialElementWhenReady();\n });\n } else {\n this.focusTrap?.destroy();\n this.focusTrap = null;\n const restore = this.previouslyFocused;\n this.previouslyFocused = null;\n if (restore && typeof restore.focus === 'function') restore.focus();\n }\n });\n\n afterNextRender(() => {\n if (this.open()) this.inputEl()?.nativeElement.focus();\n });\n\n // Auto-focus the input when opened.\n effect(() => {\n if (!this.open()) return;\n queueMicrotask(() => this.inputEl()?.nativeElement.focus());\n });\n\n // Clamp the active index when the filtered list shrinks.\n effect(() => {\n const max = Math.max(0, this.filtered().length - 1);\n if (this.activeIndex() > max) this.activeIndex.set(max);\n });\n\n this.destroyRef.onDestroy(() => this.bindingHandle?.unbind());\n }\n\n // Template handlers\n\n protected onQueryInput(event: Event): void {\n this.query.set((event.target as HTMLInputElement).value);\n this.activeIndex.set(0);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n const list = this.filtered();\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n if (list.length > 0) this.activeIndex.set((this.activeIndex() + 1) % list.length);\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (list.length > 0) this.activeIndex.set((this.activeIndex() - 1 + list.length) % list.length);\n break;\n case 'Home':\n event.preventDefault();\n this.activeIndex.set(0);\n break;\n case 'End':\n event.preventDefault();\n this.activeIndex.set(Math.max(0, list.length - 1));\n break;\n case 'Enter': {\n event.preventDefault();\n const item = list[this.activeIndex()];\n if (item) this.commit(item);\n break;\n }\n case 'Escape':\n event.preventDefault();\n this.close();\n break;\n default:\n break;\n }\n }\n\n protected onBackdropClick(): void {\n this.close();\n }\n\n protected onItemClick(item: WrCommandItem, event: MouseEvent): void {\n event.preventDefault();\n this.commit(item);\n }\n\n protected onItemHover(item: WrCommandItem): void {\n const i = this.filtered().indexOf(item);\n if (i >= 0) this.activeIndex.set(i);\n }\n\n /** Flat index of an item within the filtered list — for highlight checks. */\n protected indexOf(item: WrCommandItem): number {\n return this.filtered().indexOf(item);\n }\n\n // Public API\n\n /** Open the palette. */\n show(): void {\n this.open.set(true);\n }\n\n /** Close the palette. */\n close(): void {\n this.open.set(false);\n }\n\n // Internals\n\n private commit(item: WrCommandItem): void {\n item.action?.();\n this.picked.emit(item);\n if (this.closeOnPick()) this.close();\n }\n}\n","@if (open()) {\n <div\n class=\"wr-command-palette\"\n [class.wr-command-palette--sheet]=\"presentAsSheet()\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"resolvedPaletteLabel()\"\n >\n <!-- Backdrop captures clicks to close. Not focusable — keyboard users use\n Esc on the panel below. -->\n\n <div class=\"wr-command-palette__backdrop\" aria-hidden=\"true\" (click)=\"onBackdropClick()\"></div>\n\n <!-- Keydown is delegated from the search input; tabindex enables Esc when\n the input is unfocused. -->\n <div #panel class=\"wr-command-palette__panel\" tabindex=\"-1\" (keydown)=\"onKeydown($event)\">\n <div class=\"wr-command-palette__search\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle cx=\"7\" cy=\"7\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M11 11 L14 14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n <input\n #input\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-activedescendant]=\"activeOptionId() || null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"query()\"\n (input)=\"onQueryInput($event)\"\n />\n <kbd class=\"wr-command-palette__hint\">esc</kbd>\n </div>\n\n <div class=\"wr-command-palette__body\" role=\"listbox\" [attr.id]=\"listboxId\">\n @if (filtered().length === 0) {\n <div class=\"wr-command-palette__empty\">{{ resolvedEmpty() }}</div>\n } @else {\n @for (bucket of buckets(); track bucket.title) {\n <div class=\"wr-command-palette__group\">\n @if (bucket.title) {\n <div class=\"wr-command-palette__group-title\">{{ bucket.title }}</div>\n }\n @for (item of bucket.items; track item.id) {\n <div\n class=\"wr-command-palette__option\"\n role=\"option\"\n [attr.id]=\"optionId(indexOf(item))\"\n [class.wr-command-palette__option--active]=\"indexOf(item) === activeIndex()\"\n [attr.aria-selected]=\"indexOf(item) === activeIndex()\"\n (mouseenter)=\"onItemHover(item)\"\n (mousedown)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <wr-icon class=\"wr-command-palette__option-icon\" [name]=\"item.icon\" size=\"16\" />\n } @else {\n <span class=\"wr-command-palette__option-icon\" aria-hidden=\"true\"></span>\n }\n <div class=\"wr-command-palette__option-body\">\n <div class=\"wr-command-palette__option-label\">{{ item.label }}</div>\n @if (item.description) {\n <div class=\"wr-command-palette__option-description\">{{ item.description }}</div>\n }\n </div>\n @if (item.shortcut) {\n <kbd class=\"wr-command-palette__option-shortcut\">{{ item.shortcut }}</kbd>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -315,7 +315,15 @@ class WrCountUp {
315
315
  if (this.trigger() === 'visible')
316
316
  this.setupViewportTrigger();
317
317
  });
318
- this.destroyRef.onDestroy(() => this.cancel());
318
+ this.destroyRef.onDestroy(() => {
319
+ this.cancel();
320
+ // `cancel()` only stops timers and the rAF loop. The IntersectionObserver
321
+ // disconnects itself from inside its callback, which never fires if the
322
+ // host is destroyed before it ever scrolls into view — so it would keep
323
+ // observing a detached element for the life of the page.
324
+ this.observer?.disconnect();
325
+ this.observer = null;
326
+ });
319
327
  }
320
328
  // Scheduling
321
329
  setupViewportTrigger() {
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-counter.mjs","sources":["../../../projects/lib/counter/easing.ts","../../../projects/lib/counter/counter.ts","../../../projects/lib/counter/counter.html","../../../projects/lib/counter/count-up.ts","../../../projects/lib/counter/ngwr-counter.ts"],"sourcesContent":["/** Cubic ease-out — the shared tween curve for counter / count-up. */\nexport function easeOutCubic(t: number): number {\n return 1 - Math.pow(1 - t, 3);\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 { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n LOCALE_ID,\n PLATFORM_ID,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n} from '@angular/core';\n\nimport { easeOutCubic } from './easing';\nimport type { WrCounterMode } from './interfaces';\n\n/** Visual cell in odometer mode — either a 0-9 column or a static glyph. */\ntype Cell = { readonly kind: 'digit'; readonly fraction: number } | { readonly kind: 'static'; readonly char: string };\n\n/**\n * Animated number display with two modes:\n *\n * - **`odometer`** (default) — each digit is a vertical strip of 0-9 that\n * rolls into place, continuously interpolated for smooth motion when the\n * value changes.\n * - **`tween`** — a single eased count-up between the previous and new value,\n * rendered through `Intl.NumberFormat`.\n *\n * Reacts to `[value]` changes — animate from any number to any number.\n *\n * @example\n * ```html\n * <wr-counter [value]=\"123456\" mode=\"odometer\" />\n * <wr-counter [value]=\"9.99\" mode=\"tween\" [decimals]=\"2\" prefix=\"$\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/counter\n */\n@Component({\n selector: 'wr-counter',\n templateUrl: './counter.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-counter' },\n})\nexport class WrCounter {\n /** Target value. */\n readonly value = input.required<number>();\n\n /** Animation mode. @default 'odometer' */\n readonly mode = input<WrCounterMode>('odometer');\n\n /** Duration (ms). @default 900 */\n readonly duration = input(900, {\n transform: (v: unknown): number => Math.max(100, coerceNumberProperty(v, 900)),\n });\n\n /** Fixed number of decimals. @default 0 */\n readonly decimals = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Optional prefix (e.g. `'$'`). */\n readonly prefix = input<string>('');\n\n /** Optional suffix (e.g. `'%'`). */\n readonly suffix = input<string>('');\n\n /** Group thousands. @default true */\n readonly grouping = input<boolean>(true);\n\n /** Pad integer part to at least this many digits. @default 0 (no padding) */\n readonly minIntegerDigits = input(0, {\n transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)),\n });\n\n private readonly current = signal<number>(0);\n private readonly locale = inject(LOCALE_ID);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private rafId: number | null = null;\n\n /** Tween-mode formatted output. */\n protected readonly tweenText = computed(() => this.format(this.current()));\n\n /**\n * Odometer-mode text for assistive tech and prerendered output. The strip\n * renders every digit 0-9 per column and picks one with a transform, so its\n * markup carries no usable text — screen readers would announce all ten, and\n * static HTML would ship the same noise. This node holds the real value.\n */\n protected readonly odoText = computed(() => `${this.prefix()}${this.format(this.value())}${this.suffix()}`);\n\n /** Odometer cells — one per character in the formatted target string. */\n protected readonly cells = computed<readonly Cell[]>(() => {\n // Build the string with target sign + max length so we can interpolate\n // each digit position smoothly.\n const target = this.value();\n const live = this.current();\n const formattedTarget = this.format(target);\n const formattedLive = this.format(live);\n\n // Right-align so trailing digits line up.\n const maxLen = Math.max(formattedTarget.length, formattedLive.length);\n const padTarget = formattedTarget.padStart(maxLen, ' ');\n const padLive = formattedLive.padStart(maxLen, ' ');\n\n const cells: Cell[] = [];\n for (let i = 0; i < maxLen; i++) {\n const t = padTarget[i];\n const l = padLive[i];\n if (/[0-9]/.test(t) && /[0-9]/.test(l)) {\n // Interpolate the fractional digit so the strip rolls smoothly —\n // multi-digit rollover (9 → 0 carries 1) looks continuous.\n const fraction = this.digitFractionAt(live, target, i, maxLen);\n cells.push({ kind: 'digit', fraction });\n } else {\n cells.push({ kind: 'static', char: t === ' ' ? '' : t });\n }\n }\n return cells;\n });\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.cancel());\n\n effect(() => {\n const target = this.value();\n // Snapshot the current value WITHOUT tracking it — the RAF tick below\n // writes `current` every frame, and tracking it here would re-trigger\n // this effect each frame, cancelling + restarting the tween endlessly\n // (the wheels hang mid-roll and only snap once the restarts converge).\n const start = untracked(() => this.current());\n if (!this.isBrowser) {\n this.current.set(target);\n return;\n }\n this.cancel();\n const startTs = performance.now();\n const dur = this.duration();\n const tick = (now: number): void => {\n const t = Math.min(1, (now - startTs) / dur);\n // Snap exactly to target on the final frame. Without this,\n // `start + (target - start) * 1` carries FP rounding (e.g.\n // 0.1 + (0.3 - 0.1) * 1 = 0.30000000000000004), so\n // `digitFractionAt`'s `live === target` rest-state check\n // fails — wheels visibly stop on a fractional position and\n // never settle to the clean integer glyph.\n const v = t >= 1 ? target : start + (target - start) * easeOutCubic(t);\n this.current.set(v);\n if (t < 1) this.rafId = requestAnimationFrame(tick);\n else this.rafId = null;\n };\n this.rafId = requestAnimationFrame(tick);\n });\n }\n\n private cancel(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n private format(n: number): string {\n return new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: this.decimals(),\n maximumFractionDigits: this.decimals(),\n minimumIntegerDigits: this.minIntegerDigits() || 1,\n useGrouping: this.grouping(),\n }).format(n);\n }\n\n /**\n * Compute the smoothly-interpolated digit (0..10) at column `i` of the\n * formatted live string. Returns the integer digit + a fraction so the\n * strip CSS translate looks like a real rolling odometer.\n */\n private digitFractionAt(live: number, target: number, columnIndex: number, totalLen: number): number {\n // Determine the place value at this column. Account for grouping separators\n // and the decimal point by counting digits to the right of this column in\n // the formatted target.\n const formattedTarget = this.format(target);\n const padded = formattedTarget.padStart(totalLen, ' ');\n const tail = padded.slice(columnIndex + 1);\n const digitsRight = (tail.match(/[0-9]/g) ?? []).length;\n const placePower = digitsRight - this.decimals();\n const place = Math.pow(10, placePower);\n const absLive = Math.abs(live);\n const raw = absLive / place;\n // Modulo 10 gives the digit at this column with fractional rollover —\n // mid-animation this looks like a real wheel rolling between digits.\n const mod = raw - Math.floor(raw / 10) * 10;\n // At rest (live === target) every wheel must rest on an exact integer\n // — otherwise upper digits show as partial (e.g. tens reads \"5.6\"\n // for value 123456, visibly clipping between 5 and 6 in the\n // overflow:hidden window). The continuous-mechanical look is only\n // wanted DURING the tween, not after it settles.\n if (live === target) return Math.floor(mod + 1e-9);\n return mod;\n }\n}\n","@if (mode() === 'tween') {\n <span class=\"wr-counter__tween\">{{ prefix() }}{{ tweenText() }}{{ suffix() }}</span>\n} @else {\n <span class=\"wr-counter__sr-only\">{{ odoText() }}</span>\n <span class=\"wr-counter__odo\" aria-hidden=\"true\">\n @if (prefix()) {\n <span class=\"wr-counter__static\">{{ prefix() }}</span>\n }\n @for (cell of cells(); track $index) {\n @if (cell.kind === 'digit') {\n <span class=\"wr-counter__digit\">\n <span class=\"wr-counter__strip\" [style.transform]=\"`translateY(-${cell.fraction}em)`\">\n <span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span\n ><span>7</span><span>8</span><span>9</span>\n </span>\n </span>\n } @else {\n <span class=\"wr-counter__static\">{{ cell.char }}</span>\n }\n }\n @if (suffix()) {\n <span class=\"wr-counter__static\">{{ suffix() }}</span>\n }\n </span>\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 * The spring-physics path is an adaptation of the CountUp effect by\n * David Haz / reactbits.dev (https://www.reactbits.dev/text-animations/count-up).\n * Same critically-damped formula, implemented inline with rAF — no\n * external dependency.\n */\n\nimport { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n LOCALE_ID,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { numAttr } from 'ngwr/utils';\n\nimport { easeOutCubic } from './easing';\nimport type { WrCountUpDirection, WrCountUpEasing, WrCountUpTrigger } from './interfaces';\n\n/**\n * Animated number tick. Animates from `from` to the current `to`, formatting\n * via `Intl.NumberFormat`. Re-runs whenever `to` changes.\n *\n * @example Basic\n * ```html\n * <wr-count-up [to]=\"12345\" />\n * <wr-count-up [to]=\"9.99\" [decimals]=\"2\" prefix=\"$\" />\n * ```\n *\n * @example Reactbits-style — spring curve + viewport trigger\n * ```html\n * <wr-count-up [to]=\"100\" easing=\"spring\" trigger=\"visible\" [delay]=\"200\" />\n * ```\n *\n * @example Count down\n * ```html\n * <wr-count-up [from]=\"60\" [to]=\"0\" direction=\"down\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/counter\n */\n@Component({\n selector: 'wr-count-up',\n template: `{{ prefix() }}{{ formatted() }}{{ suffix() }}`,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-count-up' },\n})\nexport class WrCountUp {\n /** Starting value. @default 0 */\n readonly from = input(0, { transform: numAttr(0) });\n\n /** Target value. */\n readonly to = input.required<number>();\n\n /**\n * Animation duration. Units depend on `easing`:\n *\n * - `ease-out` — milliseconds (default 1200, min 100)\n * - `spring` — seconds (tunes spring stiffness; default 2)\n */\n readonly duration = input(1200, { transform: numAttr(1200) });\n\n /** Optional delay (ms) before the animation starts. @default 0 */\n readonly delay = input(0, { transform: numAttr(0) });\n\n /** Animation curve. @default 'ease-out' */\n readonly easing = input<WrCountUpEasing>('ease-out');\n\n /**\n * When to start the animation.\n *\n * - `'mount'` (default) — start as soon as the component is rendered.\n * - `'visible'` — wait for the host to enter the viewport\n * (IntersectionObserver). Useful for long pages or hero numbers\n * below the fold.\n */\n readonly trigger = input<WrCountUpTrigger>('mount');\n\n /** Counting direction. `'down'` swaps `from` ↔ `to`. @default 'up' */\n readonly direction = input<WrCountUpDirection>('up');\n\n /** Fixed number of decimals. @default 0 */\n readonly decimals = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Optional prefix (e.g. `'$'`). */\n readonly prefix = input<string>('');\n\n /** Optional suffix (e.g. `'%'`). */\n readonly suffix = input<string>('');\n\n /** Disable grouping separators (`1,234` → `1234`). @default true (grouping on) */\n readonly grouping = input<boolean>(true);\n\n /** Emits when the animation begins. */\n readonly started = output<void>();\n\n /** Emits when the animation settles. */\n readonly completed = output<void>();\n\n private readonly value = signal<number>(0);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly locale = inject(LOCALE_ID);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly destroyRef = inject(DestroyRef);\n\n private rafId: number | null = null;\n private delayTimer: ReturnType<typeof setTimeout> | undefined;\n private observer: IntersectionObserver | null = null;\n private hasFiredForVisible = false;\n\n protected readonly formatted = computed(() => {\n return new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: this.decimals(),\n maximumFractionDigits: this.decimals(),\n useGrouping: this.grouping(),\n }).format(this.value());\n });\n\n constructor() {\n if (!this.isBrowser) {\n // SSR: settle on the value the animation ENDS on. Seeding the start\n // instead would bake the placeholder (usually 0) into prerendered HTML,\n // so readers and crawlers would get 0 rather than the real figure. The\n // browser rewinds to the start and animates once it boots.\n effect(() => this.value.set(this.direction() === 'down' ? this.from() : this.to()));\n return;\n }\n\n // Seed the resting value so first paint shows the start, not 0.\n effect(() => {\n const initial = this.direction() === 'down' ? this.to() : this.from();\n this.value.set(initial);\n });\n\n // Run the animation whenever the `to` target changes (or on first mount).\n // For `trigger=\"visible\"` the first run waits for the IntersectionObserver\n // to fire; subsequent `to` changes re-run immediately.\n effect(() => {\n // Establish dependencies so the effect re-runs on `to` changes.\n this.to();\n this.from();\n this.direction();\n this.duration();\n this.easing();\n this.delay();\n\n if (this.trigger() === 'visible' && !this.hasFiredForVisible) return;\n this.scheduleRun();\n });\n\n afterNextRender(() => {\n if (this.trigger() === 'visible') this.setupViewportTrigger();\n });\n\n this.destroyRef.onDestroy(() => this.cancel());\n }\n\n // Scheduling\n\n private setupViewportTrigger(): void {\n this.observer = new IntersectionObserver(\n (entries, obs) => {\n for (const e of entries) {\n if (e.isIntersecting && !this.hasFiredForVisible) {\n obs.disconnect();\n this.hasFiredForVisible = true;\n this.scheduleRun();\n break;\n }\n }\n },\n { threshold: 0, rootMargin: '0px' }\n );\n this.observer.observe(this.host.nativeElement);\n }\n\n private scheduleRun(): void {\n this.cancel();\n const d = this.delay();\n if (d > 0) {\n this.delayTimer = setTimeout(() => this.run(), d);\n } else {\n this.run();\n }\n }\n\n private run(): void {\n const start = this.direction() === 'down' ? this.to() : this.from();\n const end = this.direction() === 'down' ? this.from() : this.to();\n this.started.emit();\n if (this.easing() === 'spring') this.tweenSpring(start, end);\n else this.tweenEaseOut(start, end);\n }\n\n // Tweens\n\n private tweenEaseOut(start: number, target: number): void {\n const duration = Math.max(100, this.duration());\n const startTs = performance.now();\n const tick = (now: number): void => {\n const t = Math.min(1, (now - startTs) / duration);\n const v = start + (target - start) * easeOutCubic(t);\n this.value.set(v);\n if (t < 1) {\n this.rafId = requestAnimationFrame(tick);\n } else {\n this.completed.emit();\n }\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n /**\n * Critically-damped spring tween. Same formula as `motion/react`'s\n * `useSpring` with mass = 1:\n *\n * damping = 20 + 40 / duration\n * stiffness = 100 / duration\n *\n * We integrate `(spring force − damping force)` each frame until both\n * displacement and velocity fall below epsilon.\n */\n private tweenSpring(start: number, target: number): void {\n const duration = Math.max(0.05, this.duration());\n const damping = 20 + 40 / duration;\n const stiffness = 100 / duration;\n let current = start;\n let velocity = 0;\n let lastTs = 0;\n const epsilon = 0.001 * Math.max(1, Math.abs(target - start));\n\n const step = (ts: number): void => {\n const dt = lastTs === 0 ? 1 / 60 : Math.min(0.05, (ts - lastTs) / 1000);\n lastTs = ts;\n\n const displacement = current - target;\n const accel = -stiffness * displacement - damping * velocity;\n velocity += accel * dt;\n current += velocity * dt;\n this.value.set(current);\n\n if (Math.abs(current - target) < epsilon && Math.abs(velocity) < epsilon * 10) {\n this.value.set(target);\n this.completed.emit();\n return;\n }\n this.rafId = requestAnimationFrame(step);\n };\n this.rafId = requestAnimationFrame(step);\n }\n\n // Cleanup\n\n private cancel(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.rafId = null;\n if (this.delayTimer !== undefined) {\n clearTimeout(this.delayTimer);\n this.delayTimer = undefined;\n }\n }\n}\n\nexport type { WrCountUpEasing, WrCountUpTrigger, WrCountUpDirection } from './interfaces';\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-counter.mjs","sources":["../../../projects/lib/counter/easing.ts","../../../projects/lib/counter/counter.ts","../../../projects/lib/counter/counter.html","../../../projects/lib/counter/count-up.ts","../../../projects/lib/counter/ngwr-counter.ts"],"sourcesContent":["/** Cubic ease-out — the shared tween curve for counter / count-up. */\nexport function easeOutCubic(t: number): number {\n return 1 - Math.pow(1 - t, 3);\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 { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n LOCALE_ID,\n PLATFORM_ID,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n} from '@angular/core';\n\nimport { easeOutCubic } from './easing';\nimport type { WrCounterMode } from './interfaces';\n\n/** Visual cell in odometer mode — either a 0-9 column or a static glyph. */\ntype Cell = { readonly kind: 'digit'; readonly fraction: number } | { readonly kind: 'static'; readonly char: string };\n\n/**\n * Animated number display with two modes:\n *\n * - **`odometer`** (default) — each digit is a vertical strip of 0-9 that\n * rolls into place, continuously interpolated for smooth motion when the\n * value changes.\n * - **`tween`** — a single eased count-up between the previous and new value,\n * rendered through `Intl.NumberFormat`.\n *\n * Reacts to `[value]` changes — animate from any number to any number.\n *\n * @example\n * ```html\n * <wr-counter [value]=\"123456\" mode=\"odometer\" />\n * <wr-counter [value]=\"9.99\" mode=\"tween\" [decimals]=\"2\" prefix=\"$\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/counter\n */\n@Component({\n selector: 'wr-counter',\n templateUrl: './counter.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-counter' },\n})\nexport class WrCounter {\n /** Target value. */\n readonly value = input.required<number>();\n\n /** Animation mode. @default 'odometer' */\n readonly mode = input<WrCounterMode>('odometer');\n\n /** Duration (ms). @default 900 */\n readonly duration = input(900, {\n transform: (v: unknown): number => Math.max(100, coerceNumberProperty(v, 900)),\n });\n\n /** Fixed number of decimals. @default 0 */\n readonly decimals = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Optional prefix (e.g. `'$'`). */\n readonly prefix = input<string>('');\n\n /** Optional suffix (e.g. `'%'`). */\n readonly suffix = input<string>('');\n\n /** Group thousands. @default true */\n readonly grouping = input<boolean>(true);\n\n /** Pad integer part to at least this many digits. @default 0 (no padding) */\n readonly minIntegerDigits = input(0, {\n transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)),\n });\n\n private readonly current = signal<number>(0);\n private readonly locale = inject(LOCALE_ID);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private rafId: number | null = null;\n\n /** Tween-mode formatted output. */\n protected readonly tweenText = computed(() => this.format(this.current()));\n\n /**\n * Odometer-mode text for assistive tech and prerendered output. The strip\n * renders every digit 0-9 per column and picks one with a transform, so its\n * markup carries no usable text — screen readers would announce all ten, and\n * static HTML would ship the same noise. This node holds the real value.\n */\n protected readonly odoText = computed(() => `${this.prefix()}${this.format(this.value())}${this.suffix()}`);\n\n /** Odometer cells — one per character in the formatted target string. */\n protected readonly cells = computed<readonly Cell[]>(() => {\n // Build the string with target sign + max length so we can interpolate\n // each digit position smoothly.\n const target = this.value();\n const live = this.current();\n const formattedTarget = this.format(target);\n const formattedLive = this.format(live);\n\n // Right-align so trailing digits line up.\n const maxLen = Math.max(formattedTarget.length, formattedLive.length);\n const padTarget = formattedTarget.padStart(maxLen, ' ');\n const padLive = formattedLive.padStart(maxLen, ' ');\n\n const cells: Cell[] = [];\n for (let i = 0; i < maxLen; i++) {\n const t = padTarget[i];\n const l = padLive[i];\n if (/[0-9]/.test(t) && /[0-9]/.test(l)) {\n // Interpolate the fractional digit so the strip rolls smoothly —\n // multi-digit rollover (9 → 0 carries 1) looks continuous.\n const fraction = this.digitFractionAt(live, target, i, maxLen);\n cells.push({ kind: 'digit', fraction });\n } else {\n cells.push({ kind: 'static', char: t === ' ' ? '' : t });\n }\n }\n return cells;\n });\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.cancel());\n\n effect(() => {\n const target = this.value();\n // Snapshot the current value WITHOUT tracking it — the RAF tick below\n // writes `current` every frame, and tracking it here would re-trigger\n // this effect each frame, cancelling + restarting the tween endlessly\n // (the wheels hang mid-roll and only snap once the restarts converge).\n const start = untracked(() => this.current());\n if (!this.isBrowser) {\n this.current.set(target);\n return;\n }\n this.cancel();\n const startTs = performance.now();\n const dur = this.duration();\n const tick = (now: number): void => {\n const t = Math.min(1, (now - startTs) / dur);\n // Snap exactly to target on the final frame. Without this,\n // `start + (target - start) * 1` carries FP rounding (e.g.\n // 0.1 + (0.3 - 0.1) * 1 = 0.30000000000000004), so\n // `digitFractionAt`'s `live === target` rest-state check\n // fails — wheels visibly stop on a fractional position and\n // never settle to the clean integer glyph.\n const v = t >= 1 ? target : start + (target - start) * easeOutCubic(t);\n this.current.set(v);\n if (t < 1) this.rafId = requestAnimationFrame(tick);\n else this.rafId = null;\n };\n this.rafId = requestAnimationFrame(tick);\n });\n }\n\n private cancel(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n private format(n: number): string {\n return new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: this.decimals(),\n maximumFractionDigits: this.decimals(),\n minimumIntegerDigits: this.minIntegerDigits() || 1,\n useGrouping: this.grouping(),\n }).format(n);\n }\n\n /**\n * Compute the smoothly-interpolated digit (0..10) at column `i` of the\n * formatted live string. Returns the integer digit + a fraction so the\n * strip CSS translate looks like a real rolling odometer.\n */\n private digitFractionAt(live: number, target: number, columnIndex: number, totalLen: number): number {\n // Determine the place value at this column. Account for grouping separators\n // and the decimal point by counting digits to the right of this column in\n // the formatted target.\n const formattedTarget = this.format(target);\n const padded = formattedTarget.padStart(totalLen, ' ');\n const tail = padded.slice(columnIndex + 1);\n const digitsRight = (tail.match(/[0-9]/g) ?? []).length;\n const placePower = digitsRight - this.decimals();\n const place = Math.pow(10, placePower);\n const absLive = Math.abs(live);\n const raw = absLive / place;\n // Modulo 10 gives the digit at this column with fractional rollover —\n // mid-animation this looks like a real wheel rolling between digits.\n const mod = raw - Math.floor(raw / 10) * 10;\n // At rest (live === target) every wheel must rest on an exact integer\n // — otherwise upper digits show as partial (e.g. tens reads \"5.6\"\n // for value 123456, visibly clipping between 5 and 6 in the\n // overflow:hidden window). The continuous-mechanical look is only\n // wanted DURING the tween, not after it settles.\n if (live === target) return Math.floor(mod + 1e-9);\n return mod;\n }\n}\n","@if (mode() === 'tween') {\n <span class=\"wr-counter__tween\">{{ prefix() }}{{ tweenText() }}{{ suffix() }}</span>\n} @else {\n <span class=\"wr-counter__sr-only\">{{ odoText() }}</span>\n <span class=\"wr-counter__odo\" aria-hidden=\"true\">\n @if (prefix()) {\n <span class=\"wr-counter__static\">{{ prefix() }}</span>\n }\n @for (cell of cells(); track $index) {\n @if (cell.kind === 'digit') {\n <span class=\"wr-counter__digit\">\n <span class=\"wr-counter__strip\" [style.transform]=\"`translateY(-${cell.fraction}em)`\">\n <span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span\n ><span>7</span><span>8</span><span>9</span>\n </span>\n </span>\n } @else {\n <span class=\"wr-counter__static\">{{ cell.char }}</span>\n }\n }\n @if (suffix()) {\n <span class=\"wr-counter__static\">{{ suffix() }}</span>\n }\n </span>\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 * The spring-physics path is an adaptation of the CountUp effect by\n * David Haz / reactbits.dev (https://www.reactbits.dev/text-animations/count-up).\n * Same critically-damped formula, implemented inline with rAF — no\n * external dependency.\n */\n\nimport { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n LOCALE_ID,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { numAttr } from 'ngwr/utils';\n\nimport { easeOutCubic } from './easing';\nimport type { WrCountUpDirection, WrCountUpEasing, WrCountUpTrigger } from './interfaces';\n\n/**\n * Animated number tick. Animates from `from` to the current `to`, formatting\n * via `Intl.NumberFormat`. Re-runs whenever `to` changes.\n *\n * @example Basic\n * ```html\n * <wr-count-up [to]=\"12345\" />\n * <wr-count-up [to]=\"9.99\" [decimals]=\"2\" prefix=\"$\" />\n * ```\n *\n * @example Reactbits-style — spring curve + viewport trigger\n * ```html\n * <wr-count-up [to]=\"100\" easing=\"spring\" trigger=\"visible\" [delay]=\"200\" />\n * ```\n *\n * @example Count down\n * ```html\n * <wr-count-up [from]=\"60\" [to]=\"0\" direction=\"down\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/counter\n */\n@Component({\n selector: 'wr-count-up',\n template: `{{ prefix() }}{{ formatted() }}{{ suffix() }}`,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-count-up' },\n})\nexport class WrCountUp {\n /** Starting value. @default 0 */\n readonly from = input(0, { transform: numAttr(0) });\n\n /** Target value. */\n readonly to = input.required<number>();\n\n /**\n * Animation duration. Units depend on `easing`:\n *\n * - `ease-out` — milliseconds (default 1200, min 100)\n * - `spring` — seconds (tunes spring stiffness; default 2)\n */\n readonly duration = input(1200, { transform: numAttr(1200) });\n\n /** Optional delay (ms) before the animation starts. @default 0 */\n readonly delay = input(0, { transform: numAttr(0) });\n\n /** Animation curve. @default 'ease-out' */\n readonly easing = input<WrCountUpEasing>('ease-out');\n\n /**\n * When to start the animation.\n *\n * - `'mount'` (default) — start as soon as the component is rendered.\n * - `'visible'` — wait for the host to enter the viewport\n * (IntersectionObserver). Useful for long pages or hero numbers\n * below the fold.\n */\n readonly trigger = input<WrCountUpTrigger>('mount');\n\n /** Counting direction. `'down'` swaps `from` ↔ `to`. @default 'up' */\n readonly direction = input<WrCountUpDirection>('up');\n\n /** Fixed number of decimals. @default 0 */\n readonly decimals = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Optional prefix (e.g. `'$'`). */\n readonly prefix = input<string>('');\n\n /** Optional suffix (e.g. `'%'`). */\n readonly suffix = input<string>('');\n\n /** Disable grouping separators (`1,234` → `1234`). @default true (grouping on) */\n readonly grouping = input<boolean>(true);\n\n /** Emits when the animation begins. */\n readonly started = output<void>();\n\n /** Emits when the animation settles. */\n readonly completed = output<void>();\n\n private readonly value = signal<number>(0);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly locale = inject(LOCALE_ID);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly destroyRef = inject(DestroyRef);\n\n private rafId: number | null = null;\n private delayTimer: ReturnType<typeof setTimeout> | undefined;\n private observer: IntersectionObserver | null = null;\n private hasFiredForVisible = false;\n\n protected readonly formatted = computed(() => {\n return new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: this.decimals(),\n maximumFractionDigits: this.decimals(),\n useGrouping: this.grouping(),\n }).format(this.value());\n });\n\n constructor() {\n if (!this.isBrowser) {\n // SSR: settle on the value the animation ENDS on. Seeding the start\n // instead would bake the placeholder (usually 0) into prerendered HTML,\n // so readers and crawlers would get 0 rather than the real figure. The\n // browser rewinds to the start and animates once it boots.\n effect(() => this.value.set(this.direction() === 'down' ? this.from() : this.to()));\n return;\n }\n\n // Seed the resting value so first paint shows the start, not 0.\n effect(() => {\n const initial = this.direction() === 'down' ? this.to() : this.from();\n this.value.set(initial);\n });\n\n // Run the animation whenever the `to` target changes (or on first mount).\n // For `trigger=\"visible\"` the first run waits for the IntersectionObserver\n // to fire; subsequent `to` changes re-run immediately.\n effect(() => {\n // Establish dependencies so the effect re-runs on `to` changes.\n this.to();\n this.from();\n this.direction();\n this.duration();\n this.easing();\n this.delay();\n\n if (this.trigger() === 'visible' && !this.hasFiredForVisible) return;\n this.scheduleRun();\n });\n\n afterNextRender(() => {\n if (this.trigger() === 'visible') this.setupViewportTrigger();\n });\n\n this.destroyRef.onDestroy(() => {\n this.cancel();\n // `cancel()` only stops timers and the rAF loop. The IntersectionObserver\n // disconnects itself from inside its callback, which never fires if the\n // host is destroyed before it ever scrolls into view — so it would keep\n // observing a detached element for the life of the page.\n this.observer?.disconnect();\n this.observer = null;\n });\n }\n\n // Scheduling\n\n private setupViewportTrigger(): void {\n this.observer = new IntersectionObserver(\n (entries, obs) => {\n for (const e of entries) {\n if (e.isIntersecting && !this.hasFiredForVisible) {\n obs.disconnect();\n this.hasFiredForVisible = true;\n this.scheduleRun();\n break;\n }\n }\n },\n { threshold: 0, rootMargin: '0px' }\n );\n this.observer.observe(this.host.nativeElement);\n }\n\n private scheduleRun(): void {\n this.cancel();\n const d = this.delay();\n if (d > 0) {\n this.delayTimer = setTimeout(() => this.run(), d);\n } else {\n this.run();\n }\n }\n\n private run(): void {\n const start = this.direction() === 'down' ? this.to() : this.from();\n const end = this.direction() === 'down' ? this.from() : this.to();\n this.started.emit();\n if (this.easing() === 'spring') this.tweenSpring(start, end);\n else this.tweenEaseOut(start, end);\n }\n\n // Tweens\n\n private tweenEaseOut(start: number, target: number): void {\n const duration = Math.max(100, this.duration());\n const startTs = performance.now();\n const tick = (now: number): void => {\n const t = Math.min(1, (now - startTs) / duration);\n const v = start + (target - start) * easeOutCubic(t);\n this.value.set(v);\n if (t < 1) {\n this.rafId = requestAnimationFrame(tick);\n } else {\n this.completed.emit();\n }\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n /**\n * Critically-damped spring tween. Same formula as `motion/react`'s\n * `useSpring` with mass = 1:\n *\n * damping = 20 + 40 / duration\n * stiffness = 100 / duration\n *\n * We integrate `(spring force − damping force)` each frame until both\n * displacement and velocity fall below epsilon.\n */\n private tweenSpring(start: number, target: number): void {\n const duration = Math.max(0.05, this.duration());\n const damping = 20 + 40 / duration;\n const stiffness = 100 / duration;\n let current = start;\n let velocity = 0;\n let lastTs = 0;\n const epsilon = 0.001 * Math.max(1, Math.abs(target - start));\n\n const step = (ts: number): void => {\n const dt = lastTs === 0 ? 1 / 60 : Math.min(0.05, (ts - lastTs) / 1000);\n lastTs = ts;\n\n const displacement = current - target;\n const accel = -stiffness * displacement - damping * velocity;\n velocity += accel * dt;\n current += velocity * dt;\n this.value.set(current);\n\n if (Math.abs(current - target) < epsilon && Math.abs(velocity) < epsilon * 10) {\n this.value.set(target);\n this.completed.emit();\n return;\n }\n this.rafId = requestAnimationFrame(step);\n };\n this.rafId = requestAnimationFrame(step);\n }\n\n // Cleanup\n\n private cancel(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.rafId = null;\n if (this.delayTimer !== undefined) {\n clearTimeout(this.delayTimer);\n this.delayTimer = undefined;\n }\n }\n}\n\nexport type { WrCountUpEasing, WrCountUpTrigger, WrCountUpDirection } from './interfaces';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;AAAA;AACM,SAAU,YAAY,CAAC,CAAS,EAAA;AACpC,IAAA,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC/B;;ACHA;;;;;AAKG;AAwBH;;;;;;;;;;;;;;;;;;AAkBG;MAOU,SAAS,CAAA;;IAEX,KAAK,GAAG,KAAK,CAAC,QAAQ;8EAAU;;IAGhC,IAAI,GAAG,KAAK,CAAgB,UAAU;6EAAC;;IAGvC,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,UAAA,EAAA,8BAAA,EAAA,CAAA,EAC3B,SAAS,EAAE,CAAC,CAAU,KAAa,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAA,CAC9E;;IAGO,QAAQ,GAAG,KAAK,CAAC,CAAC,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,UAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,CAAC,CAAU,KAAa,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAA,CAAG;;IAGnG,MAAM,GAAG,KAAK,CAAS,EAAE;+EAAC;;IAG1B,MAAM,GAAG,KAAK,CAAS,EAAE;+EAAC;;IAG1B,QAAQ,GAAG,KAAK,CAAU,IAAI;iFAAC;;IAG/B,gBAAgB,GAAG,KAAK,CAAC,CAAC,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,kBAAA,EAAA,8BAAA,EAAA,CAAA,EACjC,SAAS,EAAE,CAAC,CAAU,KAAa,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAA,CAC1E;IAEe,OAAO,GAAG,MAAM,CAAS,CAAC;gFAAC;AAC3B,IAAA,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAC1B,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3D,KAAK,GAAkB,IAAI;;AAGhB,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;kFAAC;AAE1E;;;;;AAKG;IACgB,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAA,EAAG,IAAI,CAAC,MAAM,EAAE,CAAA,EAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA,EAAG,IAAI,CAAC,MAAM,EAAE,CAAA,CAAE;gFAAC;;AAGxF,IAAA,KAAK,GAAG,QAAQ,CAAkB,MAAK;;;AAGxD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE;AAC3B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE;QAC3B,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;;AAGvC,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC;QACrE,MAAM,SAAS,GAAG,eAAe,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;QACvD,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;QAEnD,MAAM,KAAK,GAAW,EAAE;AACxB,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE;AAC/B,YAAA,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;AACtB,YAAA,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;AACpB,YAAA,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;;;AAGtC,gBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC;gBAC9D,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;YACzC;iBAAO;gBACL,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,KAAK,GAAG,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;YAC1D;QACF;AACA,QAAA,OAAO,KAAK;IACd,CAAC;8EAAC;AAEF,IAAA,WAAA,GAAA;AACE,QAAA,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAEjD,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE;;;;;AAK3B,YAAA,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;AAC7C,YAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;AACnB,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;gBACxB;YACF;YACA,IAAI,CAAC,MAAM,EAAE;AACb,YAAA,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;AACjC,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC3B,YAAA,MAAM,IAAI,GAAG,CAAC,GAAW,KAAU;AACjC,gBAAA,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,OAAO,IAAI,GAAG,CAAC;;;;;;;gBAO5C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,KAAK,GAAG,CAAC,MAAM,GAAG,KAAK,IAAI,YAAY,CAAC,CAAC,CAAC;AACtE,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;gBACnB,IAAI,CAAC,GAAG,CAAC;AAAE,oBAAA,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC;;AAC9C,oBAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACxB,YAAA,CAAC;AACD,YAAA,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC;AAC1C,QAAA,CAAC,CAAC;IACJ;IAEQ,MAAM,GAAA;AACZ,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;AAAE,YAAA,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC;AACzD,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;IACnB;AAEQ,IAAA,MAAM,CAAC,CAAS,EAAA;QACtB,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE;AACxC,YAAA,qBAAqB,EAAE,IAAI,CAAC,QAAQ,EAAE;AACtC,YAAA,qBAAqB,EAAE,IAAI,CAAC,QAAQ,EAAE;AACtC,YAAA,oBAAoB,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC;AAClD,YAAA,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE;AAC7B,SAAA,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACd;AAEA;;;;AAIG;AACK,IAAA,eAAe,CAAC,IAAY,EAAE,MAAc,EAAE,WAAmB,EAAE,QAAgB,EAAA;;;;QAIzF,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAC3C,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC;QACtD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC;AAC1C,QAAA,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM;QACvD,MAAM,UAAU,GAAG,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AAC9B,QAAA,MAAM,GAAG,GAAG,OAAO,GAAG,KAAK;;;AAG3B,QAAA,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE;;;;;;QAM3C,IAAI,IAAI,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;AAClD,QAAA,OAAO,GAAG;IACZ;uGAtJW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAT,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,SAAS,wnCCtDtB,q9BAyBA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FD6Ba,SAAS,EAAA,UAAA,EAAA,CAAA;kBANrB,SAAS;+BACE,YAAY,EAAA,aAAA,EAEP,iBAAiB,CAAC,IAAI,QAC/B,EAAE,KAAK,EAAE,YAAY,EAAE,EAAA,QAAA,EAAA,q9BAAA,EAAA;;;AEpD/B;;;;;;;;;;AAUG;AAyBH;;;;;;;;;;;;;;;;;;;;;AAqBG;MAOU,SAAS,CAAA;;AAEX,IAAA,IAAI,GAAG,KAAK,CAAC,CAAC,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,MAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,EAAA,CAAG;;IAG1C,EAAE,GAAG,KAAK,CAAC,QAAQ;2EAAU;AAEtC;;;;;AAKG;AACM,IAAA,QAAQ,GAAG,KAAK,CAAC,IAAI,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,UAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,EAAA,CAAG;;AAGpD,IAAA,KAAK,GAAG,KAAK,CAAC,CAAC,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,OAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,EAAA,CAAG;;IAG3C,MAAM,GAAG,KAAK,CAAkB,UAAU;+EAAC;AAEpD;;;;;;;AAOG;IACM,OAAO,GAAG,KAAK,CAAmB,OAAO;gFAAC;;IAG1C,SAAS,GAAG,KAAK,CAAqB,IAAI;kFAAC;;IAG3C,QAAQ,GAAG,KAAK,CAAC,CAAC,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,UAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,CAAC,CAAU,KAAa,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAA,CAAG;;IAGnG,MAAM,GAAG,KAAK,CAAS,EAAE;+EAAC;;IAG1B,MAAM,GAAG,KAAK,CAAS,EAAE;+EAAC;;IAG1B,QAAQ,GAAG,KAAK,CAAU,IAAI;iFAAC;;IAG/B,OAAO,GAAG,MAAM,EAAQ;;IAGxB,SAAS,GAAG,MAAM,EAAQ;IAElB,KAAK,GAAG,MAAM,CAAS,CAAC;8EAAC;AACzB,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC;AAClD,IAAA,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAC1B,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAClD,IAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IAExC,KAAK,GAAkB,IAAI;AAC3B,IAAA,UAAU;IACV,QAAQ,GAAgC,IAAI;IAC5C,kBAAkB,GAAG,KAAK;AAEf,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAK;QAC3C,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE;AACxC,YAAA,qBAAqB,EAAE,IAAI,CAAC,QAAQ,EAAE;AACtC,YAAA,qBAAqB,EAAE,IAAI,CAAC,QAAQ,EAAE;AACtC,YAAA,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE;SAC7B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;kFAAC;AAEF,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;;;;;AAKnB,YAAA,MAAM,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YACnF;QACF;;QAGA,MAAM,CAAC,MAAK;YACV,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE;AACrE,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AACzB,QAAA,CAAC,CAAC;;;;QAKF,MAAM,CAAC,MAAK;;YAEV,IAAI,CAAC,EAAE,EAAE;YACT,IAAI,CAAC,IAAI,EAAE;YACX,IAAI,CAAC,SAAS,EAAE;YAChB,IAAI,CAAC,QAAQ,EAAE;YACf,IAAI,CAAC,MAAM,EAAE;YACb,IAAI,CAAC,KAAK,EAAE;YAEZ,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,kBAAkB;gBAAE;YAC9D,IAAI,CAAC,WAAW,EAAE;AACpB,QAAA,CAAC,CAAC;QAEF,eAAe,CAAC,MAAK;AACnB,YAAA,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,SAAS;gBAAE,IAAI,CAAC,oBAAoB,EAAE;AAC/D,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAK;YAC7B,IAAI,CAAC,MAAM,EAAE;;;;;AAKb,YAAA,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE;AAC3B,YAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;AACtB,QAAA,CAAC,CAAC;IACJ;;IAIQ,oBAAoB,GAAA;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAoB,CACtC,CAAC,OAAO,EAAE,GAAG,KAAI;AACf,YAAA,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE;gBACvB,IAAI,CAAC,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE;oBAChD,GAAG,CAAC,UAAU,EAAE;AAChB,oBAAA,IAAI,CAAC,kBAAkB,GAAG,IAAI;oBAC9B,IAAI,CAAC,WAAW,EAAE;oBAClB;gBACF;YACF;QACF,CAAC,EACD,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CACpC;QACD,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IAChD;IAEQ,WAAW,GAAA;QACjB,IAAI,CAAC,MAAM,EAAE;AACb,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE;AACtB,QAAA,IAAI,CAAC,GAAG,CAAC,EAAE;AACT,YAAA,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACnD;aAAO;YACL,IAAI,CAAC,GAAG,EAAE;QACZ;IACF;IAEQ,GAAG,GAAA;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE;QACnE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE;AACjE,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;AACnB,QAAA,IAAI,IAAI,CAAC,MAAM,EAAE,KAAK,QAAQ;AAAE,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC;;AACvD,YAAA,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC;IACpC;;IAIQ,YAAY,CAAC,KAAa,EAAE,MAAc,EAAA;AAChD,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;AAC/C,QAAA,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;AACjC,QAAA,MAAM,IAAI,GAAG,CAAC,GAAW,KAAU;AACjC,YAAA,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,OAAO,IAAI,QAAQ,CAAC;AACjD,YAAA,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,MAAM,GAAG,KAAK,IAAI,YAAY,CAAC,CAAC,CAAC;AACpD,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AACjB,YAAA,IAAI,CAAC,GAAG,CAAC,EAAE;AACT,gBAAA,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC;YAC1C;iBAAO;AACL,gBAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;YACvB;AACF,QAAA,CAAC;AACD,QAAA,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC;IAC1C;AAEA;;;;;;;;;AASG;IACK,WAAW,CAAC,KAAa,EAAE,MAAc,EAAA;AAC/C,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;AAChD,QAAA,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,QAAQ;AAClC,QAAA,MAAM,SAAS,GAAG,GAAG,GAAG,QAAQ;QAChC,IAAI,OAAO,GAAG,KAAK;QACnB,IAAI,QAAQ,GAAG,CAAC;QAChB,IAAI,MAAM,GAAG,CAAC;AACd,QAAA,MAAM,OAAO,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;AAE7D,QAAA,MAAM,IAAI,GAAG,CAAC,EAAU,KAAU;AAChC,YAAA,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,MAAM,IAAI,IAAI,CAAC;YACvE,MAAM,GAAG,EAAE;AAEX,YAAA,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM;YACrC,MAAM,KAAK,GAAG,CAAC,SAAS,GAAG,YAAY,GAAG,OAAO,GAAG,QAAQ;AAC5D,YAAA,QAAQ,IAAI,KAAK,GAAG,EAAE;AACtB,YAAA,OAAO,IAAI,QAAQ,GAAG,EAAE;AACxB,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;YAEvB,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,OAAO,GAAG,EAAE,EAAE;AAC7E,gBAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;AACtB,gBAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;gBACrB;YACF;AACA,YAAA,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC;AAC1C,QAAA,CAAC;AACD,QAAA,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC;IAC1C;;IAIQ,MAAM,GAAA;AACZ,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;AAAE,YAAA,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC;AACzD,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACjB,QAAA,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE;AACjC,YAAA,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC;AAC7B,YAAA,IAAI,CAAC,UAAU,GAAG,SAAS;QAC7B;IACF;uGA7NW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAT,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,SAAS,sgDAJV,CAAA,6CAAA,CAA+C,EAAA,QAAA,EAAA,IAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAI9C,SAAS,EAAA,UAAA,EAAA,CAAA;kBANrB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,aAAa;AACvB,oBAAA,QAAQ,EAAE,CAAA,6CAAA,CAA+C;oBACzD,aAAa,EAAE,iBAAiB,CAAC,IAAI;AACrC,oBAAA,IAAI,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE;AAC/B,iBAAA;;;AC9DD;;AAEG;;;;"}